Skip to content

Redesign enqueue API: auto-registry + named-parameter jobs - #27

Merged
jeffperrin merged 1 commit into
mainfrom
25-26-enqueue-api
Jul 9, 2026
Merged

jeffperrin merged 1 commit into
mainfrom
25-26-enqueue-api

Conversation

@jeffperrin

Copy link
Copy Markdown
Owner

Reworks the user-facing enqueue API so consuming apps never touch a registry and jobs can carry named parameters. Two halves of one redesign.

Auto-registry (#25)

Benchwarmer::Job.inherited registers every named subclass under its job_type in Benchwarmer::Job.registry. Queue, Worker, and Web default their registry to this global hash, so a consuming app just defines job classes. An explicit registry:/:registry still overrides it, preserving the injected-registry test seam and per-app isolation. Anonymous classes (Class.new(Job)) have no name and are skipped.

Named parameters (#26)

Base Job#initialize(**params) captures constructor kwargs. Queue#enqueue now accepts:

  • a Job class — enqueue(GreetJob, args: ["world"]) (positional args)
  • a Job instance — enqueue(GreetJob.new(name: "World")) (its kwargs become the payload)
  • a type string — enqueue("greet", args: {name: "World"}) (how the web form submits)

Instance kwargs serialize into the args column as a JSON object; args: arrays serialize as JSON arrays. The worker parses the payload and dispatches Array -> perform(*args), Object -> perform(**symbolized). The instance is a value object describing the run; the worker rebuilds fresh via job_factory and passes params to perform (collaborators stay DI via initialize, params are data).

Args must be JSON-serializable — non-native values raise ArgumentError at enqueue time (JSON strict mode) rather than failing inside the worker. Symbols still round-trip (kwargs survive).

Ripple effects

  • Job#enqueue_child and Queue#schedule (type: accepts a class) get the same flexibility.
  • queue.retry copies args verbatim, so object payloads round-trip (tested).
  • Web enqueue form accepts a JSON array or object (422 only for a bare scalar); its registry defaults to the auto-registry via a deferred read so late-defined jobs appear.
  • examples/, tasks/dev.rake, and README.md rewritten to the new API — no hand-built registry anywhere.

Breaking changes (pre-1.0)

  • Worker.new/Queue.new registry: is now optional (defaults to the global auto-registry) rather than required.
  • Queue#enqueue's first positional arg is now a class/instance/string (was a type string only) — strings still work.
  • Enqueue args are validated with JSON strict mode: non-JSON-native values (arbitrary objects, Time, Proc) now raise ArgumentError at enqueue time instead of being silently coerced to strings.

Verification

  • bundle exec rake test — 126 runs, 417 assertions, 0 failures.
  • bin/check (standardrb) — clean.
  • Manually ran rake dev:ui: enqueue form shows the new "Args (JSON array or object)" label; POSTing {"chunk":"abc"} object args enqueued successfully (stored {"chunk":"abc"}); a bare scalar 42 returned 422; graceful shutdown cleaned up the demo db.
  • Booted examples/bin/worker: scheduled nightly via the class-based type: NightlyJob and polled cleanly; ran a GreetJob.new(name:...) instance end-to-end through a worker (perform(name:, language:) received the kwargs).

Closes #25
Closes #26

🤖 Generated with Claude Code

Closes #25 and #26 — one API redesign in two halves.

Auto-registry (#25): Benchwarmer::Job.inherited registers each named subclass
under its job_type in Benchwarmer::Job.registry. Queue, Worker, and Web default
their registry to this global hash, so consuming apps never build one by hand;
an explicit registry: still overrides it (the injected-registry test seam and
per-app isolation both keep working). Anonymous classes (Class.new(Job)) have no
name and are skipped.

Named parameters (#26): base Job#initialize(**params) captures constructor
kwargs. Queue#enqueue now accepts a Job class (positional args:), a Job instance
(its kwargs become the payload), or a type string. Instance kwargs serialize
into the args column as a JSON object; args: arrays serialize as JSON arrays.
The worker parses the payload and dispatches Array -> perform(*args),
Object -> perform(**symbolized). Args must be JSON-serializable — non-native
values raise ArgumentError at enqueue time (JSON strict mode) instead of failing
inside the worker.

Ripple effects: Job#enqueue_child and Queue#schedule (type: accepts a class) get
the same flexibility; retry copies args verbatim so object payloads round-trip;
the web enqueue form accepts a JSON array OR object (422 only for a bare scalar)
and defaults its registry to the auto-registry via a deferred read so
late-defined jobs appear. examples/, tasks/dev.rake, and README updated to the
new API — no hand-built registry anywhere.

Breaking changes (pre-1.0):
- Worker.new/Queue.new registry: is now optional (defaults to the global
  auto-registry) rather than required.
- Queue#enqueue's first positional arg is now a class/instance/string (was a
  type string only) — strings still work.
- Enqueue args are validated with JSON strict mode: values that aren't
  JSON-native (arbitrary objects, Time, Proc) now raise ArgumentError at enqueue
  time instead of being silently coerced to strings.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@jeffperrin
jeffperrin merged commit 68965ca into main Jul 9, 2026
2 checks passed
@jeffperrin
jeffperrin deleted the 25-26-enqueue-api branch July 9, 2026 16:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle named-parameters when initializing a job Change user-facing api

1 participant