Skip to content

Fix custom schema support of rivertest.Worker#1262

Merged
brandur merged 1 commit into
riverqueue:masterfrom
zmwangx:rivertest-honor-config-schema
May 31, 2026
Merged

Fix custom schema support of rivertest.Worker#1262
brandur merged 1 commit into
riverqueue:masterfrom
zmwangx:rivertest-honor-config-schema

Conversation

@zmwangx
Copy link
Copy Markdown
Contributor

@zmwangx zmwangx commented May 31, 2026

Currently, rivertest.Worker ignores custom schema in river config.

The fix is one line. Also added a test case for it.

Simple testcontainers-based repro:

package repro

import (
	"context"
	"testing"
	"time"

	"github.com/jackc/pgx/v5/pgxpool"
	"github.com/riverqueue/river"
	"github.com/riverqueue/river/riverdriver/riverpgxv5"
	"github.com/riverqueue/river/rivermigrate"
	"github.com/riverqueue/river/rivertest"
	"github.com/stretchr/testify/require"
	"github.com/testcontainers/testcontainers-go"
	"github.com/testcontainers/testcontainers-go/modules/postgres"
	"github.com/testcontainers/testcontainers-go/wait"
)

type Args struct{}

func (Args) Kind() string { return "repro" }

// TestRivertestWorkerCustomSchema reproduces the rivertest.Worker custom-schema bug.
//
//	PRE-FIX  (released river through v0.38.0): FAILS with
//	  "failed to update job to running state: ... relation \"river_job\" does not exist"
//	POST-FIX (replace -> patched fork): PASSES.
//
// River is migrated into a NON-default schema, and the job is worked through a
// transaction whose search_path doesn't include that schema. The insert (via
// the client) qualifies river_job with the schema, but the pre-fix running-state
// update runs unqualified and can't find the table.
func TestRivertestWorkerCustomSchema(t *testing.T) {
	ctx := context.Background()

	pgc, err := postgres.Run(ctx, "postgres:18-alpine",
		postgres.WithDatabase("river"),
		postgres.WithUsername("postgres"),
		postgres.WithPassword("postgres"),
		testcontainers.WithWaitStrategy(
			wait.ForLog("database system is ready to accept connections").
				WithOccurrence(2).WithStartupTimeout(60*time.Second),
		),
	)
	require.NoError(t, err)
	t.Cleanup(func() { _ = pgc.Terminate(ctx) })

	dsn, err := pgc.ConnectionString(ctx, "sslmode=disable")
	require.NoError(t, err)

	pool, err := pgxpool.New(ctx, dsn)
	require.NoError(t, err)
	t.Cleanup(pool.Close)

	const schema = "custom_schema"

	_, err = pool.Exec(ctx, "CREATE SCHEMA "+schema)
	require.NoError(t, err)
	migrator, err := rivermigrate.New(riverpgxv5.New(pool), &rivermigrate.Config{Schema: schema})
	require.NoError(t, err)
	_, err = migrator.Migrate(ctx, rivermigrate.DirectionUp, nil)
	require.NoError(t, err)

	config := &river.Config{ID: "repro", Schema: schema}
	tx, err := pool.Begin(ctx)
	require.NoError(t, err)
	t.Cleanup(func() { _ = tx.Rollback(ctx) })

	worker := river.WorkFunc(func(ctx context.Context, job *river.Job[Args]) error { return nil })
	tw := rivertest.NewWorker(t, riverpgxv5.New(pool), config, worker)

	res, err := tw.Work(ctx, t, tx, Args{}, nil)
	require.NoError(t, err) // <-- fails pre-fix
	require.Equal(t, river.EventKindJobCompleted, res.EventKind)
}

Disclosure: Claude Opus assisted in authoring the fix. Everything's carefully human reviewed, and PR is entirely human authored.

Copy link
Copy Markdown
Contributor

@brandur brandur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thank you!!

A couple minor nits below. Could you also add a changelog entry under the "fixed" section please?

Comment thread rivertest/worker.go Outdated
Comment thread rivertest/worker_test.go Outdated
// is migrated into an isolated named schema and worked through a transaction
// whose search_path is empty (see DBPool), so its tables resolve only via
// schema qualification.
func TestWorker_Work_CustomSchema(t *testing.T) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests are currently ordered as:

  • TestWorker_Work
  • TestWorker_WorkJob

With subtests under each for different things. It seems a bit odd to pull out this new responsibility into a separate top-level test and put Work + WorkJob under it.

Can you ask Claude to reorder so that "CustomSchema" becomes a subtest under each of TestWorker_Work and TestWorker_WorkJob instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I greenlighted a separate test because these need a different setup, but yeah, probably better to fold in with inline setup instead. Done.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx.

@zmwangx zmwangx force-pushed the rivertest-honor-config-schema branch from 3c7426c to 044cda2 Compare May 31, 2026 04:13
@brandur
Copy link
Copy Markdown
Contributor

brandur commented May 31, 2026

@zmwangx Thanks! And can you add that changelog too?

…Worker`

`rivertest.Worker` works a job in three database steps: it inserts the job
through the client, builds an inline completer, and transitions the job to
`running` via `JobUpdateFull`. The first two already thread `config.Schema`
through — the client uses it internally, and it's passed explicitly to
`jobcompleter.NewInlineCompleter` — but the `JobUpdateFull` call omitted it.

With a non-default `Schema`, the insert lands the job in `<schema>.river_job`
correctly, then the running-state update runs unqualified and resolves only
through the connection's `search_path`. On a connection that doesn't include
the configured schema it fails one step later with:

    test worker internal error: failed to update job to running state: ERROR: relation "river_job" does not exist (SQLSTATE 42P01)

Pass `w.config.Schema` into `JobUpdateFullParams` so all three steps agree on
the schema. This finishes custom-schema support for `rivertest.Worker`; the
`rivertest.Require*` family received an analogous per-call `Schema` option in
riverqueue#926 (riverqueue#907).

The regression tests migrate River into an isolated named schema and work jobs
through a transaction whose `search_path` is empty, so the tables resolve only
via schema qualification — the exact condition that fails before this change.
They live as `CustomSchema` subtests of `TestWorker_Work` and
`TestWorker_WorkJob`, each building its own bundle inline since the schema setup
differs from those tests' shared `setup`.
@zmwangx zmwangx force-pushed the rivertest-honor-config-schema branch from 044cda2 to 3134739 Compare May 31, 2026 06:09
@zmwangx
Copy link
Copy Markdown
Contributor Author

zmwangx commented May 31, 2026

Oh sorry, missed that comment. Pushed.

@brandur brandur merged commit 87e82c3 into riverqueue:master May 31, 2026
11 of 12 checks passed
@zmwangx zmwangx deleted the rivertest-honor-config-schema branch May 31, 2026 07:49
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.

2 participants