russellromney/honker

GitHub: russellromney/honker

honker是一个SQLite扩展,提供轻量级的通知和任务队列功能。

Stars: 2765 | Forks: 67


honker

`honker` 是一个 SQLite 扩展和语言绑定,它为 SQLite 添加了 Postgres 风格的 `NOTIFY`/`LISTEN` 语义,内置 持久的 pub/sub、任务队列和事件流,无需客户端轮询 或守护进程/代理。任何可以 `SELECT load_extension('honker')` 的语言都获得相同的功能。 `honker` 用单个微秒级的 `PRAGMA data_version` 读取替换了队列表轮询。默认监视器每 1 毫秒 检查一次,提供类似推送的语义和单数毫秒级的跨进程 交付;当较低的空闲 CPU 比最低延迟唤醒更重要时 提高监视器间隔。 如果 SQLite 是您的首选数据存储,队列应位于同一文件中。`INSERT INTO orders` 和 `queue.enqueue(...)` 可以在 同一事务中提交。回滚将删除两者。 有关指南和 API 详细信息,请参阅 [honker.dev](https://honker.dev),以及 [绑定支持](BINDINGS.md) 了解每个绑定支持的内容。 [Simon Willison 突出了 honker](https://simonwillison.net/2026/Apr/24/honker/) 作为 SQLite 的交易性出站模式实现。 ## 快速入门 ``` pip install honker ``` ``` import honker db = honker.open("app.db") emails = db.queue("emails") with db.transaction() as tx: tx.execute("INSERT INTO orders (user_id) VALUES (?)", [42]) emails.enqueue({"to": "alice@example.com"}, tx=tx) async for job in emails.claim("worker-1"): send_email(job.payload) job.ack() ``` 入队与订单插入是原子的。另一个进程中的 当事务提交时,工作员会唤醒。 ## 它做什么 - 在一个 SQLite `.db` 文件上跨进程通知/监听 - 可持久至少一次队列,具有重试、延迟作业、优先级、 可见性超时、死信行和任务结果存储 - 可持久流,具有每个消费者的偏移量 - 基于时间的调度,使用 cron 和 `@every ` 表达式 - 命名锁、速率限制和交易性出站助手 - 通过 SQLite 可加载扩展的 SQL 函数 - 轻量级绑定,支持 Python、Node.js、Rust、Go、Ruby、Bun、Elixir、C++、 .NET / C#、Java/JVM 和 Kotlin 故意不包括:工作流 DAG、任务链/组/和弦、多写者复制, 或跨机器的分布式锁定。 ## 为什么 SQLite 越来越多地成为已发布项目的数据库。这些项目 最终需要 pub/sub 和任务队列。通常的答案是 "添加 Redis + Celery。" 这有效,但它引入了第二个数据存储,它有自己的 备份故事,业务表和队列之间的双写问题,以及一个代理来运行。 Honker 采用的方法是,如果 SQLite 是主要的数据存储,队列应位于同一文件中。队列只是表中的行 具有部分索引。每个绑定都使用相同的模式和解耦器, 因此一种语言可以入队工作,另一种语言可以获取它。 ## 设计 Honker 围绕三个部分构建: - 带有 `notify()` / `listen()` 的短暂 pub/sub - 带有每个消费者偏移量的持久流 - 带有可见性超时和重试的最少一次队列 所有三个都是您事务内的 INSERT。将 `queue.enqueue(...)`、`stream.publish(...)` 或 `notify(...)` 放在 创建工作的写入旁边。提交将留下两行。回滚将删除两行。 SQLite 没有服务器端推送通道,因此 honker 使用共享监视器。 稳定的后端每毫秒读取 `PRAGMA data_version`;当计数器改变时, 监听器重新读取索引的 SQLite 状态。 如果您使用您应用程序的现有 SQLite 文件,honker 将在 每次提交该文件时唤醒工作员。大多数唤醒将不会找到给定 队列或通道的工作。这种过度触发是有意的:一个索引 SELECT 很便宜,而一个错过唤醒是一个正确性错误。稳定的语义是: - 在提交更新时唤醒 - 忽略回滚的工作 - 在每次唤醒后重新读取 SQLite 状态 - 使用基于文件的 SQLite 数据库,而不是 `:memory:` 可选的源构建后端也存在,用于内核文件事件和 WAL 共享内存读取。有关哪些绑定公开后端选项以及 CI 证明的内容,请参阅 [绑定支持](BINDINGS.md)。 Honker 是单机文件后端的。SQLite 的锁定模型是为一个主机写入一个数据库文件而设计的;两个服务器通过 NFS 写入相同的 `.db` 不是 Honker 部署策略。 ## 先前艺术 [`pg_notify`](https://www.postgresql.org/docs/current/sql-notify.html) 为 Postgres 提供了快速的触发器,但没有重试或可见性超时。 [pg-boss](https://github.com/timgit/pg-boss) 和 [Oban](https://hexdocs.pm/oban/) 是我们在 SQLite 上追求的 Postgres 方面的黄金标准。 [Huey](https://github.com/coleifer/huey) 是一个 一个出色的 SQLite 后备 Python 任务队列。如果您已经运行 Postgres, 使用 Postgres 工具,因为它们很出色。 交易性出站想法也归功于 Brandur Leach 的 [Postgres 中的交易性阶段作业清除](https://brandur.org/job-drain): 在业务行相同的交易中写入作业行,然后让 工作员在提交后交付它。 ## 绑定 | 生态系统 | 包 / 路径 | 备注 | | --- | --- | --- | | Python | `pip install honker` | 包含 Python API 和可加载扩展的电池包;发布轮盘中包含 | | Node.js | `npm install @russellthehippo/honker-node` | 原生 Node 绑定 | | Ruby | `gem install honker` | 可用平台上的预编译原生 gem | | .NET / C# | `dotnet add package Honker` | 包含捆绑运行时资源的 NuGet 包 | | Rust | `honker`, `honker-core`, `honker-extension` | 核心引擎和 Rust 包装器 | | Elixir | Hex 包 `honker` | 解耦器支持的 Elixir 绑定 | | Go, Bun, C++, JVM, Kotlin | 在 `packages/` 中 | 在树内维护的绑定 | | SQLite | `honker-extension` | 适用于任何 SQLite 3.9+ 客户端的可加载扩展 | 详细的兼容性表位于 [BINDINGS.md](BINDINGS.md). 语言特定的安装和 API 说明位于每个包的 README 中。 ## SQL 扩展 任何可以加载扩展的 SQLite 客户端都可以直接使用 honker: ``` .load ./libhonker_ext SELECT honker_bootstrap(); INSERT INTO _honker_live (queue, payload) VALUES ('emails', '{"to":"alice"}'); SELECT honker_claim_batch('emails', 'worker-1', 32, 300); -- JSON array SELECT honker_ack_batch('[1,2,3]', 'worker-1'); -- DELETEs; returns count SELECT honker_sweep_expired('emails'); -- count moved to dead SELECT honker_lock_acquire('backup', 'me', 60); -- 1 = got it, 0 = held SELECT honker_lock_release('backup', 'me'); -- 1 = released SELECT honker_rate_limit_try('api', 10, 60); -- 1 = under, 0 = at limit SELECT honker_rate_limit_sweep(3600); -- drop windows >1h old SELECT honker_cron_next_after('0 3 * * *', unixepoch()); -- 5-field cron SELECT honker_cron_next_after('*/2 * * * * *', unixepoch()); -- 6-field cron SELECT honker_cron_next_after('@every 5s', unixepoch()); -- interval schedule SELECT honker_scheduler_register('nightly', 'backups', '0 3 * * *', '"go"', 0, NULL); -- periodic task SELECT honker_scheduler_tick(unixepoch()); -- JSON: fires due SELECT honker_scheduler_soonest(); -- min next_fire_at SELECT honker_queue_next_claim_at('emails'); -- next run/reclaim deadline SELECT honker_stream_publish('orders', 'k', '{"id":42}'); -- returns offset SELECT honker_stream_read_since('orders', 0, 1000); -- JSON array SELECT honker_stream_save_offset('worker', 'orders', 42); -- monotonic upsert SELECT honker_stream_get_offset('worker', 'orders'); -- offset or 0 SELECT honker_result_save(42, '{"ok":true}', 3600); -- save w/ 1h TTL SELECT honker_result_get(42); -- value or NULL SELECT honker_result_sweep(); -- prune expired SELECT notify('orders', '{"id":42}'); SELECT honker_enqueue('emails', '{"to":"alice@example.com"}', NULL, NULL, 0, 3, NULL); ``` 该扩展与语言绑定共享表,因此 Python 工作员可以获取由 SQL、Node、Ruby、Go 或任何其他 绑定编写的作业。 ## 架构 - 每个 `Database` 一个 `PRAGMA data_version` 监视器;默认 Rust 支持的监视器节奏是 1 毫秒,可以提升 - 计数器变化将唤醒每个监听器/工作员/订阅者 - 订阅者使用索引 SELECT 重新读取 SQLite 状态 - 100 个订阅者仍然共享一个监视器 - 空闲监听器运行零队列/通知 SELECT 队列获取是通过部分索引的一个 `UPDATE ... RETURNING`: `(queue, priority DESC, run_at, id) WHERE state IN ('pending','processing')`。 确认是一个 `DELETE`。重试耗尽的作业移动到 `_honker_dead`,因此 获取速度取决于挂起/处理作业,而不是旧队列历史。 语言绑定默认使用 WAL,因为它提供了具有一个写者和一个并发读者的并发读取器, 以及高效的 fsync 批处理。其他日志模式仍然有效。正确性和跨进程唤醒不依赖于 WAL;唤醒路径 是 SQLite 自己的 `data_version` 计数器。 ## ORMs 和框架 Honker 不提供框架插件。在您的框架或 ORM 连接上加载扩展,运行 `honker_bootstrap()`, 并在 ORM 的交易中调用 SQL 函数。 这适用于 SQLAlchemy、SQLModel、Django、Drizzle、Kysely、sqlx、GORM、ActiveRecord、Ecto、Hibernate、jOOQ、MyBatis、和 Exposed。有关 ORM 指南,请参阅 [honker.dev/guides/orm](https://honker.dev/guides/orm/). ## 性能 在现代笔记本电脑上,honker 可以处理每秒数千条消息。 跨进程唤醒延迟由监视器节奏设置,默认为 1 毫秒。使用以下方法 在您的硬件上测量: ``` python bench/wake_latency_bench.py --samples 500 python bench/real_bench.py --workers 4 --enqueuers 2 --seconds 15 ``` ## 开发 ``` make test # Rust + Python + Node fast path make test-all # broader suite, including slower tests make build # build Python package + loadable extension cargo build --release -p honker-extension ``` 仓库布局: ``` honker-core/ # shared Rust engine honker-extension/ # SQLite loadable extension packages/ # language bindings tests/ # cross-package integration tests bench/ # benchmarks ``` ## 文档 - [绑定支持](BINDINGS.md) - [Python 示例](packages/honker/examples/README.md) - [基准测试](bench/README.md) - [路线图](ROADMAP.md) - [变更日志](CHANGELOG.md) - [honker.dev](https://honker.dev) ## 许可证 Apache-2.0 OR MIT。请参阅 [LICENSE](LICENSE).
标签:DNS解析, MITM代理, PostgreSQL, SQLite, 事件流, 事务, 代码库, 任务调度, 原子操作, 发布订阅, 可视化界面, 延迟任务, 开源项目, 性能优化, 扩展模块, 技术博客, 持久化队列, 数据库, 日志审计, 检测绕过, 死信队列, 消息队列, 社区推荐, 结果存储, 语言绑定, 跨进程通信, 逆向工具, 锁