概要
honker は、SQLiteに PostgresのNOTIFY/LISTEN 機能を追加する拡張機能。 耐久性のあるpub/sub・タスクキュー・イベントストリーム を提供し、 ポーリングやブローカー不要。 Rust製SQLite拡張として実装され、 Python/Node.js/Ruby/Go/Elixir/C++ など多言語対応。 WALファイルのイベント通知 で高速なプッシュセマンティクスを実現。 RedisやCelery不要 で、業務処理とキュー操作を同一トランザクションで管理可能。
honker概要と特徴
- SQLite用拡張機能 で、 PostgresのNOTIFY/LISTEN に近いpub/sub・キュー機能を実装
- Rust crate (honker, honker-core, honker-extension)として提供
- Python(honker)/Node.js(@russellthehippo/honker-node)/Bun/Ruby/Go/Elixir/C++ 向けラッパー
- on-diskレイアウトはRustで一元管理、各言語バインディングは薄いラッパー
- WALファイルの変更検知 でイベント発火、 シングルミリ秒台の通知遅延 を実現
- 耐久性のあるpub/sub、タスクキュー、イベントストリーム を1つのSQLiteファイルで管理
- ポーリング不要・デーモンや外部ブローカー不要、シンプルな運用
- トランザクション内で業務処理とキュー投入が同時コミット、ロールバックも一括
- 各種リトライ、優先度、遅延実行、デッドレター、レートリミット等もサポート
- APIは実験的段階、将来的に変更の可能性
honker導入の背景とメリット
- SQLiteがメインDB の場合、 pub/subやタスクキュー も同じファイルで完結
- RedisやCelery等の外部システム不要、バックアップや運用負荷を削減
- ordersテーブルへのINSERTとqueue.enqueueを同一トランザクションで管理
- 過去事例:pg_notify(Postgres)、Huey(Python)、pg-boss/Oban(Postgres)等を参考
- Postgres利用中ならpg_notifyやOban推奨、SQLiteユーザー向け
主要機能一覧
- 1つの.dbファイル内でプロセス間通知(notify/listen)
- リトライ・優先度・遅延・デッドレター付きワークキュー
- 業務処理とキュー投入のアトミックコミット
- ミリ秒単位の高速リアクション、ポーリング不要
- ハンドラータイムアウト、エクスポネンシャルバックオフによるリトライ
- 遅延ジョブ、タスク有効期限、ネームドロック、レートリミット
- crontab式定期タスク(リーダー選出スケジューラ付き)
- タスク結果の保存・取得(IDで管理、ワーカーが結果永続化)
- 耐久性のあるストリーム(各コンシューマごとにオフセット管理)
- SQLite拡張としてどのクライアントからも同一テーブル参照可能
- Python, Node.js, Rust, Go, Ruby, Bun, Elixir向けバインディング
クイックスタート例(Python)
-
pip install honker でインストール
-
db = honker.open("app.db") で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"): try: send(job.payload) job.ack() except Exception as e: job.retry(delay_s=60, error=str(e)) -
claim()はWALコミットで即時起床、WAL監視不可時のみ5秒ポーリング
-
デフォルトvisibilityは300秒、バッチ処理もclaim_batchで対応
タスクデコレータ(Python)
-
関数を@emails.taskで装飾し、直接enqueueせずジョブ化可能
@emails.task(retries=3, timeout_s=30) def send_email(to: str, subject: str) -> dict: ... return {"sent_at": time.time()} -
呼び出し側:r = send_email("alice@example.com", "Hi")、r.get(timeout=10)で結果取得
-
ワーカーはpython -m honker worker myapp.tasks:db --queue=emails --concurrency=4で起動
-
*定期タスクは@emails.periodic_task(crontab("0 3 * * "))で実装
ストリーム・通知(Python)
- 耐久性pub/sub:db.stream("user-events")でストリーム取得、publish/subscribeで利用
- 各コンシューマは自身のオフセットを_honker_stream_consumersで管理
- subscribeは履歴リプレイ→WAL通知でライブ配信に移行、オフセット自動保存可
- ephemeral pub/sub:db.listen("orders")でリスナ起動、tx.notify("orders", {...})で通知
- 耐久性リプレイ不要ならlisten/notify、必要ならstream/publish推奨
- 通知テーブルは自動クリーンアップされないため、db.prune_notificationsで管理
Node.js例
- const { open } = require('@russellthehippo/honker-node')でDBオープン
- トランザクションで業務処理+notifyをアトミックに実行
- for await (const n of db.listen('orders'))で通知受信
SQLite拡張機能のSQL例
- .load ./libhonker_extで拡張読込
- SELECT honker_bootstrap()で初期化
- INSERT INTO _honker_liveでキュー投入
- SELECT honker_claim_batchでジョブ取得、SELECT honker_ack_batchでACK
- 各種ロック、レートリミット、スケジューラ、ストリーム、結果保存APIも提供
設計思想とアーキテクチャ
- Python/Node/Rust/Go/Ruby/Bun/Elixir向けバインディングを同梱
- Huey(Python SQLiteキュー)を参考に設計
- Postgresならpg_notify+pg-boss/Obanが相当、honkerはSQLite向け
- 3つのプリミティブ:ephemeral pub/sub(notify)、durable pub/sub(stream)、at-least-once queue(queue)
- 全てトランザクション内INSERTでアトミック
- NOTIFY/LISTENセマンティクスをポーリング無しで実現、WALコミットごとに通知
- WALモード必須(journal_mode = WAL)
- WALファイルのstat(2)で変更検知、クロスプラットフォームで1ms精度
- .db + .db-walのみで完結、運用・スナップショット容易
- サーバープッシュ不可のため、ファイル変更→SELECTで通知
- トランザクションは安価、ジョブ・イベント・通知は全てテーブルの行として管理
注意点・非対応事項
- WALモード必須、DELETE/TRUNCATEモード非対応
- 複数ライター複製、DAG型ワークフロー等は非対応
- バックアップ先や共有ファイルシステム等、WALモード非推奨環境では利用不可
- API・仕様は今後変更の可能性あり
このように、 honker はSQLite単体で 高機能なpub/sub・タスクキュー・イベントストリーム を実現するための 軽量・高性能拡張 です。 外部システム無しで、業務処理とキュー処理のアトミック性 を重視するプロジェクトに最適です。