Alpha162 opened a new issue, #13906:
URL: https://github.com/apache/cloudstack/issues/13906

   ### problem
   
   Split out of #13399 at @DaanHoogland's request.
   
   `UsageManagerImpl.parse()` correctly derives its start date from the last 
successful job:
   
   ```java
   long lastSuccess = _usageJobDao.getLastJobSuccessDateMillis();
   if (lastSuccess != 0) {
       startDateMillis = lastSuccess + 1;
   }
   ```
   
   and then overwrites it with the create date of the oldest unprocessed event, 
moving it only ever *earlier*:
   
   ```java
   // make sure start date is before all of our un-processed events
   Date oldestEventDate = events.get(0).getCreateDate();
   if (oldestEventDate.getTime() < startDateMillis) {
       startDateMillis = oldestEventDate.getTime();
       startDate = new Date(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.
   
   ### The steps to reproduce the bug
   
   1. Have any row in `cloud_usage.usage_event` that cannot be successfully 
processed, #13399 gives one reliable route, but the mechanism is independent of 
cause.
   2. Let the usage job run on its normal schedule.
   3. `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.
   4. `TIMESTAMPDIFF(HOUR, start_date, end_date)` grows without bound, as does 
`exec_time`.
   5. 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.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to