once

io.github.aurumflux20由 GitHub 账号 aurumflux20 发布v0.2.1更新于 Oct 27, 2026

Run a side effect exactly once under retries, redelivery, and concurrent workers.

发布方自己的服务:ONCE

已验证STDIO仅桌面数据库开发者工具

概览

AI 生成的概览

once 是一个本地 Python 幂等内核,让助手在重试、重投递和并发工作进程下只执行一次副作用。

可以做什么
  • 按 key 只执行一次具名副作用,重复调用者合并到已存结果
  • 识别同 key 不同负载的调用并抛出幂等冲突,而不是返回别人的缓存答案
  • 状态可存于内存、本地 SQLite 文件,或跨进程跨机器共享的 PostgreSQL
  • 通过租约接管、栅栏令牌和心跳处理工作进程崩溃,函数抛错时释放 key
  • 提供异步版本,适用于 FastAPI 风格和智能体负载
  • 内置 1,000 次并发尝试同一订单的风暴演示
适用场景
当助手或智能体调用支付、邮件、Webhook 等副作用操作,且不能在重试、重复提交或扇出时触发两次时适用。它面向需要持久、并发安全幂等保护的 Python 代码路径,而非手写的幂等表。
运行要求
作为本地进程运行,从 PyPI 包 once-kernel 安装,需要 Python 环境。未声明认证、环境变量或请求头。持久化或多进程状态需要 SQLite 文件路径或 PostgreSQL 连接串;默认内存存储仅限单进程。
安装前请注意
它保护对支付等副作用服务的调用,但本身不是支付服务商、工作流引擎,也不提供真正的网络级恰好一次保证。PostgreSQL 连接串包含凭据。存储的结果可能含个人数据,README 提到结果大小与 PII 政策。README 还提到另一个 Rust 项目和商业支持联系方式。

安装

在 SourceWeft 中

  1. 打开 控制台中的 once,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

once

Run any side effect exactly once — even when 1,000 callers demand it at the same instant.

[1,000 concurrent duplicate charges, one execution]

⚡ once — STORM DEMO1,000 concurrent attempts to charge order #777 ($49.00)
ACTUAL EXECUTIONS   :      1   ← the whole pointserved same answer  :  1,000 / 1,000elapsed             :   0.1s
💰 double-spend prevented this run: $48,951.00

That's not a mock — it's a live attack you can run right now:

bash
pip install once-kernelpython -m once.demo

The problem

Networks retry. Users double-click. Queues redeliver. AI agents re-fire tools at machine speed. Any of these turns one payment into two, one email into three, one server into two hundred.

Most teams hand-roll an idempotency table — and most of those are quietly broken under concurrent load: two identical requests both pass the "already done?" check, then both execute. The bugs are subtle, the failures are money.

once is that table done right, once, for everyone — a tiny idempotency kernel with the four defenses hand-rolled versions miss:

  1. Atomic leader election — concurrent duplicates can't all pass the check; exactly one executes, the rest coalesce onto its result.
  2. Payload fingerprinting (RFC 8785) — same key with a different body is a hard IdempotencyConflict, never someone else's cached answer.
  3. Fence tokens + generations — a crashed worker's lease can be taken over, and when the "dead" worker wakes up late, it is locked out of corrupting the record.
  4. Honest failure states — a failed attempt frees the key for retry; an unknown outcome never silently re-runs.

Use it

python
from once import Once
o = Once()
def charge():    return gateway.charge(order_id="ord_1", amount_cents=4900)
# Retries, double submits, webhook redelivery, agent fan-out → runs ONCEresult = o.run("pay:ord_1", {"order": "ord_1", "amount_cents": 4900}, charge)

One box, several processes, no database server — SQLite, nothing to install:

python
from once import Oncefrom once.sqlite import SqliteStore
o = Once(SqliteStore("/var/lib/myapp/once.db"))  # schema auto-created

Survives restarts and works across processes (WAL mode). The default MemoryStore does neither — it is per-process, so the moment you run a second worker each one keeps its own private idea of what already ran, and the guard silently stops guarding.

Several machines — share state through the Postgres you already run:

python
from once import Oncefrom once.pg import PostgresStore
o = Once(PostgresStore("postgresql://user:pass@host/db"))  # table auto-created

Async (FastAPI, agents) — sync side effects go to a worker thread, waiters park on the event loop (no thread-pool starvation under duplicate storms; there's a test that proves it):

python
from once import AsyncOnce
ao = AsyncOnce()result = await ao.run("pay:ord_1", payload, charge)

→ The full 5-minute guide

What you can rely on

If this happensYou get
Same key + same payload, againThe stored result — no second execution
Same key + different payloadIdempotencyConflict — never a silent wrong answer
1,000 concurrent first requestsOne executor; everyone else coalesces (wait=True) or is told to wait
Executing worker diesLease expires → another caller takes over
"Dead" worker wakes up lateFenced out — cannot complete, cannot fail, cannot corrupt
Long job outliving its leaseheartbeat() keeps it protected
Your function raisesKey freed — a later retry may execute

The honest model (put this on a poster): exactly-once execution + at-least-once result delivery. True network exactly-once is physically impossible — libraries claiming it are lying to you. We execute once and re-deliver the answer as many times as asked.

Tested like money depends on it

Because it does. Every claim above is enforced by the chaos suite — barrier-forced thread storms, dead-lease reclaim stampedes, zombie-writer fencing, frozen-clock timeout attacks, event-loop-starvation detection — run against both the in-memory store and real PostgreSQL on every commit (CI fails loudly if the Postgres bench is skipped). Silence in CI never means "untested."

And we run it on our own production mailer — a double-approved send replays instead of double-emailing a real prospect. Dogfood first.

Not this

  • Not a payment provider — it guards your calls to one
  • Not a workflow engine (no sagas, no multi-key transactions — by decision)
  • Not magic "exactly-once everywhere" — see the honest model above

Docs

Sibling project — EffectFence (Rust)

EffectFence (cargo add effectfence) is the Rust half of the same idea: a causal fence for tool side effects, with content-addressed certificates and an MCP proxy mode — effectfence wrap -- <any mcp server> fences another server's tool calls with zero code change (proven against once-mcp).

Use once when the side effect is Python and you want a durable store; use EffectFence when the fence lives in Rust or in front of an MCP server.

Commercial support

Free and Apache-2.0, and staying that way. If you want help applying it to a codebase that already moves money — side-effecting paths inventoried, storm-tested, fenced, with a CI test that keeps them fenced — email [email protected]. Details: the Fence Audit.

License

Apache-2.0

来源:README.md,提交 ffa6a80

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

1
  1. v0.2.1最新Sep 16, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分

其他 Once 集成