@@ -5,6 +5,7 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" {
55 beforeEach ( function () {
66 variables .provider = getWireBox ().getInstance ( " DBProvider@cbq" ).setProperties ( {} );
77 makePublic ( variables .provider , " fetchPotentiallyOpenRecords" );
8+ makePublic ( variables .provider , " tryToLockRecords" );
89 variables .pool = makeWorkerPool ( variables .provider );
910 // clean up any leftover test records
1011 variables .provider
@@ -89,6 +90,41 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" {
8990 " A job past the pool timeout but still within its job-specific timeout should not be re-grabbed"
9091 );
9192 } );
93+
94+ it ( " locks an orphaned reservation that was claimed without a reserved date" , function () {
95+ var job = getWireBox ().getInstance ( " SendWelcomeEmailJob" );
96+ variables .provider .push ( " default" , job );
97+
98+ var deadWorkerUUID = createUUID ();
99+ var now = javacast ( " long" , getTickCount () / 1000 );
100+ variables .provider
101+ .newQuery ()
102+ .table ( " cbq_jobs" )
103+ .update ( {
104+ " reservedBy" : deadWorkerUUID ,
105+ " reservedDate" : {
106+ " value" : " " ,
107+ " null" : true ,
108+ " nulls" : true
109+ },
110+ " availableDate" : now - 1
111+ } );
112+
113+ var ids = variables .provider .fetchPotentiallyOpenRecords ( capacity = 10 , pool = variables .pool );
114+ variables .provider .tryToLockRecords ( ids , variables .pool );
115+
116+ var row = variables .provider
117+ .newQuery ()
118+ .from ( " cbq_jobs" )
119+ .first ();
120+
121+ expect ( ids ).toHaveLength ( 1 , " The orphaned reservation should be selected for reclaiming" );
122+ expect ( row .reservedBy ).toBe (
123+ variables .pool .getUniqueId (),
124+ " The live worker pool should be able to claim the orphaned reservation"
125+ );
126+ expect ( row .reservedDate ?: " " ).toBe ( " " , " The job should remain pending reservation processing" );
127+ } );
92128 } );
93129 }
94130
0 commit comments