Skip to content

Commit 0b20373

Browse files
committed
fix(desktop): judge a lease refusal by whether the claim was confirmed when the renewal was sent
1 parent d79c626 commit 0b20373

2 files changed

Lines changed: 32 additions & 4 deletions

File tree

‎apps/sim/lib/mothership/tools/client/native-files.test.ts‎

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ describe('an import keeps its lease while it runs', () => {
167167
stopped: boolean
168168
renewalsReceived: number
169169
transient: number[]
170+
/** How long the server takes to answer the next renewal it receives. */
171+
nextAnswerDelayMs: number
170172
}
171173
let scanMs: number
172174
let finishUpload: () => void
@@ -176,7 +178,14 @@ describe('an import keeps its lease while it runs', () => {
176178

177179
beforeEach(() => {
178180
vi.useFakeTimers()
179-
server = { leaseUntil: 0, claimed: false, stopped: false, renewalsReceived: 0, transient: [] }
181+
server = {
182+
leaseUntil: 0,
183+
claimed: false,
184+
stopped: false,
185+
renewalsReceived: 0,
186+
transient: [],
187+
nextAnswerDelayMs: 0,
188+
}
180189
scanMs = 0
181190
mocks.invoke.mockImplementation(async (request: { operation: string }) => {
182191
if (request.operation !== 'manifest')
@@ -195,10 +204,14 @@ describe('an import keeps its lease while it runs', () => {
195204
mocks.json.mockImplementation(async (contract: unknown) => {
196205
if (contract !== renewDesktopToolLeaseContract) return { folder: { id: 'created-folder' } }
197206
server.renewalsReceived += 1
207+
const delayMs = server.nextAnswerDelayMs
208+
server.nextAnswerDelayMs = 0
198209
const transient = server.transient.shift()
210+
const refused = server.stopped || !server.claimed || !leaseLive()
211+
if (!transient && !refused) server.leaseUntil = Date.now() + LEASE_MS
212+
await sleep(delayMs)
199213
if (transient) return answer(transient)
200-
if (server.stopped || !server.claimed || !leaseLive()) return answer(410)
201-
server.leaseUntil = Date.now() + LEASE_MS
214+
if (refused) return answer(410)
202215
return { renewed: true }
203216
})
204217
})
@@ -220,6 +233,18 @@ describe('an import keeps its lease while it runs', () => {
220233
expect(leaseLive()).toBe(false)
221234
})
222235

236+
it('a refusal of a renewal sent before the claim does not stop it, however late it arrives', async () => {
237+
// The first renewal goes out before the desktop claims the call; its 410 arrives only after
238+
// the manifest confirmed the claim.
239+
server.nextAnswerDelayMs = 5_000
240+
scanMs = 1_000
241+
const run = executeNativeFileTool('tool', 'import_local_files')
242+
await vi.advanceTimersByTimeAsync(90_000)
243+
expect(leaseLive()).toBe(true)
244+
finishUpload()
245+
await run
246+
})
247+
223248
it('stops renewing once the server refuses the claimed call', async () => {
224249
const run = executeNativeFileTool('tool', 'import_local_files')
225250
await vi.advanceTimersByTimeAsync(1_000)

‎apps/sim/lib/mothership/tools/client/native-files.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,12 @@ function keepImportLeased(toolCallId: string): { claimed(): void; stop(): void }
123123
let stopped = false
124124
const renew = () => {
125125
if (stopped) return
126+
// Whether the claim was confirmed when this renewal was sent: a refusal of one sent before it
127+
// may arrive after, and says nothing about the running import.
128+
const sentAfterClaim = claimed
126129
requestJson(renewDesktopToolLeaseContract, { body: { toolCallId, chatView: true } }).catch(
127130
(error) => {
128-
if (claimed && error instanceof ApiClientError && error.status === 410) {
131+
if (sentAfterClaim && error instanceof ApiClientError && error.status === 410) {
129132
stop()
130133
return
131134
}

0 commit comments

Comments
 (0)