1- import { afterEach , beforeEach , describe , expect , it } from 'bun:test'
1+ import {
2+ afterEach ,
3+ beforeEach ,
4+ describe ,
5+ expect ,
6+ it ,
7+ mock ,
8+ spyOn ,
9+ } from 'bun:test'
210import { mkdtempSync , rmSync } from 'node:fs'
311import { tmpdir } from 'node:os'
412import { join } from 'node:path'
@@ -7,12 +15,21 @@ import type { AccountMetadataV3 } from '@cortexkit/antigravity-auth-core'
715
816import {
917 DEFAULT_SIDEBAR_STATE ,
18+ drainSidebarWrites ,
1019 readSidebarState ,
1120 SIDEBAR_STATE_ENV ,
1221 SIDEBAR_STATE_VERSION ,
1322 type SidebarStateV1 ,
23+ setSidebarMergeHooks ,
1424} from '../sidebar-state'
15- import { classifyQuotaGroup , pushSidebarQuotaSnapshot } from './quota.ts'
25+ import { registerQuotaManagerProducer } from './index.ts'
26+ import { createPluginLifecycle } from './lifecycle.ts'
27+ import {
28+ classifyQuotaGroup ,
29+ createOpenCodeQuotaManager ,
30+ pushSidebarQuotaSnapshot ,
31+ } from './quota.ts'
32+ import type { PluginClient } from './types.ts'
1633
1734interface QuotaSnapshotAccount {
1835 index : number
@@ -154,4 +171,98 @@ describe('pushSidebarQuotaSnapshot', () => {
154171 const state = read ( )
155172 expect ( state . accounts ) . toEqual ( [ ] )
156173 } )
174+
175+ it ( 'fences the real quota wrapper sidebar enqueue before the lifecycle drain' , async ( ) => {
176+ const events : string [ ] = [ ]
177+ let releaseFetch ! : ( ) => void
178+ const fetchGate = new Promise < void > ( ( resolve ) => {
179+ releaseFetch = resolve
180+ } )
181+ let fetchStartedResolve ! : ( ) => void
182+ const fetchStarted = new Promise < void > ( ( resolve ) => {
183+ fetchStartedResolve = resolve
184+ } )
185+ const fetchSpy = spyOn ( globalThis , 'fetch' ) . mockImplementation (
186+ ( async ( ) =>
187+ new Response (
188+ JSON . stringify ( { access_token : 'access-token' , expires_in : 3600 } ) ,
189+ { status : 200 } ,
190+ ) ) as unknown as typeof fetch ,
191+ )
192+ const client = {
193+ auth : { set : mock ( async ( ) => { } ) } ,
194+ } as unknown as PluginClient
195+ const account : AccountMetadataV3 = {
196+ refreshToken : 'refresh-token' ,
197+ managedProjectId : 'managed-project' ,
198+ addedAt : 0 ,
199+ lastUsed : 0 ,
200+ }
201+ const manager = createOpenCodeQuotaManager ( client , 'google' , {
202+ getAccountsForSidebar : ( ) => [
203+ {
204+ index : 0 ,
205+ email : 'primary@example.test' ,
206+ cachedQuota : {
207+ claude : { remainingFraction : 0.42 , modelCount : 1 } ,
208+ } ,
209+ } ,
210+ ] ,
211+ fetchVia : async ( ) => {
212+ events . push ( 'fetch:start' )
213+ fetchStartedResolve ( )
214+ await fetchGate
215+ return new Response ( 'unavailable' , { status : 503 } )
216+ } ,
217+ } )
218+ const lifecycle = createPluginLifecycle ( {
219+ sessionRegistry : { clear : ( ) => { } } ,
220+ shutdownDiskSignatureCache : async ( ) => { } ,
221+ clearFetchState : ( ) => { } ,
222+ drainSidebarWrites : async ( ) => {
223+ events . push ( 'lifecycle:drain' )
224+ await drainSidebarWrites ( )
225+ events . push (
226+ readSidebarState ( stateFile ) . accounts . length === 1
227+ ? 'drain:sees-sidebar-write'
228+ : 'drain:misses-sidebar-write' ,
229+ )
230+ } ,
231+ } )
232+ registerQuotaManagerProducer ( lifecycle , manager )
233+ setSidebarMergeHooks ( {
234+ onStep : async ( step ) => {
235+ if ( step === 'await-lock' ) events . push ( 'sidebar:write-start' )
236+ } ,
237+ } )
238+
239+ const refresh = manager . refreshAccounts ( [ account ] , {
240+ indexFor : ( ) => 0 ,
241+ force : true ,
242+ } )
243+ await fetchStarted
244+ const dispose = lifecycle . dispose ( )
245+ releaseFetch ( )
246+
247+ try {
248+ await dispose
249+ await manager . refreshAccounts ( [ account ] , {
250+ indexFor : ( ) => 0 ,
251+ force : true ,
252+ } )
253+ await drainSidebarWrites ( )
254+ expect ( events ) . toEqual ( [
255+ 'fetch:start' ,
256+ 'fetch:start' ,
257+ 'sidebar:write-start' ,
258+ 'lifecycle:drain' ,
259+ 'drain:sees-sidebar-write' ,
260+ ] )
261+ } finally {
262+ await refresh
263+ await drainSidebarWrites ( )
264+ setSidebarMergeHooks ( null )
265+ fetchSpy . mockRestore ( )
266+ }
267+ } )
157268} )
0 commit comments