From e5881b781d9cca4ea300698b64077f3e5f84bde1 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Tue, 8 Sep 2026 06:38:18 -0600 Subject: [PATCH 1/3] perf(db): bind queue names and job payloads as text --- models/Providers/DBProvider.cfc | 10 ++- .../Providers/DBProviderPayloadSpec.cfc | 70 +++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 tests/specs/integration/Providers/DBProviderPayloadSpec.cfc diff --git a/models/Providers/DBProvider.cfc b/models/Providers/DBProvider.cfc index 18bdc7f..1d9d768 100644 --- a/models/Providers/DBProvider.cfc +++ b/models/Providers/DBProvider.cfc @@ -206,14 +206,20 @@ component accessors="true" extends="AbstractQueueProvider" { numeric attempts = 0 ) { var jobPayload = { - "queue" : arguments.queueName, + "queue" : { + "value" : arguments.queueName, + "cfsqltype" : "cf_sql_varchar" + }, "attempts" : { "value" : arguments.attempts, "sqltype" : "bigint" }, "availableDate" : getCurrentUnixTimestamp( arguments.delay ), "createdDate" : getCurrentUnixTimestamp(), - "payload" : serializeJSON( arguments.job.getMemento() ) + "payload" : { + "value" : serializeJSON( arguments.job.getMemento() ), + "cfsqltype" : "cf_sql_varchar" + } }; if ( variables.log.canDebug() ) { diff --git a/tests/specs/integration/Providers/DBProviderPayloadSpec.cfc b/tests/specs/integration/Providers/DBProviderPayloadSpec.cfc new file mode 100644 index 0000000..547a7d2 --- /dev/null +++ b/tests/specs/integration/Providers/DBProviderPayloadSpec.cfc @@ -0,0 +1,70 @@ +component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" { + + function run() { + describe( "DBProvider text payload persistence", function() { + beforeEach( function() { + variables.provider = getWireBox() + .buildInstance( getWireBox().getBinder().getMapping( "DBProvider@cbq" ) ) + .setProperties( {} ); + getWireBox().autowire( + target = variables.provider, + mapping = getWireBox().getBinder().getMapping( "DBProvider@cbq" ) + ); + variables.queue = "payload-#createUUID()#"; + } ); + afterEach( function() { + variables.provider + .newQuery() + .table( "cbq_jobs" ) + .where( "queue", variables.queue ) + .delete(); + } ); + it( "round trips long JSON text, literal escapes and nested values with bigint attempts", function() { + var properties = { + "text" : repeatString( "José with quotes, dates 2026-09-08 and 00123. ", 1000 ), + "quote" : chr( 34 ), + "slash" : chr( 92 ), + "line" : chr( 10 ), + "nested" : { + "empty" : "", + "values" : [ true, false, 1, "00123" ] + } + }; + var job = getInstance( "SendWelcomeEmailJob" ).setProperties( properties ); + var before = variables.provider.getCurrentUnixTimestamp(); + variables.provider.push( + queueName = variables.queue, + job = job, + delay = 17, + attempts = 2147483648 + ); + var after = variables.provider.getCurrentUnixTimestamp(); + var row = variables.provider + .newQuery() + .from( "cbq_jobs" ) + .where( "queue", variables.queue ) + .first(); + expect( row.queue ).toBe( variables.queue ); + expect( row.attempts ).toBe( 2147483648 ); + expect( row.createdDate >= before && row.createdDate <= after ).toBeTrue(); + expect( row.availableDate >= before + 17 && row.availableDate <= after + 17 ).toBeTrue(); + expect( deserializeJSON( row.payload ).properties ).toBe( properties ); + } ); + it( "preserves a numeric-looking queue name without normalizing its leading zeros", function() { + variables.queue = "000" & randRange( 100000000, 999999999 ); + variables.provider.push( + variables.queue, + getInstance( "SendWelcomeEmailJob" ), + 17 + ); + var row = variables.provider + .newQuery() + .from( "cbq_jobs" ) + .where( "queue", variables.queue ) + .first(); + expect( row.queue ).toBe( variables.queue ); + } ); + } ); + } + +} From a645322bb554eb81f4d6aa181d01b54d80673023 Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Tue, 8 Sep 2026 06:42:00 -0600 Subject: [PATCH 2/3] test(db): compare queue names as literal text --- tests/specs/integration/Providers/DBProviderPayloadSpec.cfc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/specs/integration/Providers/DBProviderPayloadSpec.cfc b/tests/specs/integration/Providers/DBProviderPayloadSpec.cfc index 547a7d2..4ee005d 100644 --- a/tests/specs/integration/Providers/DBProviderPayloadSpec.cfc +++ b/tests/specs/integration/Providers/DBProviderPayloadSpec.cfc @@ -44,7 +44,7 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" { .from( "cbq_jobs" ) .where( "queue", variables.queue ) .first(); - expect( row.queue ).toBe( variables.queue ); + expect( compare( row.queue, variables.queue ) ).toBe( 0 ); expect( row.attempts ).toBe( 2147483648 ); expect( row.createdDate >= before && row.createdDate <= after ).toBeTrue(); expect( row.availableDate >= before + 17 && row.availableDate <= after + 17 ).toBeTrue(); @@ -62,7 +62,7 @@ component extends="tests.resources.ModuleIntegrationSpec" appMapping="/app" { .from( "cbq_jobs" ) .where( "queue", variables.queue ) .first(); - expect( row.queue ).toBe( variables.queue ); + expect( compare( row.queue, variables.queue ) ).toBe( 0 ); } ); } ); } From 2b1b09c8245efec998a68239b9f4d6f49bd221fd Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Tue, 8 Sep 2026 20:02:37 -0600 Subject: [PATCH 3/3] fix(db): omit cf_sql prefix from text bindings --- models/Providers/DBProvider.cfc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/models/Providers/DBProvider.cfc b/models/Providers/DBProvider.cfc index 1d9d768..7eccc66 100644 --- a/models/Providers/DBProvider.cfc +++ b/models/Providers/DBProvider.cfc @@ -208,7 +208,7 @@ component accessors="true" extends="AbstractQueueProvider" { var jobPayload = { "queue" : { "value" : arguments.queueName, - "cfsqltype" : "cf_sql_varchar" + "cfsqltype" : "varchar" }, "attempts" : { "value" : arguments.attempts, @@ -218,7 +218,7 @@ component accessors="true" extends="AbstractQueueProvider" { "createdDate" : getCurrentUnixTimestamp(), "payload" : { "value" : serializeJSON( arguments.job.getMemento() ), - "cfsqltype" : "cf_sql_varchar" + "cfsqltype" : "varchar" } };