@@ -200,18 +200,19 @@ describe('Farm', () => {
200200 workerReply ( 0 , null , 17 ) ;
201201 await p0 ;
202202
203- // Note that the stickiness is not created by the method name or the arguments
204- // it is solely controlled by the provided "computeWorkerKey" method, which in
205- // the test example always returns the same key, so all calls should be
206- // redirected to worker 1 (which is the one that resolved the first call).
203+ // Note that the stickiness is not created by the method name or the
204+ // arguments it is solely controlled by the provided "computeWorkerKey"
205+ // method, which in the test example always returns the same key, so all
206+ // calls should be redirected to worker 1 (which is the one that resolved
207+ // the first call).
207208 const p1 = farm . doWork ( 'foo' , 'bar' ) ;
208209 workerReply ( 1 , null , 17 ) ;
209210 await p1 ;
210211
211- // The first time, a call with a "1234567890abcdef" hash had never been done
212- // earlier ("foo" call), so it got queued to all workers. Later, since the one
213- // that resolved the call was the one in position 1, all subsequent calls are
214- // only redirected to that worker.
212+ // The first time, a call with a "1234567890abcdef" hash had never been
213+ // done earlier ("foo" call), so it got queued to all workers. Later, since
214+ // the one that resolved the call was the one in position 1, all subsequent
215+ // calls are only redirected to that worker.
215216 expect ( callback ) . toHaveBeenCalledTimes ( 2 ) ; // Only "foo".
216217 expect ( callback ) . toHaveBeenNthCalledWith (
217218 1 ,
@@ -248,11 +249,11 @@ describe('Farm', () => {
248249 workerReply ( 1 , null , 17 ) ;
249250 await p1 ;
250251
251- // Both requests are send to the same worker
252- // The first time, a call with a "1234567890abcdef" hash had never been done
253- // earlier ("foo" call), so it got queued to all workers. Later, since the one
254- // that resolved the call was the one in position 1, all subsequent calls are
255- // only redirected to that worker.
252+ // Both requests are send to the same worker. The first time, a call with
253+ // a "1234567890abcdef" hash had never been done earlier ("foo" call), so
254+ // it got queued to all workers. Later, since the one that resolved the
255+ // call was the one in position 1, all subsequent calls are only redirected
256+ // to that worker.
256257 expect ( callback ) . toHaveBeenCalledTimes ( 2 ) ;
257258 expect ( callback ) . toHaveBeenNthCalledWith (
258259 1 ,
@@ -269,4 +270,67 @@ describe('Farm', () => {
269270 expect . any ( Function ) ,
270271 ) ;
271272 } ) ;
273+
274+ it ( 'checks that locking works, and jobs are never lost' , async ( ) => {
275+ const hash = jest
276+ . fn ( )
277+ // This will go to both queues, but picked by the first worker.
278+ . mockReturnValueOnce ( 0 )
279+ // This will go to both queues too, but picked by the second worker.
280+ . mockReturnValueOnce ( 1 )
281+ // This will go to worker 0, now only assigned to it.
282+ . mockReturnValueOnce ( 0 )
283+ // This will go to worker 1, now only assigned to it.
284+ . mockReturnValueOnce ( 1 )
285+ // This will go to both queues too, but will wait, since workers are busy.
286+ . mockReturnValueOnce ( 2 )
287+ // This will only go to the first queue.
288+ . mockReturnValueOnce ( 0 )
289+ // This will be gone if the queue implementation is wrong.
290+ . mockReturnValueOnce ( 0 )
291+ // Push onto the second queue; potentially wiping the earlier job.
292+ . mockReturnValueOnce ( 1 ) ;
293+
294+ const farm = new Farm ( 2 , callback , hash ) ;
295+
296+ // First and second jobs get resolved, so that their hash is sticked to
297+ // the right worker: worker assignment is performed when workers reply, not
298+ // when the call is made.
299+ const p0 = farm . doWork ( 'work-0' ) ;
300+ const p1 = farm . doWork ( 'work-1' ) ;
301+ workerReply ( 0 , null , 'response-0' ) ;
302+ await p0 ;
303+ workerReply ( 1 , null , 'response-1' ) ;
304+ await p1 ;
305+
306+ // Now we perform the rest of the calls (7 resolves before 5 and 6, since 4
307+ // is in both queues, and as soon as you resolve 4, 7 will be picked).
308+ const p2 = farm . doWork ( 'work-2' ) ;
309+ const p3 = farm . doWork ( 'work-3' ) ;
310+ const p4 = farm . doWork ( 'work-4' ) ;
311+ const p5 = farm . doWork ( 'work-5' ) ;
312+ const p6 = farm . doWork ( 'work-6' ) ;
313+ const p7 = farm . doWork ( 'work-7' ) ;
314+ workerReply ( 2 , null , 'response-2' ) ;
315+ await p2 ;
316+ workerReply ( 3 , null , 'response-3' ) ;
317+ await p3 ;
318+ workerReply ( 4 , null , 'response-4' ) ;
319+ await p4 ;
320+ workerReply ( 5 , null , 'response-7' ) ;
321+ await p7 ;
322+ workerReply ( 6 , null , 'response-5' ) ;
323+ await p5 ;
324+ workerReply ( 7 , null , 'response-6' ) ;
325+ await p6 ;
326+
327+ await expect ( p0 ) . resolves . toBe ( 'response-0' ) ;
328+ await expect ( p1 ) . resolves . toBe ( 'response-1' ) ;
329+ await expect ( p2 ) . resolves . toBe ( 'response-2' ) ;
330+ await expect ( p3 ) . resolves . toBe ( 'response-3' ) ;
331+ await expect ( p4 ) . resolves . toBe ( 'response-4' ) ;
332+ await expect ( p5 ) . resolves . toBe ( 'response-5' ) ;
333+ await expect ( p6 ) . resolves . toBe ( 'response-6' ) ;
334+ await expect ( p7 ) . resolves . toBe ( 'response-7' ) ;
335+ } ) ;
272336} ) ;
0 commit comments