0d986f60bd
web-platform-ci / Standalone decision service (no cloud credentials) (push) Has been cancelled
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
lekiwi-compatibility / cpu-compatibility (push) Has been cancelled
集成服务器托管模型、自然语言移动与有界抓放、内置 LeKiwi URL 导入和双摄像头;同步部署契约与指定域名 iframe 白名单,保留原有物理安全、会话及调用预算防护。 更新 npm 包及锁文件版本、CHANGELOG 与发布文档。提交前 typecheck、120 项定向前端测试和 44 项后端测试通过(3 项可选跳过);真实 v2 云模型抓放仍待单独验收,不包含运行密钥或构建产物。
31 lines
1.3 KiB
Python
31 lines
1.3 KiB
Python
"""Persistent shared-key quota: new cookies and worker restarts cannot reset it."""
|
|
|
|
import sqlite3
|
|
import time
|
|
from contextlib import closing
|
|
|
|
from .protocol import DecisionError
|
|
|
|
|
|
class HostedBudget:
|
|
def __init__(self, path, hourly=60, daily=600):
|
|
if not 1 <= hourly <= daily <= 10000:
|
|
raise ValueError("invalid_hosted_budget")
|
|
self.path, self.hourly, self.daily = str(path), hourly, daily
|
|
with closing(sqlite3.connect(self.path)) as db, db:
|
|
db.execute("CREATE TABLE IF NOT EXISTS calls (created REAL, weight INTEGER)")
|
|
|
|
def reserve(self, weight=1):
|
|
now = time.time()
|
|
# Synchronous short transaction, no await between checking and reserving.
|
|
with closing(sqlite3.connect(self.path, timeout=2)) as db, db:
|
|
db.execute("BEGIN IMMEDIATE")
|
|
db.execute("DELETE FROM calls WHERE created < ?", (now - 86400,))
|
|
daily = db.execute("SELECT COALESCE(SUM(weight),0) FROM calls").fetchone()[0]
|
|
hourly = db.execute(
|
|
"SELECT COALESCE(SUM(weight),0) FROM calls WHERE created >= ?", (now - 3600,)
|
|
).fetchone()[0]
|
|
if hourly + weight > self.hourly or daily + weight > self.daily:
|
|
raise DecisionError("shared_budget_exceeded", 429)
|
|
db.execute("INSERT INTO calls VALUES (?,?)", (now, weight))
|