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
and then overwrites it with the create date of the oldest unprocessed event, moving it only ever earlier:
// make sure start date is before all of our un-processed eventsDateoldestEventDate = events.get(0).getCreateDate();
if (oldestEventDate.getTime() < startDateMillis) {
startDateMillis = oldestEventDate.getTime();
startDate = newDate(startDateMillis);
}
events comes from UsageEventDaoImpl.listLatestEvents() — WHERE processed = 0 AND created <= ? ORDER BY createDate ASC, with no limit and no floor.
Consequence: any event that can never be successfully processed pins the aggregation start date permanently. Each subsequent run re-aggregates from that date to the present, growing by one aggregation range per range elapsed. The job continues to report success = 1 throughout, so nothing surfaces as an error.
Measured on an affected 4.22.1.0 deployment:
1,678 consecutive successful jobs whose start_millis never advanced past a single event 71 days earlier
exec_time of 2,555,055 ms (42.6 min) per hourly run, growing by 24 aggregation periods per day
cloud_usage at 54.4M rows / 14 GB, of which roughly 150k rows were genuine; duplicate counts were an exact multiple of the number of replays
Not specific to one event type:#13112 was reported on 4.21.0.0 against usage_type = 13, predating the volume-specific trigger in #13399. The rewind is the common mechanism; the triggering event type varies.
versions
Observed on CloudStack 4.22.1.0 (EL9 packages), MySQL 8.x / InnoDB, with usage.stats.job.aggregation.range = 60 and usage.stats.job.exec.time = 00:15.
#13112 reports the same mechanism on 4.21.0.0, so this is not new in 4.22.
SELECT id, start_date, end_date, exec_time FROM cloud_usage.usage_job WHERE success = 1 ORDER BY id DESC LIMIT 5; — start_date stays pinned at the oldest unprocessed event's created while end_date advances.
TIMESTAMPDIFF(HOUR, start_date, end_date) grows without bound, as does exec_time.
Row counts in cloud_usage.cloud_usage per period equal the number of times that period has been re-aggregated.
What to do about it?
Bound the rewind, and/or provide a way to quarantine or age out events that repeatedly fail to process, so one unprocessable row cannot halt aggregation indefinitely.
This is a design decision rather than an obvious patch, which is why it's raised separately from #13399.
problem
Split out of #13399 at @DaanHoogland's request.
UsageManagerImpl.parse()correctly derives its start date from the last successful job:and then overwrites it with the create date of the oldest unprocessed event, moving it only ever earlier:
eventscomes fromUsageEventDaoImpl.listLatestEvents()—WHERE processed = 0 AND created <= ? ORDER BY createDate ASC, with no limit and no floor.Consequence: any event that can never be successfully processed pins the aggregation start date permanently. Each subsequent run re-aggregates from that date to the present, growing by one aggregation range per range elapsed. The job continues to report
success = 1throughout, so nothing surfaces as an error.Measured on an affected 4.22.1.0 deployment:
start_millisnever advanced past a single event 71 days earlierexec_timeof 2,555,055 ms (42.6 min) per hourly run, growing by 24 aggregation periods per daycloud_usageat 54.4M rows / 14 GB, of which roughly 150k rows were genuine; duplicate counts were an exact multiple of the number of replaysNot specific to one event type: #13112 was reported on 4.21.0.0 against
usage_type = 13, predating the volume-specific trigger in #13399. The rewind is the common mechanism; the triggering event type varies.versions
Observed on CloudStack 4.22.1.0 (EL9 packages), MySQL 8.x / InnoDB, with
usage.stats.job.aggregation.range = 60andusage.stats.job.exec.time = 00:15.#13112 reports the same mechanism on 4.21.0.0, so this is not new in 4.22.
The steps to reproduce the bug
cloud_usage.usage_eventthat cannot be successfully processed, Usage Server repeatedly reprocesses historical usage and creates duplicate cloud_usage records for usage_type=1 #13399 gives one reliable route, but the mechanism is independent of cause.SELECT id, start_date, end_date, exec_time FROM cloud_usage.usage_job WHERE success = 1 ORDER BY id DESC LIMIT 5;—start_datestays pinned at the oldest unprocessed event'screatedwhileend_dateadvances.TIMESTAMPDIFF(HOUR, start_date, end_date)grows without bound, as doesexec_time.cloud_usage.cloud_usageper period equal the number of times that period has been re-aggregated.What to do about it?
Bound the rewind, and/or provide a way to quarantine or age out events that repeatedly fail to process, so one unprocessable row cannot halt aggregation indefinitely.
This is a design decision rather than an obvious patch, which is why it's raised separately from #13399.