Punk-Queue
view release on metacpan or search on metacpan
include/pq_backend.h view on Meta::CPAN
pq_txn_begin(aTHX_ self);
if (!pq_guarded_peek(aTHX_ self, id, retries, prestate, sizeof prestate,
&attempts_col)) {
pq_txn_commit(aTHX_ self);
return 0;
}
now = pq_now(aTHX_ self);
sql = pq_sql_new(aTHX_
"UPDATE pq_jobs SET state = 'inactive', retries = retries + 1,"
" retried = ?, delayed = ?, started = NULL, finished = NULL,"
" worker = NULL, result = NULL");
if (opts && (v = pq_get(aTHX_ opts, "delay")) && SvOK(v))
delay = SvNV(v);
pq_bind_nv(aTHX_ bind, now);
pq_bind_nv(aTHX_ bind, now + delay);
if (opts && (v = pq_get(aTHX_ opts, "priority")) && SvOK(v)) {
pq_sql_cat(aTHX_ sql, ", priority = ?");
pq_bind_iv(aTHX_ bind, SvIV(v));
}
if (opts && (v = pq_get(aTHX_ opts, "queue")) && SvOK(v)) {
pq_name_check(aTHX_ v, "queue");
pq_sql_cat(aTHX_ sql, ", queue = ?");
pq_bind_sv(aTHX_ bind, v);
}
if (opts && (v = pq_get(aTHX_ opts, "attempts")) && SvOK(v)) {
if (SvIV(v) < 1) {
pq_txn_rollback(aTHX_ self);
croak("Punk::Queue: attempts must be at least 1, not %ld",
(long)SvIV(v));
}
pq_sql_cat(aTHX_ sql, ", attempts = ?");
pq_bind_iv(aTHX_ bind, SvIV(v));
}
pq_sql_cat(aTHX_ sql, " WHERE id = ? AND retries = ?");
pq_bind_iv(aTHX_ bind, id);
pq_bind_iv(aTHX_ bind, retries);
took = pq_do(aTHX_ self, sql, bind);
if (took > 0) {
/* the children had counted this parent done; block them again */
if (strEQ(prestate, "finished"))
pq_children_adjust(aTHX_ self, id, +1, PQ_KIDS_ALL);
else if (strEQ(prestate, "failed"))
pq_children_adjust(aTHX_ self, id, +1, PQ_KIDS_LAX);
pq_log_addf(aTHX_ self, id, "info",
delay > 0 ? "retried from '%s' - due in %.1" NVff "s"
: "retried from '%s'",
prestate, (NV)delay);
}
pq_txn_commit(aTHX_ self);
return took > 0 ? 1 : 0;
}
/* remove_job refuses an active job: the worker running it would finish
* into a void and the supervision bookkeeping would point at a ghost.
* Retry it first (which strands the running attempt), then remove. Dep
* rows cascade via the foreign keys - but only after the children's
* counters are adjusted, because the adjustment needs the dep rows to
* find them. */
static IV pq_remove_job(pTHX_ SV *self, IV id) {
char prestate[16];
IV attempts = 0, took = 0;
pq_txn_begin(aTHX_ self);
{
AV *bind = pq_binds(aTHX), *row;
pq_bind_iv(aTHX_ bind, id);
row = pq_selectrow(aTHX_ self, sv_2mortal(newSVpvs(
"SELECT state, attempts FROM pq_jobs WHERE id = ?")), bind);
if (!row) { pq_txn_commit(aTHX_ self); return 0; }
{
SV *st = pq_col(aTHX_ row, 0);
my_strlcpy(prestate, SvOK(st) ? SvPV_nolen(st) : "",
sizeof prestate);
attempts = pq_col_iv(aTHX_ row, 1);
}
SvREFCNT_dec((SV *)row);
PERL_UNUSED_VAR(attempts);
}
if (strEQ(prestate, "active")) {
pq_txn_commit(aTHX_ self);
return 0;
}
if (strEQ(prestate, "inactive"))
pq_children_adjust(aTHX_ self, id, -1, PQ_KIDS_ALL);
else if (strEQ(prestate, "failed"))
pq_children_adjust(aTHX_ self, id, -1, PQ_KIDS_NONLAX);
/* finished: every child already got its decrement */
{
AV *bind = pq_binds(aTHX);
pq_bind_iv(aTHX_ bind, id);
took = pq_do(aTHX_ self, sv_2mortal(newSVpvs(
"DELETE FROM pq_jobs WHERE id = ?"
" AND state IN ('inactive', 'failed', 'finished')")), bind);
}
if (took > 0) {
AV *bind = pq_binds(aTHX);
pq_bind_iv(aTHX_ bind, id);
(void)pq_do(aTHX_ self, sv_2mortal(newSVpvs(
"DELETE FROM pq_job_logs WHERE job_id = ?")), bind);
}
pq_txn_commit(aTHX_ self);
return took > 0 ? 1 : 0;
}
/* ---- notes -----------------------------------------------------------------
*
* Merge, not replace, and merged in C after an frj decode rather than in
* SQL - json_patch exists on neither backend in a portable form, and the
* conformance suite requires byte-identical behaviour. A key set to undef
* is deleted. Works in any state: progress notes on an active job are the
* whole point. */
static IV pq_note(pTHX_ SV *self, IV id, HV *merge) {
AV *bind, *row;
SV *decoded, *json;
( run in 2.035 seconds using v1.01-cache-2.11-cpan-e7c6538aa59 )