Skip to content

Commit d68206e

Browse files
committed
d-miner5(kat): pin daily-summary emission honesty (newest-day, no __pool__, sub-aware)
Extends the D-MINER.5 P1 notify-engine selftest (9->12) to cover the daily subcommand, which previously had no regression lock: 10) empty daily rollup -> emits nothing (no fabricated summary) 11) only the most-recent day is summarized; the __pool__ aggregate row is excluded from per-worker summaries 12) subscribed worker -> delivered; unsubscribed worker present in the rollup -> recorded undelivered (logged, never silently dropped) Safe-additive: test-only, no engine behavior change.
1 parent 7e798ba commit d68206e

1 file changed

Lines changed: 44 additions & 1 deletion

File tree

scripts/miner_notify_engine.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,13 +475,56 @@ def put(ts, worker, hr):
475475
nosub = dict(sub, enabled=0, channels=[])
476476
check(route_event(con, info_ev, nosub) is None, "unsub should route to None")
477477

478+
# --- daily-summary path (the `daily` subcommand, P1) ----------------
479+
# the sampler owns the `daily` rollup; build it here for the KAT
480+
dcon = connect(":memory:")
481+
dcon.execute("CREATE TABLE IF NOT EXISTS daily (day TEXT NOT NULL, "
482+
"worker TEXT NOT NULL, hours_online REAL NOT NULL, "
483+
"avg_hashrate REAL NOT NULL, shares INTEGER NOT NULL DEFAULT 0, "
484+
"stale_pct REAL NOT NULL DEFAULT 0, PRIMARY KEY(day,worker))")
485+
dcon.commit()
486+
dargs = argparse.Namespace(dry_run=True, smtp_host="x", smtp_port=0, sender="x")
487+
488+
# 10) no rollups yet -> daily() emits nothing (no fabricated summary)
489+
daily(dcon, dargs)
490+
nd = dcon.execute("SELECT COUNT(*) FROM notifications WHERE kind=?",
491+
(DAILY_SUMMARY,)).fetchone()[0]
492+
check(nd == 0, f"empty rollup must emit no summary, got {nd}")
493+
494+
for day, w, hrs, hr, stale in [
495+
("2026-06-25", "w1", 20.0, 90.0, 1.0),
496+
("2026-06-26", "w1", 23.5, 110.0, 0.5),
497+
("2026-06-26", "w2", 4.0, 5.0, 9.0),
498+
("2026-06-26", "__pool__", 24.0, 999.0, 0.0)]:
499+
dcon.execute("INSERT INTO daily(day,worker,hours_online,avg_hashrate,"
500+
"shares,stale_pct) VALUES(?,?,?,?,0,?)",
501+
(day, w, hrs, hr, stale))
502+
dcon.execute("INSERT INTO subscriptions(worker,channels,route,enabled) "
503+
"VALUES('w1','logonly','w1@route',1)")
504+
dcon.commit()
505+
506+
# 11) newest day only, __pool__ aggregate excluded -> w1,w2 summarized
507+
daily(dcon, dargs)
508+
drows = dcon.execute("SELECT worker,status FROM notifications WHERE kind=? "
509+
"ORDER BY worker", (DAILY_SUMMARY,)).fetchall()
510+
dworkers = sorted({r[0] for r in drows})
511+
check(dworkers == ["w1", "w2"],
512+
f"newest-day summary covers w1,w2 only (no __pool__/old day), got {dworkers}")
513+
514+
# 12) subscribed -> delivered; unsubscribed -> undelivered (honest, not dropped)
515+
dstat = dict(drows)
516+
check(dstat.get("w1") == "delivered", f"subscribed delivered, got {dstat.get('w1')}")
517+
check(dstat.get("w2") == "undelivered", f"unsubscribed undelivered, got {dstat.get('w2')}")
518+
dcon.close()
519+
520+
478521
con.close()
479522
if fails:
480523
print("SELFTEST FAILED:")
481524
for f in fails:
482525
print(" -", f)
483526
return 1
484-
print("SELFTEST OK (15/15)")
527+
print("SELFTEST OK (18/18)")
485528
return 0
486529

487530

0 commit comments

Comments
 (0)