MCPcopy Create free account
hub / github.com/Roy3838/Observer / _write_rollup

Function _write_rollup

api/usage_log.py:261–291  ·  view source on GitHub ↗
(batch: list[tuple])

Source from the content-addressed store, hash-verified

259
260
261async def _write_rollup(batch: list[tuple]) -> None:
262 counts: dict[tuple[str, str, str, str], int] = defaultdict(int)
263 for ts, user_id, service, _host in batch:
264 counts[(user_id, ts.strftime("%Y-%m"), service, ts.strftime("%d"))] += 1
265
266 # Group the batch by hash first, so chunking splits between hashes rather
267 # than through the middle of one and every EXPIRE lands with its HINCRBYs.
268 by_key: dict[str, list] = defaultdict(list)
269 for (user_id, month, service, day), n in counts.items():
270 by_key[_rollup_key(user_id, month)] += [_rollup_field(service, day), n]
271
272 global _rollup_script
273 redis = await get_redis()
274 if _rollup_script is None:
275 _rollup_script = redis.register_script(_ROLLUP_LUA)
276
277 items = list(by_key.items())
278 for start in range(0, len(items), ROLLUP_CHUNK):
279 chunk = items[start:start + ROLLUP_CHUNK]
280 # Keys are addressed by index from ARGV so each hash is named once,
281 # however many of its fields the batch touches.
282 keys = [k for k, _ in chunk]
283 argv: list = [ROLLUP_TTL_DAYS * 86400]
284 for i, (_key, fields) in enumerate(chunk, start=1):
285 for j in range(0, len(fields), 2):
286 argv += [i, fields[j], fields[j + 1]]
287 # Each chunk is independent. A failure part-way through leaves earlier
288 # chunks applied, which is the same partial-batch outcome the caller
289 # already tolerates - these counters are explicitly approximate, and
290 # HINCRBY is not idempotent so retrying would double-count.
291 await _rollup_script(keys=keys, args=argv)
292
293
294async def _flush(batch: list[tuple]) -> None:

Callers 1

_flushFunction · 0.85

Calls 3

get_redisFunction · 0.90
_rollup_keyFunction · 0.85
_rollup_fieldFunction · 0.85

Tested by

no test coverage detected