mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 16:02:15 +00:00
fix(power): avoid redundant macOS display blocking
This commit is contained in:
@@ -49,13 +49,15 @@ function createPlatformAssertion() {
|
||||
function createService(
|
||||
blocker = createBlocker(),
|
||||
macosAssertion = createPlatformAssertion(),
|
||||
linuxAssertion = createPlatformAssertion()
|
||||
linuxAssertion = createPlatformAssertion(),
|
||||
platform: NodeJS.Platform = 'linux'
|
||||
): AgentAwakeService {
|
||||
return new AgentAwakeService({
|
||||
blocker,
|
||||
linuxAssertion,
|
||||
macosAssertion,
|
||||
now: () => 1_000,
|
||||
platform,
|
||||
powerMonitor: null,
|
||||
logger: {
|
||||
debug: vi.fn(),
|
||||
@@ -65,6 +67,18 @@ function createService(
|
||||
}
|
||||
|
||||
describe('AgentAwakeService platform assertions', () => {
|
||||
it('uses caffeinate without Electron display blocking on macOS', () => {
|
||||
const blocker = createBlocker()
|
||||
const macosAssertion = createPlatformAssertion()
|
||||
const service = createService(blocker, macosAssertion, createPlatformAssertion(), 'darwin')
|
||||
|
||||
service.setEnabled(true)
|
||||
service.setStatuses([workingStatus()])
|
||||
|
||||
expect(macosAssertion.start).toHaveBeenCalledTimes(1)
|
||||
expect(blocker.start).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('keeps Electron blocker active when macOS assertion start fails', () => {
|
||||
const blocker = createBlocker()
|
||||
const macosAssertion = createPlatformAssertion()
|
||||
@@ -72,7 +86,7 @@ describe('AgentAwakeService platform assertions', () => {
|
||||
macosAssertion.start.mockImplementation(() => {
|
||||
throw new Error('caffeinate failed')
|
||||
})
|
||||
const service = createService(blocker, macosAssertion, linuxAssertion)
|
||||
const service = createService(blocker, macosAssertion, linuxAssertion, 'darwin')
|
||||
|
||||
service.setEnabled(true)
|
||||
service.setStatuses([workingStatus()])
|
||||
@@ -85,6 +99,20 @@ describe('AgentAwakeService platform assertions', () => {
|
||||
expect(linuxAssertion.stop).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('drops the display-blocking fallback after caffeinate recovers', () => {
|
||||
const blocker = createBlocker()
|
||||
const macosAssertion = createPlatformAssertion()
|
||||
macosAssertion.start.mockImplementationOnce(() => false).mockImplementation(() => true)
|
||||
const service = createService(blocker, macosAssertion, createPlatformAssertion(), 'darwin')
|
||||
|
||||
service.setEnabled(true)
|
||||
service.setStatuses([workingStatus()])
|
||||
expect(blocker.start).toHaveBeenCalledWith('prevent-display-sleep')
|
||||
|
||||
service.setStatuses([{ ...workingStatus(), receivedAt: 1_001 }])
|
||||
expect(blocker.stop).toHaveBeenCalledWith(1)
|
||||
})
|
||||
|
||||
it('keeps Electron blocker active when Linux assertion start fails', () => {
|
||||
const blocker = createBlocker()
|
||||
const macosAssertion = createPlatformAssertion()
|
||||
|
||||
@@ -85,6 +85,7 @@ function createService(
|
||||
linuxAssertion,
|
||||
macosAssertion,
|
||||
now,
|
||||
platform: 'linux',
|
||||
powerMonitor,
|
||||
logger: {
|
||||
debug: vi.fn(),
|
||||
|
||||
@@ -23,7 +23,7 @@ type PowerSaveBlocker = {
|
||||
}
|
||||
|
||||
type PlatformAwakeAssertion = {
|
||||
start: (reason: string) => void
|
||||
start: (reason: string) => boolean | void
|
||||
stop: (reason: string) => void
|
||||
dispose: () => void
|
||||
}
|
||||
@@ -41,6 +41,7 @@ type AgentAwakeServiceOptions = {
|
||||
logger?: Logger
|
||||
macosAssertion?: PlatformAwakeAssertion
|
||||
now?: () => number
|
||||
platform?: NodeJS.Platform
|
||||
powerMonitor?: PowerMonitorEventSource | null
|
||||
}
|
||||
|
||||
@@ -55,6 +56,7 @@ export class AgentAwakeService {
|
||||
private readonly linuxAssertion: PlatformAwakeAssertion
|
||||
private readonly logger: Logger
|
||||
private readonly macosAssertion: PlatformAwakeAssertion
|
||||
private readonly platform: NodeJS.Platform
|
||||
private readonly now: () => number
|
||||
private readonly unsubscribeResume: (() => void) | null
|
||||
|
||||
@@ -78,6 +80,7 @@ export class AgentAwakeService {
|
||||
now: this.now,
|
||||
onUnexpectedFailure: (reason) => this.refresh(reason)
|
||||
})
|
||||
this.platform = options.platform ?? process.platform
|
||||
const resumeSource = options.powerMonitor === undefined ? powerMonitor : options.powerMonitor
|
||||
if (resumeSource) {
|
||||
const onResume = () => this.refresh('power-resume')
|
||||
@@ -132,8 +135,12 @@ export class AgentAwakeService {
|
||||
const runningStatusCount = this.getEligibleRunningStatusCount()
|
||||
const shouldBlock = this.mode === 'on' || (this.mode === 'auto' && runningStatusCount > 0)
|
||||
if (shouldBlock) {
|
||||
this.startBlocker(reason, runningStatusCount)
|
||||
this.startMacosAssertion(reason)
|
||||
const macosAssertionActive = this.startMacosAssertion(reason)
|
||||
if (this.platform !== 'darwin' || !macosAssertionActive) {
|
||||
this.startBlocker(reason, runningStatusCount)
|
||||
} else {
|
||||
this.stopBlocker('macos-assertion-active', runningStatusCount)
|
||||
}
|
||||
this.startLinuxAssertion(reason)
|
||||
} else {
|
||||
this.stopBlocker(reason, runningStatusCount)
|
||||
@@ -229,15 +236,16 @@ export class AgentAwakeService {
|
||||
}
|
||||
}
|
||||
|
||||
private startMacosAssertion(reason: string): void {
|
||||
private startMacosAssertion(reason: string): boolean {
|
||||
try {
|
||||
this.macosAssertion.start(reason)
|
||||
return this.macosAssertion.start(reason) !== false
|
||||
} catch (err) {
|
||||
this.logger.warn('[agent-awake] failed to start macOS system sleep assertion', {
|
||||
reason,
|
||||
mode: this.mode,
|
||||
error: err
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,13 +53,16 @@ export class MacosSystemSleepAssertion {
|
||||
this.spawn = options.spawn ?? nodeSpawn
|
||||
}
|
||||
|
||||
start(reason: string): void {
|
||||
if (this.platform !== 'darwin' || this.child) {
|
||||
return
|
||||
start(reason: string): boolean {
|
||||
if (this.platform !== 'darwin') {
|
||||
return false
|
||||
}
|
||||
if (this.child) {
|
||||
return true
|
||||
}
|
||||
if (this.retryNotBefore !== null && this.now() < this.retryNotBefore) {
|
||||
this.scheduleRetry()
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
let child: CaffeinateProcess
|
||||
@@ -70,7 +73,7 @@ export class MacosSystemSleepAssertion {
|
||||
})
|
||||
} catch (error) {
|
||||
this.handleFailure('spawn-error', reason, error)
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
this.child = child
|
||||
@@ -91,6 +94,7 @@ export class MacosSystemSleepAssertion {
|
||||
child.on('exit', onExit)
|
||||
this.resetRetrySuppression()
|
||||
this.resetFailureStreak()
|
||||
return true
|
||||
}
|
||||
|
||||
stop(_reason: string): void {
|
||||
|
||||
Reference in New Issue
Block a user