@@ -7,6 +7,7 @@ import { KnexAdapter } from '../src/drivers/knex_adapter.js'
77import { QueueSchemaService } from '../src/services/queue_schema.js'
88import { registerDriverTestSuite } from './_utils/register_driver_test_suite.js'
99import { withRedisWriteSpy } from './_utils/with_redis_write_spy.js'
10+ import { withKnexQuerySpy } from './_utils/with_knex_query_spy.js'
1011
1112const KEY_PREFIX = 'boringnode::queue::test::'
1213
@@ -146,6 +147,67 @@ test.group('Adapter | Knex (SQLite)', (group) => {
146147 return adapter
147148 } ,
148149 } )
150+
151+ test ( 'listSchedules should execute a single SQL query in Knex adapter' , async ( { assert } ) => {
152+ const knexAdapter = new KnexAdapter ( { connection } )
153+
154+ for ( let i = 0 ; i < 20 ; i ++ ) {
155+ await knexAdapter . upsertSchedule ( {
156+ id : `knex-list-${ i } ` ,
157+ name : 'KnexPerfJob' ,
158+ payload : { i } ,
159+ everyMs : 60_000 ,
160+ timezone : 'UTC' ,
161+ } )
162+ }
163+
164+ const { result : schedules , queries } = await withKnexQuerySpy ( {
165+ connection,
166+ run : ( ) => knexAdapter . listSchedules ( ) ,
167+ } )
168+ assert . lengthOf ( schedules , 20 )
169+
170+ const scheduleSelectQueries = queries . filter (
171+ ( sql ) => sql . includes ( 'select' ) && sql . includes ( 'queue_schedules' )
172+ )
173+
174+ assert . lengthOf (
175+ scheduleSelectQueries ,
176+ 1 ,
177+ `Expected a single schedule SELECT query, got ${ scheduleSelectQueries . length } `
178+ )
179+ } )
180+
181+ test ( 'deleteSchedule should execute a single SQL query in Knex adapter' , async ( { assert } ) => {
182+ const knexAdapter = new KnexAdapter ( { connection } )
183+ const id = 'knex-delete-atomicity'
184+
185+ await knexAdapter . upsertSchedule ( {
186+ id,
187+ name : 'KnexDeleteJob' ,
188+ payload : { } ,
189+ everyMs : 60_000 ,
190+ timezone : 'UTC' ,
191+ } )
192+
193+ const { queries } = await withKnexQuerySpy ( {
194+ connection,
195+ run : ( ) => knexAdapter . deleteSchedule ( id ) ,
196+ } )
197+
198+ const schedule = await knexAdapter . getSchedule ( id )
199+ assert . isNull ( schedule )
200+
201+ const scheduleDeleteQueries = queries . filter (
202+ ( sql ) => sql . includes ( 'delete' ) && sql . includes ( 'queue_schedules' )
203+ )
204+
205+ assert . lengthOf (
206+ scheduleDeleteQueries ,
207+ 1 ,
208+ `Expected a single schedule DELETE query, got ${ scheduleDeleteQueries . length } `
209+ )
210+ } )
149211} )
150212
151213test . group ( 'Adapter | Knex (PostgreSQL)' , ( group ) => {
@@ -192,4 +254,69 @@ test.group('Adapter | Knex (PostgreSQL)', (group) => {
192254 return adapter
193255 } ,
194256 } )
257+
258+ test ( 'listSchedules should execute a single SQL query in Knex PostgreSQL adapter' , async ( {
259+ assert,
260+ } ) => {
261+ const knexAdapter = new KnexAdapter ( { connection, tableName, schedulesTableName } )
262+
263+ for ( let i = 0 ; i < 20 ; i ++ ) {
264+ await knexAdapter . upsertSchedule ( {
265+ id : `pg-list-${ i } ` ,
266+ name : 'PgPerfJob' ,
267+ payload : { i } ,
268+ everyMs : 60_000 ,
269+ timezone : 'UTC' ,
270+ } )
271+ }
272+
273+ const { result : schedules , queries } = await withKnexQuerySpy ( {
274+ connection,
275+ run : ( ) => knexAdapter . listSchedules ( ) ,
276+ } )
277+ assert . lengthOf ( schedules , 20 )
278+
279+ const scheduleSelectQueries = queries . filter (
280+ ( sql ) => sql . includes ( 'select' ) && sql . includes ( schedulesTableName )
281+ )
282+
283+ assert . lengthOf (
284+ scheduleSelectQueries ,
285+ 1 ,
286+ `Expected a single schedule SELECT query, got ${ scheduleSelectQueries . length } `
287+ )
288+ } )
289+
290+ test ( 'deleteSchedule should execute a single SQL query in Knex PostgreSQL adapter' , async ( {
291+ assert,
292+ } ) => {
293+ const knexAdapter = new KnexAdapter ( { connection, tableName, schedulesTableName } )
294+ const id = 'pg-delete-atomicity'
295+
296+ await knexAdapter . upsertSchedule ( {
297+ id,
298+ name : 'PgDeleteJob' ,
299+ payload : { } ,
300+ everyMs : 60_000 ,
301+ timezone : 'UTC' ,
302+ } )
303+
304+ const { queries } = await withKnexQuerySpy ( {
305+ connection,
306+ run : ( ) => knexAdapter . deleteSchedule ( id ) ,
307+ } )
308+
309+ const schedule = await knexAdapter . getSchedule ( id )
310+ assert . isNull ( schedule )
311+
312+ const scheduleDeleteQueries = queries . filter (
313+ ( sql ) => sql . includes ( 'delete' ) && sql . includes ( schedulesTableName )
314+ )
315+
316+ assert . lengthOf (
317+ scheduleDeleteQueries ,
318+ 1 ,
319+ `Expected a single schedule DELETE query, got ${ scheduleDeleteQueries . length } `
320+ )
321+ } )
195322} )
0 commit comments