Skip to content

v0.1.13

Choose a tag to compare

@github-actions github-actions released this 31 Aug 09:12
· 27 commits to main since this release

Keep a job in processing when its lease cannot be written

pop() wrapped the JSON parse and the lease write in one try, and the catch
deleted the entry from the processing list before returning null. LMOVE had
already taken it out of pending, so a Redis blip on the lease write destroyed
the job outright — no retry, no failed record, nothing to recover.

Only an unparseable or malformed payload is purged now. A lease failure
propagates and leaves the job in processing, where recoverStale() reclaims it:
a missing lease is what it already treats as recoverable.

Say it out loud when the lossy pop is running in production

The opt-in silenced the warning, so a process deliberately running with
at-most-once delivery said nothing about it. Agreeing once in a config file
is not the same as being reminded, in the logs of the incident, that this is
how the process was running. The README now states the guarantee and the two
ways to keep it.

Refuse the lossy pop in production, and stop the worker on shutdown

Without LMOVE the pop is lpop then rpush, and a crash between the two
deletes the job from pending before it reaches processing: nothing recovers
it, because nothing knows it existed. That is a different delivery
guarantee, and in production it now has to be asked for.

stop() waits for the loop to actually be gone rather than only the job in
flight, and its sleep is cancellable, so a teardown does not return with a
worker still polling. The provider shuts down the queue IT booted, so two
applications in one process cannot stop each other's.

Declare the environment variables the generated config reads

Checked against @adonisjs/mail 10.4.0, whose configure() publishes the config
AND calls defineEnvVariables beside it. Mine wrote a config full of
env.get('QUEUE_STORE') and declared nothing, which is the half-installation
the hook exists to prevent: the application boots, the config asks the
environment for something nothing ever put there, and the fallback answers.

addEnvVars was already on ream's codemods and simply went unused.

Say that ream add sets this up, because it does now

Ship the configure hook ream add expects

ream add <pkg> installs, then imports <pkg>/configure and runs it. Nine
packages provided that hook and this one did not, so ream add left an
application with a provider registered and no config file for it to read —
falling back to a default that is rarely the one anybody wanted, silently.

The hook registers the provider and writes the config stub beside it, because
the two are one step: a provider without its file is not installed, it is half
installed.

Name the queue backend in the config, like every other package

Bay took driver: "memory" and threw for anything else, telling the
application to build the QueueManager itself — so Redis could not be reached
from a config file at all, and the environment could not choose.

AdonisJS gives a package with several backends and one selected the same shape
everywhere (session, limiter, lock, mail, drive): a factory namespace imported
beside defineConfig, each entry that namespace's result, the selection read
from the environment.

import { defineConfig, stores } from '@c9up/bay'

default: env.get('QUEUE_STORE'),
stores: {
memory: stores.memory(),
redis: stores.redis({ connection: 'main' }),
}

Only the selected store is built, and a default naming nothing throws listing
what exists — falling back to memory would look like it worked until a restart
dropped every pending job. The quasar connection name goes through the bridge
bay already had, so quasar stays an optional peer.

The single driver form still works.


Changes since v0.1.12.