-
Notifications
You must be signed in to change notification settings - Fork 1.5k
fix: enforce uniqueness and hour alignment for agent runtime usage events #27983
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
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
1cec4c4
chore(coderd/notifications): sync formatting and rendered-template go…
jaaydenh 06c925f
fix: enforce uniqueness and hour alignment for agent runtime usage ev…
jaaydenh 5ef08aa
revert: "chore(coderd/notifications): sync formatting and rendered-te…
jaaydenh 41e1a2d
updates for PR review
jaaydenh 0c25db9
chore(coderd/database): restore original InsertUsageEvent comment
jaaydenh 6982b2f
fix(coderd/database): renumber agent runtime invariants migration to …
jaaydenh 99ab235
chore(enterprise/coderd/usage): restore agent runtime requeue guidanc…
jaaydenh 92a01e2
fix(coderd/database): renumber agent runtime invariants migration to …
jaaydenh fd1be2f
chore(enterprise/coderd/usage): correct ON CONFLICT concurrency comments
jaaydenh 33ff1b7
fix(coderd/notifications/dispatch): drop unused markdown import in sm…
jaaydenh 92bfe85
chore(coderd): trim historical framing from invariant comments
jaaydenh f67ff01
fix(coderd/database): renumber agent runtime invariants migration to …
jaaydenh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
9 changes: 9 additions & 0 deletions
9
coderd/database/migrations/000570_usage_events_agent_runtime_invariants.down.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| -- IF EXISTS tolerates the index already being gone (e.g. rolling back out | ||
| -- of order during an incident) instead of failing. | ||
| DROP INDEX IF EXISTS idx_usage_events_agent_runtime; | ||
| CREATE INDEX idx_usage_events_agent_runtime | ||
| ON usage_events (event_type, created_at) | ||
| WHERE event_type = 'hb_agent_runtime_v1'; | ||
|
|
||
| ALTER TABLE usage_events | ||
| DROP CONSTRAINT IF EXISTS usage_events_agent_runtime_hour_aligned; |
24 changes: 24 additions & 0 deletions
24
coderd/database/migrations/000570_usage_events_agent_runtime_invariants.up.sql
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| -- The usage generator writes hb_agent_runtime_v1 rows with created_at at | ||
| -- the UTC hourly bucket start and exactly one row per bucket. Uniqueness | ||
| -- keeps any consumer that sums runtime_ms from counting a bucket twice; | ||
| -- the alignment CHECK protects the attribution model, which charges a | ||
| -- bucket to the usage period containing its start. | ||
| -- | ||
| -- Both statements validate existing rows. Every supported writer has always | ||
| -- produced conforming data, so a pre-existing violator is anomalous and | ||
| -- failing the migration loudly beats silently rewriting usage rows. | ||
| ALTER TABLE usage_events | ||
| ADD CONSTRAINT usage_events_agent_runtime_hour_aligned | ||
| CHECK ( | ||
| event_type <> 'hb_agent_runtime_v1' | ||
| OR date_trunc('hour', (created_at AT TIME ZONE 'UTC')) = (created_at AT TIME ZONE 'UTC') | ||
| ); | ||
|
|
||
| -- Inserts keep their (id) arbiter: re-inserting a bucket under its | ||
| -- deterministic id stays a silent no-op, while a duplicate bucket row under | ||
| -- a different id raises a unique violation (generateBucket in | ||
| -- enterprise/coderd/usage/generator.go handles it). | ||
| DROP INDEX idx_usage_events_agent_runtime; | ||
| CREATE UNIQUE INDEX idx_usage_events_agent_runtime | ||
| ON usage_events (event_type, created_at) | ||
| WHERE event_type = 'hb_agent_runtime_v1'; | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| package usage | ||
|
|
||
| import ( | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/lib/pq" | ||
| "github.com/stretchr/testify/require" | ||
| "go.uber.org/mock/gomock" | ||
|
|
||
| "cdr.dev/slog/v3/sloggers/slogtest" | ||
| "github.com/coder/coder/v2/coderd/database" | ||
| "github.com/coder/coder/v2/coderd/database/dbmock" | ||
| "github.com/coder/coder/v2/testutil" | ||
| "github.com/coder/quartz" | ||
| ) | ||
|
|
||
| // TestGenerateBucketUniqueViolation pins that a unique violation on the | ||
| // bucket index resolves the bucket as complete: another writer already | ||
| // recorded it. TestGeneratorConcurrentReplicas also reaches this path, but | ||
| // only when its goroutines actually interleave; this case cannot pass by | ||
| // scheduling accident. | ||
| func TestGenerateBucketUniqueViolation(t *testing.T) { | ||
| t.Parallel() | ||
|
|
||
| ctx := testutil.Context(t, testutil.WaitShort) | ||
| ctrl := gomock.NewController(t) | ||
| mDB := dbmock.NewMockStore(ctrl) | ||
| gen := NewGenerator(quartz.NewMock(t), slogtest.Make(t, nil), mDB, NewDBInserter()) | ||
|
|
||
| mDB.EXPECT(). | ||
| GetTotalChatMessageRuntimeMsInRange(gomock.Any(), gomock.Any()). | ||
| Return(int64(1000), nil) | ||
| mDB.EXPECT(). | ||
| InsertUsageEvent(gomock.Any(), gomock.Any()). | ||
| Return(&pq.Error{ | ||
| Code: "23505", // unique_violation | ||
| Constraint: string(database.UniqueIndexUsageEventsAgentRuntime), | ||
| }) | ||
|
|
||
| bucket := time.Date(2025, 3, 10, 10, 0, 0, 0, time.UTC) | ||
| require.NoError(t, gen.generateBucket(ctx, bucket)) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.