@@ -19,7 +19,7 @@ jest.mock('../actions/utils', () => ({
1919
2020describe ( 'AdminAPI Optimized Tests' , ( ) => {
2121 let adminAPI ;
22- const context = { logger : { info : jest . fn ( ) , error : jest . fn ( ) } } ;
22+ const context = { logger : { info : jest . fn ( ) , error : jest . fn ( ) , debug : jest . fn ( ) } } ;
2323
2424 beforeEach ( ( ) => {
2525 adminAPI = new AdminAPI (
@@ -44,17 +44,20 @@ describe('AdminAPI Optimized Tests', () => {
4444 } ) ;
4545
4646 test ( 'should add record to previewQueue on previewAndPublish' , async ( ) => {
47- const record = { path : '/test' } ;
48- adminAPI . previewAndPublish ( record ) ;
49- expect ( adminAPI . previewQueue ) . toHaveLength ( 1 ) ;
47+ const records = [ { path : '/test' } ] ;
48+ adminAPI . previewAndPublish ( records , null , 1 ) ;
49+ // Backpressure resolves immediately when pending < MAX_PENDING_JOBS; then the batch is pushed. Allow microtasks to run.
50+ await Promise . resolve ( ) ;
5051 await Promise . resolve ( ) ;
52+ expect ( adminAPI . previewQueue ) . toHaveLength ( 1 ) ;
5153 } ) ;
5254
5355 test ( 'should add record to unpublishQueue on unpublishAndDelete' , async ( ) => {
54- const record = { path : '/test' } ;
55- adminAPI . unpublishAndDelete ( record ) ;
56- expect ( adminAPI . unpublishQueue ) . toHaveLength ( 1 ) ;
56+ const records = [ { path : '/test' } ] ;
57+ adminAPI . unpublishAndDelete ( records , null , 1 ) ;
5758 await Promise . resolve ( ) ;
59+ await Promise . resolve ( ) ;
60+ expect ( adminAPI . unpublishQueue ) . toHaveLength ( 1 ) ;
5861 } ) ;
5962
6063 test ( 'should start processing queues' , async ( ) => {
@@ -114,4 +117,52 @@ describe('AdminAPI Optimized Tests', () => {
114117 adminAPI . processQueues ( ) ;
115118 expect ( context . logger . info ) . toHaveBeenCalledWith ( 'Queues: preview=0, publish=0, unpublish live=0, unpublish preview=1, inflight=0, in queue=0' ) ;
116119 } ) ;
120+
121+ describe ( 'Qatar / bulk job serialization and rate limiting (409/429 fix)' , ( ) => {
122+ test ( 'getPendingCount returns queues + inflight' , ( ) => {
123+ adminAPI . previewQueue . push ( { records : [ ] , locale : null , batchNumber : 1 , resolve : jest . fn ( ) } ) ;
124+ adminAPI . publishQueue . push ( { records : [ ] , locale : null , batchNumber : 2 , resolve : jest . fn ( ) } ) ;
125+ expect ( adminAPI . getPendingCount ( ) ) . toBe ( 2 ) ;
126+ } ) ;
127+
128+ test ( 'MAX_PENDING_JOBS is 20' , ( ) => {
129+ expect ( adminAPI . MAX_PENDING_JOBS ) . toBe ( 20 ) ;
130+ } ) ;
131+
132+ test ( 'JOB_STATUS_POLL_INTERVAL_MS is 5000' , ( ) => {
133+ expect ( adminAPI . JOB_STATUS_POLL_INTERVAL_MS ) . toBe ( 5000 ) ;
134+ } ) ;
135+
136+ test ( 'previewAndPublish waits when pending >= MAX_PENDING_JOBS (backpressure)' , async ( ) => {
137+ // Fill up to MAX_PENDING_JOBS pending (all in queues; no inflight so we never resolve backpressure from completion)
138+ for ( let i = 0 ; i < adminAPI . MAX_PENDING_JOBS ; i ++ ) {
139+ adminAPI . previewQueue . push ( {
140+ records : [ { path : `/p/${ i } ` } ] ,
141+ locale : null ,
142+ batchNumber : i + 1 ,
143+ resolve : jest . fn ( ) ,
144+ } ) ;
145+ }
146+ expect ( adminAPI . getPendingCount ( ) ) . toBe ( adminAPI . MAX_PENDING_JOBS ) ;
147+
148+ adminAPI . previewAndPublish ( [ { path : '/extra' } ] , null , 999 ) ;
149+ await Promise . resolve ( ) ;
150+ await Promise . resolve ( ) ;
151+ // Should not have added the extra batch yet (still waiting for backpressure)
152+ expect ( adminAPI . previewQueue ) . toHaveLength ( adminAPI . MAX_PENDING_JOBS ) ;
153+ expect ( adminAPI . previewQueue . every ( ( b ) => b . batchNumber !== 999 ) ) . toBe ( true ) ;
154+
155+ // Simulate one item leaving the queue so pending drops below MAX_PENDING_JOBS
156+ adminAPI . previewQueue . pop ( ) ;
157+ adminAPI . _resolveBackpressure ( ) ;
158+
159+ await Promise . resolve ( ) ;
160+ await Promise . resolve ( ) ;
161+ // Now the waiting batch should have been pushed
162+ expect ( adminAPI . getPendingCount ( ) ) . toBeLessThanOrEqual ( adminAPI . MAX_PENDING_JOBS ) ;
163+ expect ( adminAPI . previewQueue ) . toContainEqual (
164+ expect . objectContaining ( { batchNumber : 999 } ) ,
165+ ) ;
166+ } ) ;
167+ } ) ;
117168} ) ;
0 commit comments