Closed green3g closed 4 years ago
Update: It looks like the 120 from above is coming from maintenanceIntervalSeconds
.
Can you post your init options and/or publish() calls?
Looks like you might have a bug in your parameter enumeration, where you loop and increment the placeholder value. For exampe, your statement includes values all the way up to 19, but the original statement only has 12. This is probably because I reuse these values multiple times in the SQL. Here's the original statement: https://github.com/timgit/pg-boss/blob/master/src/plans.js#L322-L380
Hmm - not sure if that's it. . I've been looking at it and it would appear that the values would get reused. I think its trying to put the value of 120 (maintenanceIntervalSeconds) in as the timezone.
Here's the SQL that is replaced:
WITH j AS (SELECT
:param_1::uuid as id,
:param_2::text as name,
:param_3::int as priority,
'created'::pgboss.job_state as state,
:param_4::int as retryLimit,
CASE
WHEN right(:param_5, 1) = 'Z' THEN CAST(:param_5 as timestamp with time zone)
ELSE now() + CAST(COALESCE(:param_5,'0') as interval)
END as startAfter,
CAST(:param_6 as interval) as expireIn,
:param_7::jsonb as data,
:param_8::text as singletonKey,
CASE
WHEN :param_9::integer IS NOT NULL THEN 'epoch'::timestamp + '1 second'::interval * (:param_9 * floor((date_part('epoch', now()) + :param_10) / :param_9))
ELSE NULL
END as singletonOn,
:param_11::int as retryDelay,
:param_12::bool as retryBackoff
)
INSERT INTO pgboss.job (
id,
name,
priority,
state,
retryLimit,
startAfter,
expireIn,
data,
singletonKey,
singletonOn,
retryDelay,
retryBackoff,
keepUntil
)
SELECT
id,
name,
priority,
state,
retryLimit,
startAfter,
expireIn,
data,
singletonKey,
singletonOn,
retryDelay,
retryBackoff,
CASE
WHEN right(:param_13, 1) = 'Z' THEN CAST(:param_13 as timestamp with time zone)
ELSE startAfter + CAST(COALESCE(:param_13,'0') as interval)
END as keepUntil
FROM j
ON CONFLICT DO NOTHING
RETURNING id
here's the parametersObject and the input array getting passed:
In response to your other question - I'm not doing anything special with the start options. Publish isn't getting called since this.boss.start()
fails with the error. error: invalid input syntax for type timestamp with time zone: "120"
(I updated my code above to be show the start call.)
FYI I'm using PostgreSQL 11.7 (Debian 11.7-2.pgdg90+1)
I must be missing something obvious. I tried testing the code you have in the plans sql and I don't understand why it isn't working.
SELECT (
CASE WHEN right('120', 1)='Z' THEN CAST('120' as timestamp with time zone)
ELSE now() + CAST(COALESCE('120','0') as interval)
END
) as startAfter
right('120', 1)='Z'
evaluates to 0 so <> 'Z' but somehow its still evaluating to throw that error...
Okay - so I think I might have found the root cause. Knex doesn't appear to use prepared statements at all so everything is being evaluated by the compiler as "static" for lack of better wordage.
https://github.com/knex/knex/issues/718
So I think that's why those values are throwing errors, the compiler knows 120 isn't a timestamp and catches it early.
what does your toString() output from knex.raw?
for example, this should show the actual values being substituted, like the following statement.
knex.raw('select 1 = ?', [1]).toString()
result:
select 1 = 1
Here's the raw tostring value:
WITH j AS (SELECT
'1d340e50-6937-11ea-b8e9-6f358183b88c'::uuid as id,
'__pgboss__maintenance'::text as name,
0::int as priority,
'created'::pgboss.job_state as state,
0::int as retryLimit,
CASE
WHEN right('120', 1) = 'Z' THEN CAST('120' as timestamp with time zone)
ELSE now() + CAST(COALESCE('120','0') as interval)
END as startAfter,
CAST('15 minutes' as interval) as expireIn,
NULL::jsonb as data,
NULL::text as singletonKey,
CASE
WHEN NULL::integer IS NOT NULL THEN 'epoch'::timestamp + '1 second'::interval * (NULL * floor((date_part('epoch', now()) + 0) / NULL))
ELSE NULL
END as singletonOn,
0::int as retryDelay,
false::bool as retryBackoff
)
INSERT INTO pgboss.job (
id,
name,
priority,
state,
retryLimit,
startAfter,
expireIn,
data,
singletonKey,
singletonOn,
retryDelay,
retryBackoff,
keepUntil
)
SELECT
id,
name,
priority,
state,
retryLimit,
startAfter,
expireIn,
data,
singletonKey,
singletonOn,
retryDelay,
retryBackoff,
CASE
WHEN right('30 days', 1) = 'Z' THEN CAST('30 days' as timestamp with time zone)
ELSE startAfter + CAST(COALESCE('30 days','0') as interval)
END as keepUntil
FROM j
ON CONFLICT DO NOTHING
RETURNING id
I rewrote the SQL to hopefully bypass knex's arg pre-parsing and substitutions. I can't say this experience with knex was a positive one, lol. Give this version a try please.
npm i pg-boss@4.0.1-beta1
Yep - looks like that fixed it!
Thanks! I'd agree - I was not aware that knex wasn't capable of using prepared statements.
Didn't work well for knex... https://nvd.nist.gov/vuln/detail/CVE-2016-20018
Hi - I'm running into an issue with upgrading to 4.0 and using the
executeSql
parameter in PgBoss.First, the reason I'm doing this is to avoid creating multiple DB connections, and reusing an existing knex connection:
The errors I'm seeing now:
On initialization:
And probably more relevant:
when inserting a new job.