Skip to content

Commit 183d9a5

Browse files
feat(winrate): add ConfirmationStore.handle and use stable conf_key (market/token:direction:signal_id) after dedupe
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent ba75ab9 commit 183d9a5

1 file changed

Lines changed: 44 additions & 27 deletions

File tree

webhook_server_fastapi.py

Lines changed: 44 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3543,34 +3543,51 @@ def webhook(payload: WebhookPayload):
35433543
# ─────────────────────────────────────────────
35443544
try:
35453545
if getattr(settings, "WINRATE_UPGRADE_ENABLED", False) and getattr(settings, "REQUIRE_CONFIRMATION", False):
3546-
# Build confirmation key: prefer explicit signal_id; fallback to hashed logging id + signal
3547-
if payload.signal_id:
3548-
conf_key = f"{payload.signal_id}|{sig_for_dedupe}"
3549-
else:
3550-
# signal_id_for_logging may be None here; use fallback hash if needed
3551-
payload_hash = _hash_payload(payload.model_dump())
3552-
fallback_id = f"hash_{payload_hash}"
3553-
conf_key = f"{fallback_id}|{sig_for_dedupe}"
3546+
# Build a stable confirmation key using market/token + direction + signal_id
3547+
try:
3548+
now_ts = int(time.time())
3549+
slot = current_slot_start(now_ts)
3550+
slug = slug_for_slot(slot)
3551+
try:
3552+
market = fetch_market_by_slug(slug)
3553+
except Exception:
3554+
market = None
3555+
up_token, down_token = resolve_up_down_tokens(market) if market else (None, None)
3556+
token_or_market = up_token or slug or "unknown_market"
3557+
sig_id = payload.signal_id or signal_id_for_logging or "no-signal-id"
3558+
conf_key = f"{token_or_market}:{sig_for_dedupe}:{sig_id}"
35543559

3555-
confirmed, _ = _confirmation_store.pop_if_confirmed(
3556-
conf_key,
3557-
delay=getattr(settings, "CONFIRMATION_DELAY_SECONDS", 60),
3558-
ttl=getattr(settings, "CONFIRMATION_TTL_SECONDS", 180),
3559-
)
3560-
if not confirmed:
3561-
# mark pending (idempotent)
3562-
_confirmation_store.mark_pending(conf_key, {"first_seen": time.time(), "request_id": request_id})
3563-
logger.info(f"[{request_id}] confirmation_pending: key={conf_key}")
3564-
return {
3565-
"ok": True,
3566-
"status": "pending_confirmation",
3567-
"reason": "confirmation_pending",
3568-
"message": "Signal stored, waiting for confirmation",
3569-
"confirmation_key": conf_key,
3570-
"mode": get_trading_mode_str(),
3571-
}
3572-
else:
3573-
logger.info(f"[{request_id}] confirmation_passed: key={conf_key}")
3560+
# Use new high-level handle API (returns pending/expired/confirmed)
3561+
result = _confirmation_store.handle(
3562+
conf_key,
3563+
delay=getattr(settings, "CONFIRMATION_DELAY_SECONDS", 60),
3564+
ttl=getattr(settings, "CONFIRMATION_TTL_SECONDS", 180),
3565+
payload={"first_seen": time.time(), "request_id": request_id},
3566+
)
3567+
status = result.get("status")
3568+
if status == "pending":
3569+
logger.info(f"[{request_id}] confirmation_pending: key={conf_key} delay={getattr(settings, 'CONFIRMATION_DELAY_SECONDS', 60)}s ttl={getattr(settings, 'CONFIRMATION_TTL_SECONDS', 180)}s")
3570+
return {
3571+
"status": "pending_confirmation",
3572+
"signal_id": sig_id,
3573+
"signal": sig_for_dedupe,
3574+
"key": conf_key,
3575+
"delay_seconds": getattr(settings, "CONFIRMATION_DELAY_SECONDS", 60),
3576+
"ttl_seconds": getattr(settings, "CONFIRMATION_TTL_SECONDS", 180),
3577+
}
3578+
if status == "expired":
3579+
logger.info(f"[{request_id}] confirmation_expired: key={conf_key}")
3580+
return {
3581+
"status": "pending_confirmation",
3582+
"signal_id": sig_id,
3583+
"signal": sig_for_dedupe,
3584+
"key": conf_key,
3585+
}
3586+
# confirmed -> continue pipeline
3587+
if status == "confirmed":
3588+
logger.info(f"[{request_id}] confirmation_passed: key={conf_key}")
3589+
except Exception:
3590+
logger.exception(f"[{request_id}] confirmation_store error, continuing without confirmation")
35743591
except Exception:
35753592
# Fail-safe: if confirmation store has issues, continue processing (do not block pipeline)
35763593
logger.exception(f"[{request_id}] confirmation_store error, continuing without confirmation")

0 commit comments

Comments
 (0)