The River client is made available to workers during execution, making it easy to enqueue additional jobs from within a job.
Basic usage
The River client working a job is stored in a value on the context provided to workers. The client can be retrieved from the context (or any contexts derived from it) using the ClientFromContext helper:
func (w *MyWorker) Work(ctx context.Context, job *river.Job[MyArgs]) error { client := river.ClientFromContext[pgx.Tx](ctx)
...}The type parameter pgx.Tx corresponds to the generic type parameter of the underlying Client[pgx.Tx]. When using the database/sql driver, the type parameter should be *sql.Tx:
client := river.ClientFromContext[*sql.Tx](ctx)If ClientFromContext is called on a context which isn’t derived from the work context, it will panic. This situation indicates a programming error so most users will find the panic more convenient, although a non-panicking version is also available:
func (w *MyWorker) Work(ctx context.Context, job *river.Job[MyArgs]) error { client, err := river.ClientFromContextSafely[pgx.Tx](ctx) if err != nil { return fmt.Errorf("error getting client from context: %w", err) }
...}The work context exposes the client, including its plugins, hooks, and middleware:
builder.worker(myJob, context -> { context.client().insert(notify, new NotifyArgs(context.args().accountId()));});Use job.client from a running worker:
def work(job) job.client.insert NotifyArgs.new(account_id: job.args.fetch("account_id"))endWorkContext::client returns the client when the worker is running under River:
let client = context.client().expect("running River worker");client.insert(NotifyArgs { account_id: job.args.account_id }).await?;The worker context includes client:
workers.add(myJob, async ({ client, job }) => { await client.insert(notify, { accountId: job.args.accountId });});River Pro Client
For River Pro customers, the riverpro.Client is also available on the context via the riverpro package:
riverproClient := riverpro.ClientFromContext[pgx.Tx](ctx)A worker running under River::Pro::Client receives that same client through job.client, including its Pro APIs:
def work(job) client = job.client run = client.workflow(job.metadata.fetch("workflow_id"))endThis example assumes the job is a workflow task. No separate context lookup or cast is required.