From 9af42c8e69e9bbb863b725739ad168c160dbb7d5 Mon Sep 17 00:00:00 2001 From: "shoney.arickathil" Date: Sat, 29 Aug 2026 23:46:29 +0200 Subject: [PATCH] fix(porch-store): correct reset_at unit on the two fresh-window paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - keypool.wo:78,89 passed msg.window (µs) straight into pool_pack's remaining_ms (ms) parameter on the first-hit and post-prune-reset paths; the third call site already divided by 1000 and was correct - fix: pool_pack(1, msg.window / 1000) at both sites — a 60s window no longer reports reset_at ~16.7h away - count/allowed were unaffected (computed independently); this only hit the client-visible reset instant, on the two most common cases (new key, window rollover) - extended gate leg 16 to assert reset_at falls within a 5s band of time.now() + window_ms, not just on count — verified the assertion itself by reverting the fix, confirming leg 16 failed with the exact defect shape, then restoring it and confirming green - woc docs/examples/porch/ exits 0; web-app-accept.sh: 47 checks, 0 failures Co-Authored-By: Claude Opus 5 (1M context) (cherry picked from commit 153fd295d37905dd083823536c6781843699e455) --- docs/examples/porch/middleware/keypool.wo | 4 +-- scripts/web-app-accept.sh | 31 +++++++++++++++++------ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/docs/examples/porch/middleware/keypool.wo b/docs/examples/porch/middleware/keypool.wo index 9136316..925aea4 100644 --- a/docs/examples/porch/middleware/keypool.wo +++ b/docs/examples/porch/middleware/keypool.wo @@ -75,7 +75,7 @@ class KeyActor { if len(hits) == 0 { insert RateLimitCounter { key: msg.key, count: 1, window: now }; - return pool_pack(1, msg.window); + return pool_pack(1, msg.window / 1000); } let row = hits[0]; @@ -86,7 +86,7 @@ class KeyActor { -- sweeper; this lazy expiry on access is it. delete row; insert RateLimitCounter { key: msg.key, count: 1, window: now }; - return pool_pack(1, msg.window); + return pool_pack(1, msg.window / 1000); } row.count = row.count + 1; diff --git a/scripts/web-app-accept.sh b/scripts/web-app-accept.sh index 6978226..8e546a1 100755 --- a/scripts/web-app-accept.sh +++ b/scripts/web-app-accept.sh @@ -484,7 +484,7 @@ sleep 0.5 expect "product survives a restart (WAL)" "$(hit GET /products)" 200 '"name":"mug"' kill -TERM "$SRV" 2>/dev/null; SRV="" -# ---- 16. porch-store task 2: the key pool counts 1 then 2 ---- +# ---- 16. porch-store task 2: the key pool counts 1 then 2, reset_at is wall-clock ---- # A flat copy of porch (manifest stripped, so it compiles as one ordinary # multi-file program with a real entry point rather than the manifest's # library build) plus a tiny driver dropped into middleware/ — same @@ -494,20 +494,35 @@ KP="$W/keypool-check" cp -r "$ROOT/docs/examples/porch" "$KP" rm -f "$KP/wo.toml" rm -rf "$KP/target" -cat >"$KP/middleware/kptest_main.wo" <<'WOEOF' +KP_WINDOW_US=60000000 +cat >"$KP/middleware/kptest_main.wo" < Int { let pool = make_pool(4); - let v1 = pool_count(pool, "ip:test", 5, 60_000_000); - let v2 = pool_count(pool, "ip:test", 5, 60_000_000); - print("${v1.count} ${v2.count}"); + let v1 = pool_count(pool, "ip:test", 5, ${KP_WINDOW_US}); + let v2 = pool_count(pool, "ip:test", 5, ${KP_WINDOW_US}); + print("\${v1.count} \${v2.count} \${v1.reset_at}"); return 0; } WOEOF if kp_out="$("$WOC" --emit "$KP" -o "$KP/kptest.wob" 2>&1)"; then + kp_before_ms="$(date +%s%3N)" kp_vm="$("$WOVM" "$KP/kptest.wob" 2>&1)" - [[ "$kp_vm" == "1 2" ]] \ - && ok "keypool: two sequential counts return 1 then 2" \ - || bad "keypool" "expected '1 2', got '$kp_vm'" + kp_after_ms="$(date +%s%3N)" + read -r kp_c1 kp_c2 kp_reset <<<"$kp_vm" + # v1 is the FIRST-ever hit for this key — the "fresh window" path + # (msg.window skipped its µs->ms conversion before the fix, landing + # reset_at ~1000x too far out: a 60s window read back as ~16.7h away). + # A tight few-second band around time.now() + window_ms catches that + # regression without being timing-flaky. + kp_window_ms=$((KP_WINDOW_US / 1000)) + kp_lo=$((kp_before_ms + kp_window_ms - 5000)) + kp_hi=$((kp_after_ms + kp_window_ms + 5000)) + if [[ "$kp_c1" == "1" && "$kp_c2" == "2" && "$kp_reset" =~ ^[0-9]+$ \ + && "$kp_reset" -ge "$kp_lo" && "$kp_reset" -le "$kp_hi" ]]; then + ok "keypool: counts 1 then 2, reset_at ~window ms ahead of time.now()" + else + bad "keypool" "counts=$kp_c1,$kp_c2 reset_at=$kp_reset expected in [$kp_lo,$kp_hi]" + fi else bad "keypool" "compile: $(printf '%s' "$kp_out" | head -1)" fi