-
Notifications
You must be signed in to change notification settings - Fork 894
chore: fix concurrent CommitQuota
transactions for unrelated users/orgs
#15261
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
dce750d
4fd9760
6215603
9ccd0b2
784a98f
5f021ad
426eeb6
b69dd0f
ec8f799
f613f31
746203d
c0d05db
245f6df
422e694
685b21e
33dbd92
a99882a
6ce8bfe
3a9270d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -306,12 +306,12 @@ | |
}) | ||
} | ||
|
||
// DB=ci DB_FROM=cikggwjxbths | ||
// nolint:paralleltest // Tests must run serially | ||
func TestWorkspaceSerialization(t *testing.T) { | ||
t.Parallel() | ||
|
||
if !dbtestutil.WillUsePostgres() { | ||
panic("We should only run this test with postgres") | ||
t.Skip("Serialization errors only occur in postgres") | ||
} | ||
|
||
db, ps := dbtestutil.NewDB(t) | ||
|
@@ -342,8 +342,6 @@ | |
}, user). | ||
Do() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm pretty sure the query planner uses the cardinality of different columns relative to the table size to determine how to run its query. That means to get reasonable assurance about whether different transactions interfere, we need a realistic number of organizations, users, workspaces, and workspace builds. PG Docs have this to say
If any page locks are held by our transactions, either as a result of bitmap scans (if that's a thing), or as a result of coalescing finer grained locks, then whether or not transactions serialize without errors could depend on factors not controlled by this test (PostgreSQL config, version, insert timing, etc). That is to say, flaky. Really, what we want is a realistic amount of data, and then to run repeated transactions, with overlapping pairs chosen randomly, and then to gather statistics on how many pairs interfered with one another. I don't think it makes sense to run these on every CI run. We could even extend to an arbitrary number of simultaneous transactions on different workspaces --- since as deployments grow in size the number of simultaneous builds increases. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right. So this does not put anything to bed, however this is a step in the right direction. I would prefer to iterate on this with more PRs. I added metrics to track and log serialization failures: #15215 So at the very least, in the next release we can begin collecting better frequency metrics on these events. I can spin up some larger datasets. I think we should take the easy index optimizations you pointed out above. |
||
|
||
var _ = otherOrg | ||
|
||
// TX mixing tests. **DO NOT** run these in parallel. | ||
// The goal here is to mess around with different ordering of | ||
// transactions and queries. | ||
|
@@ -373,6 +371,7 @@ | |
// +------------------------------+------------------+ | ||
// pq: could not serialize access due to concurrent update | ||
ctx := testutil.Context(t, testutil.WaitLong) | ||
//nolint:gocritic // testing | ||
ctx = dbauthz.AsSystemRestricted(ctx) | ||
|
||
myWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ | ||
|
@@ -380,7 +379,7 @@ | |
OwnerID: user.ID, | ||
}).Do() | ||
|
||
bumpDeadline := func() { | ||
err := db.InTx(func(db database.Store) error { | ||
err := db.UpdateWorkspaceBuildDeadlineByID(ctx, database.UpdateWorkspaceBuildDeadlineByIDParams{ | ||
Deadline: dbtime.Now(), | ||
|
@@ -426,6 +425,7 @@ | |
// +------------------------------+------------------+ | ||
// Works! | ||
ctx := testutil.Context(t, testutil.WaitLong) | ||
//nolint:gocritic // testing | ||
ctx = dbauthz.AsSystemRestricted(ctx) | ||
|
||
myWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ | ||
|
@@ -456,7 +456,6 @@ | |
Isolation: sql.LevelSerializable, | ||
}) | ||
assert.NoError(t, err) | ||
|
||
} | ||
|
||
// Start TX | ||
|
@@ -491,6 +490,7 @@ | |
// +---------------------+----------------------------------+ | ||
// pq: could not serialize access due to concurrent update | ||
ctx := testutil.Context(t, testutil.WaitShort) | ||
//nolint:gocritic // testing | ||
ctx = dbauthz.AsSystemRestricted(ctx) | ||
|
||
myWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ | ||
|
@@ -540,6 +540,7 @@ | |
// +---------------------+----------------------------------+ | ||
// pq: could not serialize access due to concurrent update | ||
ctx := testutil.Context(t, testutil.WaitShort) | ||
//nolint:gocritic // testing | ||
ctx = dbauthz.AsSystemRestricted(ctx) | ||
|
||
myWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ | ||
|
@@ -583,6 +584,7 @@ | |
// +---------------------+----------------------------------+ | ||
// Works! | ||
ctx := testutil.Context(t, testutil.WaitShort) | ||
//nolint:gocritic // testing | ||
ctx = dbauthz.AsSystemRestricted(ctx) | ||
var err error | ||
|
||
|
@@ -637,6 +639,7 @@ | |
// | | CommitTx() | | ||
// +---------------------+---------------------+ | ||
ctx := testutil.Context(t, testutil.WaitLong) | ||
//nolint:gocritic // testing | ||
ctx = dbauthz.AsSystemRestricted(ctx) | ||
|
||
myWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ | ||
|
@@ -695,6 +698,7 @@ | |
// | | CommitTx() | | ||
// +---------------------+---------------------+ | ||
ctx := testutil.Context(t, testutil.WaitLong) | ||
//nolint:gocritic // testing | ||
ctx = dbauthz.AsSystemRestricted(ctx) | ||
|
||
myWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ | ||
|
@@ -756,6 +760,7 @@ | |
// +---------------------+---------------------+ | ||
// pq: could not serialize access due to read/write dependencies among transactions | ||
ctx := testutil.Context(t, testutil.WaitLong) | ||
//nolint:gocritic // testing | ||
ctx = dbauthz.AsSystemRestricted(ctx) | ||
|
||
myWorkspace := dbfake.WorkspaceBuild(t, db, database.WorkspaceTable{ | ||
|
@@ -891,7 +896,7 @@ | |
return c.DBTx.Done() | ||
} | ||
|
||
func noReturn[T any](f func(context.Context, *testing.T) T) func(context.Context, *testing.T) { | ||
return func(ctx context.Context, t *testing.T) { | ||
f(ctx, t) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made this configurable so unit tests should not fail if they hit serial errors. We are not doing much concurrency in our tests, and if we are hitting these failures, we should understand them better and solve them case by case.
We can change this if we get too many flakes.