Skip to content

Bring TestTx helper into rivershared for use in other projects#814

Merged
brandur merged 1 commit intomasterfrom
brandur-test-tx-shared
Mar 24, 2025
Merged

Bring TestTx helper into rivershared for use in other projects#814
brandur merged 1 commit intomasterfrom
brandur-test-tx-shared

Conversation

@brandur
Copy link
Copy Markdown
Contributor

@brandur brandur commented Mar 23, 2025

I found in another demo project that I wanted to have access to the
TestTx helper for tests, but that we weren't exporting it anywhere.
Here, bring it into rivershared for easy access everywhere.

I put two variants in for now, the simpler TestTx that uses a pool to
TEST_DATABASE_URL or river_test, and a TestTxPool that lets you
inject your own pool. The former is in use for the time being by
riverinternaltest so it can do its existing connection customization
logic, but as we fully migrate it to rivershared, we should see if we
can drop that along with TestTxPool maybe. Even if we don't drop the
latter, it's not the worst thing to have around because it definitely
increases flexibility.

I also added some code that uses context.WithoutCancel to be able to
issue a full rollback in TestTx cleanup. This isn't needed by the main
River project yet, but probably will be soon. When switching to the new
Go t.Context in tests, the context is cancelled before cleanup phases
are called, so without these changes the rollback will fail.

I found in another demo project that I wanted to have access to the
`TestTx` helper for tests, but that we weren't exporting it anywhere.
Here, bring it into `rivershared` for easy access everywhere.

I put two variants in for now, the simpler `TestTx` that uses a pool to
`TEST_DATABASE_URL` or `river_test`, and a `TestTxPool` that lets you
inject your own pool. The former is in use for the time being by
`riverinternaltest` so it can do its existing connection customization
logic, but as we fully migrate it to `rivershared`, we should see if we
can drop that along with `TestTxPool` maybe. Even if we don't drop the
latter, it's not the worst thing to have around because it definitely
increases flexibility.

I also added some code that uses `context.WithoutCancel` to be able to
issue a full rollback in `TestTx` cleanup. This isn't needed by the main
River project yet, but probably will be soon. When switching to the new
Go `t.Context` in tests, the context is cancelled before cleanup phases
are called, so without these changes the rollback will fail.
@brandur brandur requested a review from bgentry March 23, 2025 00:07

// DBPool gets a lazily initialized database pool for `TEST_DATABASE_URL` or
// `river_test` if the former isn't specified.
func DBPool(ctx context.Context, tb testing.TB) *pgxpool.Pool {
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.

I wonder if this should take an arg for DB URL rather than assuming a particular env? It makes it slightly more verbose to use but also much more flexible if other projects want to use their own schemas and DBs instead of sharing those used by the main River test suite.

It could even require.NotEmpty on the URL so the caller doesn't need to use a mustGetEnv type util when calling it.

I guess the downside is that this arg would need to cascade down through TestTx and TestTxPool, whose APIs are more likely to be called in a lot of places.

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.

Yeah, good idea. I went back and forth on these quite a lot because it's hard to find a good balance between good customizability and encouraging good default convention everywhere.

Just since this is specifically in riversharedtest (strongly implying use in testing), why don't we see if we can get everything on the convention of TEST_DATABASE_URL/river_test. In case this is turns out to be harde than expected, we can swap that out early for a more injectable env version.

Comment on lines +118 to +122
// Tests may inerit context from `t.Context()` which is cancelled after
// tests run and before calling clean up. We need a non-cancelled
// context to issue rollback here, so use a bit of a bludgeon to do so
// with `context.WithoutCancel()`.
ctx := context.WithoutCancel(ctx)
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.

This of course means this rollback could hang ~indefinitely since it no longer inherits cancellation from tb.Context(), but that's probably fine within a test suite. Worst case you could re-apply a moderate timeout here.

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.

Yeah I suppose it's technically possible, but I think it's another one of those things that doesn't really happen in practice. I've had something similar to this in place at work for many months now over which time we've done millions of test runs and I've never seen it happen even one time.

@brandur
Copy link
Copy Markdown
Contributor Author

brandur commented Mar 24, 2025

Thanks!

@brandur brandur merged commit c81201e into master Mar 24, 2025
10 checks passed
@brandur brandur deleted the brandur-test-tx-shared branch March 24, 2025 14:56
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