Commit a7fd1c9
committed
Backfill WAS_RUNNING events for running apps, tasks, and service instances
Seed a synthetic WAS_RUNNING usage event for every currently-running app
process, a TASK_WAS_RUNNING event for every currently-running task, and a
WAS_RUNNING event for every existing service instance. Billing consumers can
then bootstrap a complete picture of what is running, even though the usage
event cleanup deleted the original STARTED/TASK_STARTED/CREATED events long
ago.
The backfill is a batched VCAP::WasRunningBackfill helper called from thin
no_transaction migrations, following the bigint-migration pattern. It walks
the started processes / running tasks / service instances in id order, one
batch at a time, each batch in its own READ COMMITTED transaction -- so no
statement comes near the migration statement timeout, and MySQL's
INSERT..SELECT takes no shared next-key locks on the scanned rows while the
API keeps serving traffic. Tasks in CANCELING count as running: they stay
billable until Diego reports them dead, and no usage event marks the moment a
task enters CANCELING. The app query limits its package/droplet subqueries to
each batch's apps so it never scans those whole tables, and it COALESCEs
nullable legacy columns so one bad NULL row cannot abort a deploy. The seeds
skip any resource whose start is already on record -- an earlier baseline, or
a real STARTED/TASK_STARTED/CREATED/UPDATED event -- so running the backfill
again cannot give a resource a second start that a consumer would bill twice.
The API stays live during migrations, so a seed batch can race a stop or
delete and write a baseline for a resource that is already gone -- or whose
stop event landed earlier in the table, with a lower id. Deleting such rows
would not help: consumers read these tables forward, by id, and keep what
they read. A poller may already have the baseline, and for tasks a
TASK_STOPPED may already have been written against it. You can delete a row;
you cannot make a consumer un-read it. So instead, a post-seed repair adds
the missing ending event (STOPPED / DELETED / TASK_STOPPED) for every
baseline whose resource is no longer running and that has no later ending
event (one with a higher id). The ending is built from the baseline row
itself, which carries every NOT NULL column an ending needs -- necessary,
because the resource row may be gone entirely. A baseline that already has
its real ending is never touched, and each added ending stops its baseline
from matching the test, so re-running the backfill changes nothing. Two
properties of the added ending are deliberate. Its created_at is the repair
time, not the true stop time: a bounded overbill that ends, which beats a
missing ending billed forever. And its previous_state is the baseline's
state, which no normal ending carries, so repaired endings are easy to tell
apart.
A skip_was_running_backfill config flag lets operators opt out. The
migrations check it (not the helper), because they are recorded as applied
either way; 'rake db:was_running_backfill' runs the same seeding and repair
later. Use the rake task after a skipped migration, once after the deploy
that ships these migrations (to repair anything that slipped through while
old API servers were still running), or after a destructive usage-event
purge, which wipes the task start events that task stop events depend on.
The post-deploy run matters because the seed migrations run at the start of
a rolling deploy, while old API servers still serve traffic and their old
cleanup code can still delete start events the new code depends on. The last
seed migration logs this reminder, so it shows up in the migration output
operators see during the deploy. The rake task rejects a batch size that is
not a positive whole number, instead of silently seeding nothing.
Every backfill run holds a session advisory lock, so two runs cannot both add
the same missing ending. The seed migrations wait for the lock: a deploy that
pauses behind a finishing rake run is harmless, and a failed deploy is not.
The rake task fails fast instead, so an operator gets feedback rather than a
silent queue. This is the first advisory lock in this codebase; a comment in
the helper explains why the locking tools already in use do not fit this job.
The migrations' down blocks are deliberate no-ops: consumers
may already have read the seeded rows, and deleting a row cannot make a
consumer un-read it -- it would only leave the stop events written against
these rows without a start event to pair with.
Document the WAS_RUNNING/TASK_WAS_RUNNING states, their created_at semantics,
the repaired ending events, and the rules consumers must follow on the V3
resources, and list the new states in the legacy V2 usage-event docs because
V2 reads the same event rows.1 parent e30e8af commit a7fd1c9
21 files changed
Lines changed: 1796 additions & 2 deletions
File tree
- db/migrations
- docs
- v2
- app_usage_events
- service_usage_events
- v3/source/includes/resources
- app_usage_events
- service_usage_events
- lib
- cloud_controller/config_schemas
- database
- tasks
- spec
- api/documentation
- migrations
- helpers
- tasks
- unit/lib/database
Lines changed: 27 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
Lines changed: 27 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
Lines changed: 38 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
631 | 631 | | |
632 | 632 | | |
633 | 633 | | |
| 634 | + | |
634 | 635 | | |
635 | 636 | | |
636 | 637 | | |
| 638 | + | |
637 | 639 | | |
638 | 640 | | |
639 | 641 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
290 | 290 | | |
291 | 291 | | |
292 | 292 | | |
| 293 | + | |
293 | 294 | | |
294 | 295 | | |
295 | 296 | | |
| |||
Lines changed: 2 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| 24 | + | |
| 25 | + | |
24 | 26 | | |
25 | 27 | | |
26 | 28 | | |
| |||
Lines changed: 27 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
Lines changed: 22 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
109 | 109 | | |
110 | 110 | | |
111 | 111 | | |
| 112 | + | |
112 | 113 | | |
113 | 114 | | |
114 | 115 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
0 commit comments