Skip to content

Commit ae6b23d

Browse files
committed
Fix DB provider orphan reservation locking
1 parent ce43ca1 commit ae6b23d

2 files changed

Lines changed: 45 additions & 0 deletions

File tree

models/Providers/DBProvider.cfc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,15 @@ component accessors="true" extends="AbstractQueueProvider" {
498498
"<=",
499499
variables.getCurrentUnixTimestamp()
500500
);
501+
} )
502+
.orWhere( ( q2 ) => {
503+
q2.whereNotNull( "reservedBy" )
504+
.whereNull( "reservedDate" )
505+
.where(
506+
"availableDate",
507+
"<=",
508+
variables.getCurrentUnixTimestamp()
509+
);
501510
} );
502511
} )
503512
.update(

tests/specs/integration/Providers/DBProviderTimeoutWatcherSpec.cfc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)