@@ -38,6 +38,13 @@ class TestQueue extends Queue<TestJobs, DbJobRequest<any>> {
3838 }
3939}
4040
41+ class TestQueueWithLongPolling extends TestQueue {
42+ constructor ( options = { } ) {
43+ super ( options ) ;
44+ this . supportsLongPolling = true ;
45+ }
46+ }
47+
4148describe ( 'Queue' , ( ) => {
4249 let queue : TestQueue ;
4350
@@ -221,4 +228,110 @@ describe('Queue', () => {
221228 ) ;
222229 } ) ;
223230 } ) ;
231+
232+ describe ( 'polling behavior' , ( ) => {
233+ // Plugin to track polling times
234+ class PollTrackingPlugin {
235+ public pollTimes : number [ ] = [ ] ;
236+ public pollCount = 0 ;
237+
238+ async beforePoll ( ) : Promise < 'continue' | 'stop' > {
239+ this . pollTimes . push ( Date . now ( ) ) ;
240+ this . pollCount ++ ;
241+
242+ // Stop after a few polls to prevent infinite loop
243+ if ( this . pollCount >= 3 ) {
244+ return 'stop' ;
245+ }
246+ return 'continue' ;
247+ }
248+
249+ getTimeBetweenPolls ( index1 : number , index2 : number ) : number {
250+ if ( index1 >= this . pollTimes . length || index2 >= this . pollTimes . length ) {
251+ return - 1 ;
252+ }
253+ return this . pollTimes [ index2 ] ! - this . pollTimes [ index1 ] ! ;
254+ }
255+ }
256+
257+ it ( 'should sleep for at least 500ms when timeout is 0 (non-long-polling)' , async ( ) => {
258+ const plugin = new PollTrackingPlugin ( ) ;
259+ const queue = new TestQueue ( { plugins : [ plugin ] } ) ;
260+ queue . onJob ( 'test-job' , async ( ) => { } ) ;
261+
262+ // Run with repeat=true and timeout=0
263+ await queue . run ( true , 0 ) ;
264+
265+ // Check time between polls
266+ const timeBetweenPolls = plugin . getTimeBetweenPolls ( 0 , 1 ) ;
267+ expect ( timeBetweenPolls ) . toBeGreaterThanOrEqual ( 500 ) ;
268+ expect ( timeBetweenPolls ) . toBeLessThan ( 600 ) ; // Allow some margin
269+ } ) ;
270+
271+ it ( 'should sleep for at least 500ms when timeout < 0.5s (non-long-polling)' , async ( ) => {
272+ const plugin = new PollTrackingPlugin ( ) ;
273+ const queue = new TestQueue ( { plugins : [ plugin ] } ) ;
274+ queue . onJob ( 'test-job' , async ( ) => { } ) ;
275+
276+ // Run with timeout=0.2 (200ms)
277+ await queue . run ( true , 0.2 ) ;
278+
279+ // Should still sleep for 500ms, not 200ms
280+ const timeBetweenPolls = plugin . getTimeBetweenPolls ( 0 , 1 ) ;
281+ expect ( timeBetweenPolls ) . toBeGreaterThanOrEqual ( 500 ) ;
282+ expect ( timeBetweenPolls ) . toBeLessThan ( 600 ) ;
283+ } ) ;
284+
285+ it ( 'should use timeout value when > 0.5s (non-long-polling)' , async ( ) => {
286+ const plugin = new PollTrackingPlugin ( ) ;
287+ const queue = new TestQueue ( { plugins : [ plugin ] } ) ;
288+ queue . onJob ( 'test-job' , async ( ) => { } ) ;
289+
290+ // Run with timeout=2 (2 seconds)
291+ await queue . run ( true , 2 ) ;
292+
293+ // Should sleep for 2000ms
294+ const timeBetweenPolls = plugin . getTimeBetweenPolls ( 0 , 1 ) ;
295+ expect ( timeBetweenPolls ) . toBeGreaterThanOrEqual ( 2000 ) ;
296+ expect ( timeBetweenPolls ) . toBeLessThan ( 2100 ) ;
297+ } ) ;
298+
299+ it ( 'should not sleep when timeout is 0 (long-polling)' , async ( ) => {
300+ const plugin = new PollTrackingPlugin ( ) ;
301+ const queue = new TestQueueWithLongPolling ( { plugins : [ plugin ] } ) ;
302+ queue . onJob ( 'test-job' , async ( ) => { } ) ;
303+
304+ // Run with timeout=0
305+ await queue . run ( true , 0 ) ;
306+
307+ // With long polling and timeout=0, polls should be immediate
308+ const timeBetweenPolls = plugin . getTimeBetweenPolls ( 0 , 1 ) ;
309+ expect ( timeBetweenPolls ) . toBeLessThan ( 50 ) ; // Should be nearly instant
310+ } ) ;
311+
312+ it ( 'should use exact timeout value (long-polling)' , async ( ) => {
313+ const plugin = new PollTrackingPlugin ( ) ;
314+ const queue = new TestQueueWithLongPolling ( { plugins : [ plugin ] } ) ;
315+ queue . onJob ( 'test-job' , async ( ) => { } ) ;
316+
317+ // Run with timeout=0.2 (200ms)
318+ await queue . run ( true , 0.2 ) ;
319+
320+ // Should sleep for exactly 200ms
321+ const timeBetweenPolls = plugin . getTimeBetweenPolls ( 0 , 1 ) ;
322+ expect ( timeBetweenPolls ) . toBeGreaterThanOrEqual ( 200 ) ;
323+ expect ( timeBetweenPolls ) . toBeLessThan ( 250 ) ;
324+ } ) ;
325+
326+ it ( 'should not sleep in single run mode' , async ( ) => {
327+ const plugin = new PollTrackingPlugin ( ) ;
328+ const queue = new TestQueue ( { plugins : [ plugin ] } ) ;
329+
330+ // Run with repeat=false
331+ await queue . run ( false , 0 ) ;
332+
333+ // Should only poll once
334+ expect ( plugin . pollCount ) . toBe ( 1 ) ;
335+ } ) ;
336+ } ) ;
224337} ) ;
0 commit comments