You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Keep usage event records of running apps, service instances, and tasks
App and service usage event cleanup previously pruned every record older than
the cutoff, including the opening STARTED/CREATED event of a resource that is
still running -- which makes it impossible to reconstruct current usage once
that event ages out.
Database::OldRecordCleanup can now optionally keep "running" records. For each
lifecycle a model declares via usage_lifecycles (beginning states, ending
state, guid column), a beginning-state event (STARTED/CREATED/TASK_STARTED,
and the WAS_RUNNING/TASK_WAS_RUNNING baselines) is retained unless:
* a later ending-state event (STOPPED/DELETED/TASK_STOPPED) for the same
resource also falls outside the retention window -- the run is over; or
* it is a superseded baseline: an earlier beginning of the same run and a
later beginning both exist outside the window. Consumers only need the first
beginning of the current run (the true start time) and the latest one (the
current footprint), so the in-between events written by scaling an app or
updating a service instance are pruned and cutoff_age_in_days keeps bounding
the table size for long-running, frequently-changed resources.
The app and service usage event repositories enable the behavior with
keep_running_records: true; requesting it for a model without usage_lifecycles
raises instead of silently deleting the records of running resources. Task
events get their own lifecycle (TASK_STARTED/TASK_WAS_RUNNING -> TASK_STOPPED,
keyed by task_guid), so the start events of long-running tasks survive cleanup
as well. The task baseline state is distinct from WAS_RUNNING because task
events share the app_usage_events table but carry an empty app_guid: reusing
WAS_RUNNING would let the app lifecycle correlate every task baseline through
app_guid = '' and wrongly prune them as superseded baselines of one phantom
app (and the app backfill's stale-row sweep would delete them outright).
Deletion runs in ordered passes -- prunable beginning rows first, while the
rows that make them prunable still exist, then everything else -- so a
beginning row cannot be stranded when its pair is removed in an earlier batch.
The cleanup log line now reports the row counts BatchDelete returns instead of
issuing extra COUNT queries, and BatchDelete fetches each batch's ids in the
same query that checks for emptiness, halving evaluations of the (potentially
expensive) filtered dataset. Also renames the positional days_ago to a
cutoff_age_in_days keyword.
0 commit comments