11const mockDispatchReview = jest . fn ( ) ;
2+ const mockGetReviewStatus = jest . fn ( ) ;
23const mockGetAgentConfigForOwner = jest . fn ( ) ;
34const mockPrepareReviewPayload = jest . fn ( ) ;
45
56jest . mock ( '@/lib/code-reviews/client/code-review-worker-client' , ( ) => ( {
67 codeReviewWorkerClient : {
78 dispatchReview : ( ...args : unknown [ ] ) => mockDispatchReview ( ...args ) ,
9+ getReviewStatus : ( ...args : unknown [ ] ) => mockGetReviewStatus ( ...args ) ,
810 } ,
911} ) ) ;
1012
@@ -58,6 +60,7 @@ describe('tryDispatchPendingReviews', () => {
5860
5961 beforeEach ( ( ) => {
6062 mockDispatchReview . mockResolvedValue ( undefined ) ;
63+ mockGetReviewStatus . mockResolvedValue ( null ) ;
6164 mockGetAgentConfigForOwner . mockResolvedValue ( { id : 'test-agent-config' , config : { } } ) ;
6265 mockPrepareReviewPayload . mockImplementation ( ( params : { reviewId : string } ) => ( {
6366 reviewId : params . reviewId ,
@@ -69,6 +72,7 @@ describe('tryDispatchPendingReviews', () => {
6972 . delete ( cloud_agent_code_reviews )
7073 . where ( eq ( cloud_agent_code_reviews . repo_full_name , REPO ) ) ;
7174 mockDispatchReview . mockReset ( ) ;
75+ mockGetReviewStatus . mockReset ( ) ;
7276 mockGetAgentConfigForOwner . mockReset ( ) ;
7377 mockPrepareReviewPayload . mockReset ( ) ;
7478 } ) ;
@@ -462,4 +466,130 @@ describe('tryDispatchPendingReviews', () => {
462466 expect . objectContaining ( { reviewId : staleQueuedReview . id } )
463467 ) ;
464468 } ) ;
469+
470+ it ( 'keeps a dispatch timeout claimed when the Worker status probe finds queued DO state' , async ( ) => {
471+ const recentTimestamp = minutesAgo ( 1 ) ;
472+ const owner = { type : 'user' , id : testUser . id } satisfies ReviewOwner ;
473+ await setTestUserBalance ( DEFAULT_TIER_BALANCE_MICRODOLLARS ) ;
474+ mockDispatchReview . mockRejectedValue ( new Error ( 'Request timeout after 10000ms' ) ) ;
475+ mockGetReviewStatus . mockResolvedValue ( { reviewId : 'unused' , status : 'queued' } ) ;
476+
477+ const [ review ] = await db
478+ . insert ( cloud_agent_code_reviews )
479+ . values (
480+ reviewValues ( {
481+ owner,
482+ status : 'pending' ,
483+ createdAt : recentTimestamp ,
484+ updatedAt : recentTimestamp ,
485+ } )
486+ )
487+ . returning ( { id : cloud_agent_code_reviews . id } ) ;
488+
489+ if ( ! review ) {
490+ throw new Error ( 'Expected review to be inserted' ) ;
491+ }
492+
493+ const result = await tryDispatchPendingReviews ( {
494+ type : 'user' ,
495+ id : testUser . id ,
496+ userId : testUser . id ,
497+ } ) ;
498+
499+ const storedReview = await db . query . cloud_agent_code_reviews . findFirst ( {
500+ where : eq ( cloud_agent_code_reviews . id , review . id ) ,
501+ } ) ;
502+
503+ expect ( result ) . toEqual ( {
504+ dispatched : 1 ,
505+ pending : 0 ,
506+ activeCount : 1 ,
507+ } ) ;
508+ expect ( mockGetReviewStatus ) . toHaveBeenCalledWith ( review . id ) ;
509+ expect ( storedReview ?. status ) . toBe ( 'queued' ) ;
510+ } ) ;
511+
512+ it ( 'releases a dispatch timeout claim when the Worker status probe finds no DO state' , async ( ) => {
513+ const recentTimestamp = minutesAgo ( 1 ) ;
514+ const owner = { type : 'user' , id : testUser . id } satisfies ReviewOwner ;
515+ await setTestUserBalance ( DEFAULT_TIER_BALANCE_MICRODOLLARS ) ;
516+ mockDispatchReview . mockRejectedValue ( new Error ( 'Request timeout after 10000ms' ) ) ;
517+ mockGetReviewStatus . mockResolvedValue ( null ) ;
518+
519+ const [ review ] = await db
520+ . insert ( cloud_agent_code_reviews )
521+ . values (
522+ reviewValues ( {
523+ owner,
524+ status : 'pending' ,
525+ createdAt : recentTimestamp ,
526+ updatedAt : recentTimestamp ,
527+ } )
528+ )
529+ . returning ( { id : cloud_agent_code_reviews . id } ) ;
530+
531+ if ( ! review ) {
532+ throw new Error ( 'Expected review to be inserted' ) ;
533+ }
534+
535+ const result = await tryDispatchPendingReviews ( {
536+ type : 'user' ,
537+ id : testUser . id ,
538+ userId : testUser . id ,
539+ } ) ;
540+
541+ const storedReview = await db . query . cloud_agent_code_reviews . findFirst ( {
542+ where : eq ( cloud_agent_code_reviews . id , review . id ) ,
543+ } ) ;
544+
545+ expect ( result ) . toEqual ( {
546+ dispatched : 0 ,
547+ pending : 1 ,
548+ activeCount : 0 ,
549+ } ) ;
550+ expect ( mockGetReviewStatus ) . toHaveBeenCalledWith ( review . id ) ;
551+ expect ( storedReview ?. status ) . toBe ( 'pending' ) ;
552+ } ) ;
553+
554+ it ( 'keeps a dispatch timeout claim when the Worker status probe also fails' , async ( ) => {
555+ const recentTimestamp = minutesAgo ( 1 ) ;
556+ const owner = { type : 'user' , id : testUser . id } satisfies ReviewOwner ;
557+ await setTestUserBalance ( DEFAULT_TIER_BALANCE_MICRODOLLARS ) ;
558+ mockDispatchReview . mockRejectedValue ( new Error ( 'Request timeout after 10000ms' ) ) ;
559+ mockGetReviewStatus . mockRejectedValue ( new Error ( 'status probe timeout' ) ) ;
560+
561+ const [ review ] = await db
562+ . insert ( cloud_agent_code_reviews )
563+ . values (
564+ reviewValues ( {
565+ owner,
566+ status : 'pending' ,
567+ createdAt : recentTimestamp ,
568+ updatedAt : recentTimestamp ,
569+ } )
570+ )
571+ . returning ( { id : cloud_agent_code_reviews . id } ) ;
572+
573+ if ( ! review ) {
574+ throw new Error ( 'Expected review to be inserted' ) ;
575+ }
576+
577+ const result = await tryDispatchPendingReviews ( {
578+ type : 'user' ,
579+ id : testUser . id ,
580+ userId : testUser . id ,
581+ } ) ;
582+
583+ const storedReview = await db . query . cloud_agent_code_reviews . findFirst ( {
584+ where : eq ( cloud_agent_code_reviews . id , review . id ) ,
585+ } ) ;
586+
587+ expect ( result ) . toEqual ( {
588+ dispatched : 0 ,
589+ pending : 1 ,
590+ activeCount : 0 ,
591+ } ) ;
592+ expect ( mockGetReviewStatus ) . toHaveBeenCalledWith ( review . id ) ;
593+ expect ( storedReview ?. status ) . toBe ( 'queued' ) ;
594+ } ) ;
465595} ) ;
0 commit comments