展示 HN:Honker – SQLite に PostgreSQL の NOTIFY/LISTEN セマンティクスを実装

2026/04/23 20:53

展示 HN:Honker – SQLite に PostgreSQL の NOTIFY/LISTEN セマンティクスを実装

RSS: https://news.ycombinator.com/rss

要約

Japanese Translation:

Honker は、Rust をベースとしたライブラリで、外部サーバーやポーリングなしに耐障害なパブ/サブ、タスクキューイング、およびイベントストリームを提供するように SQLite を拡張します。その核心的な利点は、非効率な time-wait ループを SQLite の Write-Ahead Log (WAL) 上の直接のファイル通知で置き換えることにあり、これにはデータベース毎に専用

stat(2)
スレッドを使用する軽量アーキテクチャが用いられ、1ms ごとの変更ポーリングを可能にします。これにより、単一の桁のミリ秒でのクロスプロセスメッセージ配信が即座に行えながら、メモリ使用量を最小限に抑え、アイドル状態のリスナーはトリガーされるまで SQL クエリを実行しないままにできます。「トランザクショナルアウブックス」パターン(
notify()
および
stream.publish()
などの機能を通じて)を活用することで、Honker はイベントの公開とタスクの処理の間での一貫性を確保し、言語境界を越えてもデータ損失を防ぎます。

Rust クレートとして提供され、ロード可能な拡張機能 (

_honker_live
,
_honker_dead
,
_honker_notifications
) および Python、Node.js、Bun、Ruby、Go、Elixir、C++ 用のバインディングを持ち、シームレスなマルチランゲージ相互運用性を可能にします。しかし、すべてのデータベースが WAL モードで構成されることを要求し(WAL 非ファイルは拒否)、特定のアーキテクチャ制約により複雑なワークフローオーケストレーション、タスクパイプライン、またはマルチライターレプリケーションシナリオには適していません。保持ポリシーは呼び出し元によって定義され (
db.prune_notifications()
)、かつクラッシュ回復は安全で、
SIGKILL
のような障害後にクレームを回収するために可視化タイムアウト(デフォルト 300s)を利用します。DAG ベースのオーケストレーションをサポートしないものの、手動での保持とデッドレターテーブルが長期データ管理を処理するイベント駆動システム向けの堅牢で低オーバーヘッドな解決策を提供します。

本文

Honker は、SQLite を拡張し、PostgreSQL 風の NOTIFY/LISTEN セマンティクスを追加する言語バインディングおよび SQLite 拡張モジュールです。クライアントからのポーリングやデーモン/ブローカーを必要とせず、堅牢なパブリッシュ・サブスクライブ(pub/sub)、タスクキュー、そしてイベントストリームを組み込んでいます。

SELECT load_extension('honker')
をサポートできる任意の言語が、同じ機能を享受できます。

Honker は以下の形態で提供されます:

  • Rust クレイト (honker, 加えて honker-core/honker-extension)
  • SQLite にロード可能な拡張モジュール
  • ライブラリパッケージ:Python (honker), Node (@russellthehippo/honker-node), Bun (@russellthehippo/honker-bun), Ruby (honker), Go, Elixir, C++

ディスク上のレイアウトは Rust で一度定義され、各言語バインディングはこのロード可能な拡張モジュールの薄いラッパーとして機能します。

Honker の仕組み: Honker は、ポーリングインターバルを SQLite の WAL ファイル(Write-Ahead Log)におけるイベント通知に置き換えることで動作し、プッシュ型セマンティクスを実現します。これにより、クロスプロセス間での通知が可能となり、単一桁のミリ秒単位の配信遅延を実現します。

実験的機能。API は変更される可能性があります。

課題と解決策

SQLite は現在、多数のプロジェクトで採用されているデータベースです。しかし、それらには必然的に pub/sub やタスクキューが必要です。従来の対応策として「Redis + Celery の追加」という方法がありますが、それは動作はしますが、追加のデータストレージ(独自のバックアップ戦略が必要)を導入し、ビジネステーブルとキュー間の二重書き込み問題を引き起こします。さらに、ブローカーを運用するオーバーヘッドも伴います。

Honker は、「SQLite が主データベースであれば、タスクキューも同じファイルに存在させるべきである」というアプローチを採用しています。 これはつまり、

INSERT INTO orders
queue.enqueue(...)
を同一のトランザクションでコミットできることを意味します。ロールバック時には両方が削除されます。キューは単なる表内の行、部分インデックスを持つものです。

先行技術:

  • pg_notify(高速なトリガーだが、再試行や可視性に関する保証がない)
  • Huey(SQLite を基盤とする Python ライブラリ)
  • pg-boss および Oban(Postgres 側での事実上のゴールドスタンダードであり、Honker が SQLite で実現を目指しているもの) もしすでに Postgres を利用している場合は、これらの優れたライブラリを使用することを推奨します。

概要 (At a Glance)

import honker

db = honker.open("app.db")
emails = db.queue("emails")

# キューイング (Queueing)
emails.enqueue({"to": "alice@example.com"})

# クライアントによる消費 (Worker プロセス)
async for job in emails.claim("worker-1"):
    send(job.payload)
    job.ack()

任意のキューイング操作は、ビジネスロジックの書き込みと原子性を持って実行できます(コミットするかロールバックするか)。

with db.transaction() as tx:
    tx.execute("INSERT INTO orders (user_id) VALUES (?)", [42])
    emails.enqueue({"to": "alice@example.com"}, tx=tx)

特徴 (Features)

現在のバージョン:

  • 一つの .db ファイル上でクロスプロセス間での notify/listen
  • 再試行、優先度、遅延ジョブ、デッドレターテーブルを備えたワークキュー
  • 送信操作がビジネスロジックの書き込みと原子性を持って実行可能(共にコミットまたはロールバック)
  • ポーリングなしで、単一桁のミリ秒単位のクロスプロセス反応時間
  • ハンドラータイムアウト、指数関数的な退避を伴う宣言的再試行機能
  • 遅延ジョブ、タスクの有効期限、名前付きロック、レート制限
  • リーダー選出スケジューラによる Crontab 風のパériオディックタスク
  • オプトインのタスク結果保存機能(enqueue は ID を返す。ワーカーは戻り値を永続化し、コールラーは queue.wait_result(id) で待つ)
  • パーコンシューマーオフセットと設定可能なフラッシュ間隔を備えた堅牢なストリーム
  • 任意の SQLite クライアントが同じテーブルを読み取れるようにする SQLite ロード可能拡張モジュール
  • バインディング:Python, Node.js, Rust, Go, Ruby, Bun, Elixir

意図的に構築されていない機能: タスクパイプライン/チェーン/グループ/コード、マルチライターレプリケーション、DAG を使ったワークフローオーケストレーション。

クイックスタート (Quick Start)

Python: キュー(永続的アトミックスリムスワンス・ワーク)

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"):               # WAL コミットで目覚める
    try:
        send(job.payload); job.ack()
    except Exception as e:
        job.retry(delay_s=60, error=str(e))

claim()
は非同期イテレーターです。各反復は
claim_batch(worker_id, 1)
に相当します。WAL コミットで目覚め、WAL ワッチャが発火できない場合にのみ 5 秒の過保護なポーリングにフォールバックします。バッチ処理の場合は明示的に
claim_batch(worker_id, n)
を呼び出し、
queue.ack_batch(ids, worker_id)
で承認してください。デフォルト:可視性タイムアウトは 300 秒です。

Python: タスク (Huey スタイルの装飾子)

手動で

queue.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")   # キューイングし、TaskResult を返す
print(r.get(timeout=10))                    # ワーカーが実行するまでブロック

# ワーカー側(同一プロセスまたは独立したプロセスとして)
python -m honker worker myapp.tasks:db --queue=emails --concurrency=4

自動名前は

{module}.{qualname}
です(Huey/Celery の慣習)。本番環境では
@emails.task(name="...")
で明示的な名前を指定することを推奨します。リネームによって未解決のジョブが孤立するのを防ぐためです。定期的なタスクには
@emails.periodic_task(crontab("0 3 * * *"))
を使用します。詳細は packages/honker/examples/tasks.py を参照してください。

Python: ストリーム(永続的なパブリッシュ・サブスクライブ)

stream = db.stream("user-events")

with db.transaction() as tx:
    tx.execute("UPDATE users SET name=? WHERE id=?", [name, uid])
    stream.publish({"user_id": uid, "change": "name"}, tx=tx)

async for event in stream.subscribe(consumer="dashboard"):
    await push_to_browser(event)

各名前付きコンシューマーは

_honker_stream_consumers
テーブル内で独自のオフセットを管理します。
subscribe
は保存されたオフセット以降の行を再生し、WAL で目覚めるとライブ配信に切り替わります。イテレーターは、最大 1000 イベントごとか 1 秒ごと(どちらか先)にオフセットを自動的に保存するため、高スループットストリームが単一ライターのスロットを叩き続けるのを防ぎます。
save_every_n=
または
save_every_s=
で上書きしたり、両方を 0 に設定して自動保存を無効化し、自分で
stream.save_offset(consumer, offset, tx=tx)
を呼び出したりできます(そのトランザクション内で行った操作と原子性を持って)。少なくとも一度:クラッシュした場合は、最後のフラッシュされたオフセットまで飛行中(in-flight)のイベントを再配信します。

Python: 通知 (Ephemeral pub/sub)

async for n in db.listen("orders"):
    print(n.channel, n.payload)

with db.transaction() as tx:
    tx.execute("INSERT INTO orders (id, total) VALUES (?, ?)", [42, 99.99])
    tx.notify("orders", {"id": 42})

リスナーは現在の MAX(id) でアタッチされ、履歴は再生されません。永続的な再生が必要な場合は

db.stream()
を使用してください。通知テーブルは自動で剪定(prune)されません。計画的なタスクから
db.prune_notifications(older_than_s=…, max_keep=…)
を呼び出してください。タスクペイロードは有効な JSON でなければならず、Python のライターと Node リーダーが同じチャンネルを共有できるようにする必要があります。

Node.js

const { open } = require('@russellthehippo/honker-node');
const db = open('app.db');

// 原子性:ビジネス書き込み + 通知が一緒にコミット
const tx = db.transaction();
tx.execute('INSERT INTO orders (id) VALUES (?)', [42]);
tx.notify('orders', { id: 42 });
tx.commit();

// Listen は WAL コミットで目覚め、チャンネルでフィルタリング
for await (const n of db.listen('orders')) {
  handle(n.payload);
}

SQLite 拡張モジュール (任意の SQLite 3.9+ クライアント)

.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 アレイ
SELECT honker_ack_batch('[1,2,3]', 'worker-1');              -- 削除;件数を返す
SELECT honker_sweep_expired('emails');                       -- デッドに移動する件数
SELECT honker_lock_acquire('backup', 'me', 60);              -- 1 = 取得成功、0 = 保持中
SELECT honker_lock_release('backup', 'me');                  -- 1 = 解放
SELECT honker_rate_limit_try('api', 10, 60);                 -- 1 = リミット以下、0 = リミット到達
SELECT honker_rate_limit_sweep(3600);                        -- 1 時間以上前のウィンドウを削除
SELECT honker_cron_next_after('0 3 * * *', unixepoch());     -- 次の発火の UNIX タイムスタンプ
SELECT honker_scheduler_register('nightly', 'backups',
  '0 3 * * *', '"go"', 0, NULL);                             -- パーイオディックタスクを登録
SELECT honker_scheduler_tick(unixepoch());                   -- JSON: 発火すべきもの
SELECT honker_scheduler_soonest();                            -- 次の最小発火時刻
SELECT honker_scheduler_unregister('nightly');                -- 1 = 削除成功
SELECT honker_stream_publish('orders', 'k', '{"id":42}');     -- オフセットを返す
SELECT honker_stream_read_since('orders', 0, 1000);           -- JSON アレイ
SELECT honker_stream_save_offset('worker', 'orders', 42);     -- 単調増加アップsert
SELECT honker_stream_get_offset('worker', 'orders');          -- オフセットまたは 0
SELECT honker_result_save(42, '{"ok":true}', 3600);           -- 1 時間の TTL で保存
SELECT honker_result_get(42);                                  -- 値または NULL
SELECT honker_result_sweep();                                  -- 有効期限切れたものを剪定
SELECT notify('orders', '{"id":42}');

この拡張モジュールは、Python バインディングと同じ

_honker_live
,
_honker_dead
, および
_honker_notifications
を共有するため、Python ワーカーが拡張モジュール経由で別の言語からプッシュされたジョブを主張(claim)できます。スキーマ互換性は tests/test_extension_interop.py で固定されています。

アーキテクチャ (Design)

このリポジトリには Honker SQLite ロード可能拡張モジュールと、Python, Node, Rust, Go, Ruby, Bun および Elixir 用のバインディングが含まれています。ほとんどのアプリケーションでは、SQLite のみで十分です。すでに SQLite を基盤とした堅牢なメッセージングを行う優れたライブラリが存在します。Huey は Honker が最も多く参照するものです。このプロジェクトは Huey に触発され、パッケージロジックを SQLite 拡張モジュールに移動させることで、言語やフレームワークを横断して類似の機能を提供することを目指しています。Postgres を基盤とするアプリケーションには pg_notify + pg-boss または Oban が同等の役割を果たします。このライブラリは、SQLite が主データベースであるアプリケーション向けです。

拡張モジュールにはそれを結び付ける 3 つのプリミティブがあります:一時的な pub/sub (

notify()
), パーコンシューマーオフセットを備えた永続的な pub/sub (
stream()
), および少なくとも一度(at-least-once)の実行保証を持つワークキュー (
queue()
). これら三つはすべて、あなたのトランザクション内での INSERT であり、タスクの「送信」がビジネスロジックの書き込みと原子性を持って実行でき、ロールバックすると全て削除されることを可能にします。明確な目標は、ポーリングなしで NOTIFY/LISTEN セマンティクスを実現することであり、単一桁のミリ秒単位の反応時間を達成することです。既存の SQLite ファイル(ビジネスロジックを含む)を使用する場合、それは WAL 各コミットでワーカーを通知します。つまり、ほとんどのトリガーは何も起こらなくなります:代わりに、ワーカーは結果なしにメッセージ/キューを読み取りますのみになります。この「過剰なトリガー(overtriggering)」は意図的であり、プッシュ型セマンティクスと高速反応時間のためのトレードオフです。

WAL 専用設計 (WAL-only by design)

Honker は管理するすべてのデータベースに対して

journal_mode = WAL
を必要とします。
honker_bootstrap()
は WAL モードではないファイルベースの DB では実行を拒否し、言語バインディングはデフォルトのオープンパスで
PRAGMA journal_mode = WAL
を設定します。

ワーカーはライフタイム全体にわたって読み取りビュー(WAL サブスクリプションチャンネル、リスナーイテレーター)を開いたままに保ちます。DELETE/TRUNCATE モードでは、ライターの独占ロックを取得し、アクティブなリーダは解放されるまでブロックされます。単一のワーカーが積極的に主張(claim)すると、システム全体の

enqueue()
/
notify()
をシリアライズしてしまいます。WAL はリーダーとライターを共存させることができます。

.db-wal サイドカーは各コミットで成長し、チェックポイント時にのみ縮小します。ステータスポーリングにより、単調で曖昧さのない変化シグナルを得られます。DELETE モードの .db-journal サイドカーはトランザクション中に現れ、コミットすると消滅するため、ステータスポーリングのターゲットとしては不適切です。

wal_autocheckpoint = 10000
を使用すれば、WAL は各コミットごとにではなく、1 万ページごとに 1 回の fsync を実行します。スループットの向上の大部分はこのためです。

SQLite データベースが WAL モードに入らないことを必要とする場合(例:バックアップターゲットや、共有ファイルシステムでの .db-wal/.db-shm サイドカーを避けるため)、Honker は適切なツールではありません。通常の SQLite を使用し、NOTIFY/LISTEN セマンティクスなしで使用してください。ライブラリ/拡張モジュールは、SQLite の特性とシングルサーバーアーキテクチャに構築された小さな調整層です。

一つの .db + 一つの .db-wal がシステム全体です。あなたが既に利用している SQLite の利点(埋め込み、ローカル、堅牢、スナップショット可能)をすべて受け取ります。WAL モードは書き込み一人と並列リーダを可能にします。主張(Claim)は部分インデックスを使用した

UPDATE … RETURNING
一つです。承認(ack)は DELETE 一つです。WAL ファイルは各コミットで成長するため、(size, mtime) がクロスプロセスのコミットシグナルとなります。SQLite はワイヤプロトコルを持っていません。消費者は読み取りを主導しなければならず、サーバープッシュは不可能です。目覚めシグナル = ファイル変化 → SELECT です。トランザクションは安価であるため、ジョブ、イベント、通知は、
db.transaction()
ブロック内での「アウトバックス」型パターンの行として呼び出し側で存在します。

クロスプラットフォームで

stat(2)
を使用し、技術的には優れた FSEvents/inotify/kqueue 代わりに使用しています。FSEvents は macOS ではサマードプロセスの書き込みをドロップするため、同じ Python プロセス内のリスナーとエンキューアーは互いを見ることができません。
stat(2)
は Linux/macOS/Windows で約 1ms の粒度で動作し、無視できる CPU コストをもたらします。コスト:カーネル通知との遅延比較で約 0.5ms です。単一マシーン、単一ライター。SQLite のロックは単一ホスト向けに設計されています。NFS を介して二つのサーバーが一つの .db に書き込むと破損します。ファイル単位でのシャーディングを行うか、Postgres に切り替えてください。

アーキテクチャ:目覚み経路 (Wake Path)

  1. データベースあたり一つ
    stat(2)
    スレッドが、.db-wal を 1ms ごとの(サイズ、更新時刻)でポーリングします。
  2. 変化 → バウンデッドチャンネルを各サブスクライバーに扇出(fan out)するティック。
  3. 各サブスクライバーは部分インデックスに対する
    SELECT … WHERE id > last_seen
    を実行し、行を返し、待機状態に戻ります。
  4. サブスクライバー 100 は 1 つの stat スレッドで対応可能。アイドルリスナーは SQL クエリを実行しません。

アイドルコスト はデータベースごとに 1ms あたり一つの

stat(2)
です。目覚めシグナルがポーリングクエリではなくファイルステータス(file stat)であるため、サブスクライバーの数が無料でスケーリングします。
SharedWalWatcher
(honker-core) がポーリングスレッドを所有し、サブスクライバー ID でキー付けられたバウンデッド
SyncSender<>()
チャンネルを通じて N つのサブスクライバーに扇出します。各
db.wal_events()
呼び出しはサブスクライバーを登録し、ドロップハンドルを返します。したがって、ドロップされたリスナーはブリッジスレッドの
rx.recv() -> Err
を引き起こし、クリーンな状態で終了します。

キュースキーマ (Queue Schema)

  • _honker_live: 待機中および処理中の行。
  • 部分インデックス:
    (queue, priority DESC, run_at, id)
    state IN ('pending','processing')
    のもの。
  • 主張(Claim)= このインデックスを使用した一つの
    UPDATE … RETURNING
    .
  • 承認(Ack)= 一つの DELETE.
  • 再試行枯渇 → _honker_dead (claim パスで永不読み込まれる).

状態に対する部分インデックスは、claim ホットパスが履歴サイズではなくワーキングセットサイズによって制限されることを意味します。10 万のデッド行を持つキューでもゼロの行列持ったキューと同じくらい速く主張できます。

主張イテレーター (Claim Iterator)

  • async for job in q.claim(id)
    は、
    claim_batch(id, 1)
    を介して一回に一つのジョブを返し。
  • Job.ack()
    は独自のトランザクションの内の DELETE です。返り値は正直な bool です:主張が無効かどうか(True)、可視性ウィンドウが経過し、別のワーカーが回収した場合(False)。
  • 任意のプロセスからの WAL コミットで目覚め、5 秒のパラノイアポーリングのみフォールバック。

バッチワークの場合は、

claim_batch(worker_id, n)
を明示的に呼び出し、
queue.ack_batch(ids, worker_id)
で承認してください。ライブラリはイテレーターの背後にバッチ処理を隠しません。API が知能(clever)を装おうとしない場合、トランザクションあたりのコストと最多一度(at-most-once)可視性セマンティクスがより理解しやすくなります。

トランザクショナルカップリング (Transactional Coupling)

  • notify()
    はライターコネクションに登録された SQL スカラー関数です。
  • 呼び出し側のオープントランザクション下の
    _honker_notifications
    への INSERTs.
  • queue.enqueue(…, tx=tx)
    および
    stream.publish(…, tx=tx)
    も同様です。
  • ロールバックは、残りのトランザクションとともにジョブ/イベント/通知をドロップします。

これはデフォルトで、インストールする必要のないライブラリによるトランザクショナルなアウトバックスパターンです。ビジネス書き込みと副作用のエンキューが共にコミットまたはロールバックします。別々のディスパッチテーブルや別々のディスパッチャープロセスはありません:サイドエフェクト行はコミットされた行であり、WAL を監視するあらゆるプロセスは約 1ms の内にそれを拾い上げます。

過剰なトリガーが迅速であれば、ポーリングによる過剰なトリガーよりも良い。

  • WAL 変化はそのデータベースのすべてのサブスクライバーを目覚めさせ、そのチャンネルがコミットしたものだけでなく。
  • 各無駄な目覚め = 一つのインデックス付き SELECT (マイクロ秒).
  • 見逃された目覚め = 沈黙した正しさのバグ.

ライブラリは、無視するリスナー十個を目覚めることを好みます。チャンネルフィルタリングはトリガー通知ではなく、SELECT パスで行われます。多くの小さなクエリは SQLite で効率的です。

リテンション (Retention)

  • キュージョブは ack まで永続し、再試行枯渇行は _honker_dead に移動します。
  • ストリームイベントは永続し、各名前付きコンシューマーは独自のオフセットを追跡します。
  • Notify は fire-and-forget であり、自動剪定されません。

呼び出し側が各プリミティブのリテンションを選択します。

db.prune_notifications(older_than_s=…, max_keep=…)
は、ライブラリのデフォルトからではなく、呼び出し側のコードでリテンションポリシーを可視化するツールです。

クラッシュ回復 (Crash Recovery)

  • ロールバックはあなたのビジネス書き込みとともにジョブ/イベント/通知をドロップします(SQLite ACID)。
  • トランザクション中の SIGKILL は安全です。WAL ロールバックにより、次のオープンで陳腐な状態が残りません。tests/test_crash_recovery.py で検証済み(サバプロセスが COMMIT 前の殺害、PRAGMA integrity_check == 'ok', 新しい通知の流れ依然として)。
  • ワーカーがジョブ中クラッシュした場合、claim は visibility_timeout_s (デフォルト 300s) 後に有効期限切れになり、別のワーカーが回収します。attempts がカウントされます。max_attempts (デフォルト 3) 後、行は _honker_dead に移動します。
  • プルン中にオフラインのリスナーは剪断されたイベントを見逃します。永続的な再生には
    db.stream()
    を使用し、パーコンシューマーオフセットを追跡します。

ウェブフレームワークへの統合 (Wiring Into Your Web Framework)

Honker はフレームワークプラグインを提供しません。API は小さく、統合は数行の接着部分で済みます:

# FastAPI: リクエスト中にエンキューし、lifespan でワーカーを実行。
@app.on_event("startup")
async def _start_workers():
    async def worker_loop():
        async for job in db.queue("emails").claim("worker"):
            await honker._worker.run_task(
                job, send_email, timeout=30, retries=3, backoff=2.0
            )
    app.state._worker = asyncio.create_task(worker_loop())

@app.post("/orders")
async def create_order(order: dict):
    with db.transaction() as tx:
        tx.execute("INSERT INTO orders (user_id) VALUES (?)", [order["user_id"]])
        db.queue("emails").enqueue({"to": order["email"]}, tx=tx)
    return {"ok": True}

SSE エンドポイントは

db.listen(channel)
または
db.stream(name).subscribe(...)
を使用した
~30
行の
async def stream(...): yield f"data: ...\n\n"
です。Django/Flask の場合は、ワーカーを専用 CLI プロセスとして実行してください(Celery/RQ と同じパターン)。

パフォーマンス

最新のラップトップで毎秒数千ものメッセージを取り扱い、クロスプロセス目覚め遅延は 1ms ステータスポーリング間隔 (~M シリーズでの中央値 1–2ms) に制限されます。bench/wake_latency_bench.py と bench/real_bench.py を実行して自分のハードウェアで測定してください。

開発 (Development)

レイアウト:

  • honker-core/: すべてのバインディングに共有される Rust rlib (in-tree, crates.io で公開)
  • honker-extension/: SQLite ロード可能拡張モジュール (cdylib, crates.io で公開)
  • packages/
    • honker/: Python パッケージ (PyO3 cdylib + Queue/Stream/Outbox/Scheduler)
    • honker-node/: napi-rs Node.js バインディング [git submodule]
    • honker-rs/: エルゴノミック Rust ラッパー [git submodule]
    • honker-go/: Go バインディング [git submodule]
    • honker-ruby/: Ruby バインディング [git submodule]
    • honker-bun/: Bun バインディング [git submodule]
    • honker-ex/: Elixir バインディング [git submodule]
    • honker-cpp/: C++ バインディング [git submodule]
  • tests/: インテグレーションテスト (クロスパッケージ)
  • bench/: ベンチマーク
  • site/: honker.dev (Astro) [git submodule]

各バインディングリポジトリは独立して公開され (PyPI / npm / crates.io / Hex / RubyGems), ここでは git submodule としてピン止めされています。honker-core + honker-extension はすべてのバインディングが依存する共有基礎となるため、in-tree に存在します。

git clone --recursive
でクローンするか、通常のクローン後に
git submodule update --init --recursive
を実行してください。

  • make test
    : デフォルト:rust + python + node (高速,~10 秒)
  • make test-python-slow
    : ソーク + リアルタイム cron テスト (~2 分)
  • make test-all
    : すべて(遅いマークを含む)
  • make build
    : PyO3 maturin develop + ロード可能拡張
python bench/wake_latency_bench.py --samples 500
python bench/real_bench.py --workers 4 --enqueuers 2 --seconds 15
python bench/ext_bench.py

カバレッジ (Coverage)

  • ワンタイム:
    make install-coverage-deps
    (coverage.py + cargo-llvm-cov をインストール).
  • make coverage
    : HTML レポートの両方を coverage/ に。
  • make coverage-python
    : honker Python パス.
  • make coverage-rust
    : honker-core Rust ユニットテスト.

Python カバレッジは Honker テストスイートの全体 (~92% of packages/honker/) を反映します。Rust カバレッジは cargo test のみ反映します。多くの honker_ops.rs パス (honker_enqueue, honker_claim_batch など) は Python テストスイート経由でしか行使されず、Rust レポートには現れません。組み合わせクロス言語カバレッジは非自明(PyO3 境界を越えた LLVM profile-data メルジング)であり、延期されています。

ライセンス

Apache 2.0。LICENSE を参照してください。

同じ日のほかのニュース

一覧に戻る →

2026/04/24 3:01

文書の見直しのお手伝いをいたしますが、ご提示いただいた「GPT-5.5」という入力は、翻訳や編集の対象となる文章を含んでおりません。 ルールに従って文書の体裁を整える対象となりますよう、該当する原文をご提供ください。 また、「GPT-5.5」という名称は、現時点で公開されている正式版のモデル名とは一致しておりません(現在最新シリーズは GPT-4o や GPT-4 Turbo などです)。 特定のテキストを処理させていただく場合は、その内容をお貼り付けください。

## Japanese Translation: OpenAI は、エージェント型コーディング、高度なコンピューター操作、知識作業、科学研究を特に目的に設計された、至今に至るまで最も知的で直感的なモデルである GPT‑5.5 を発表します。このモデルは GPT‑5.4 と同等のトークンあたり遅延を実現し、Codex タスクにおいて著しくトークン使用量を削減することで、NVIDIA GB200 および GB300 NVL72 システム上で Codex が負荷分散のヒューリスティクスを最適化するのを支援しながら、生成速度を 20% 以上向上させています。複雑なコマンドラインワークフローに関する Terminal-Bench 2.0 で 82.7% の精度、実世界の GitHub アイシュー解決における SWE-Bench Pro で 58.6% の精度を実現し、最先端のパフォーマンスを提供します。Codex においては、実装からリファクタリング、デバッグに至るまでのエンドツーエンドのエンジニアリングタスクに優れ、大規模システム全体を文脈として保持しつつ、曖昧なエラーに対しても推論を行います。安全性は引き続き最優先事項であり、モデルは新たなサイバーおよび生物学リスクに対して厳格に評価され、レッドチームによってテストされ、ほぼ 200 の信頼できるパートナーからのフィードバックに基づいて改良され、「生物学・化学およびサイバーセキュリティ能力において OpenAI の準備度フレームワークの「High」カテゴリー分類」を受領しました。GPT‑5.5 は、ChatGPT および Codex で Plus、Pro、Business、Enterprise ユーザーへ段階的に導入されており(gpt-5.5 Pro は Pro、Business、Enterprise 向けに利用可能)、API アクセスも近日中に gpt-5.5 について入力トークン当たり 5 ドル、出力トークン当たり 30 ドル(gpt-5.5-pro は 30 ドル/180 ドル)、および Very soon at $5/1M input tokens and $30/1M output tokens for gpt-5.5 ($30/$180 for gpt-5.5-pro) のレートで利用可能になります。OpenAI はまた、Trusted Access for Cyber を通じて「cyber-permissive」モデルの提供範囲を拡大し、検証済みユーザーに制限が少なくなった高度なセキュリティツールへのアクセスを提供します。知識作業ベンチマークでは、プロンプトチューニングなしで GDPval で 84.9%、OSWorld-Verified で 78.7%、Tau2-bench Telecom で 98.0% の強力な結果を示しました。 ## Text to translate: ## Summary: OpenAI is launching GPT‑5.5, its smartest and most intuitive model yet, specifically engineered for agentic coding, complex computer use, knowledge work, and scientific research. The model matches GPT‑5.4 per-token latency while significantly reducing token usage for Codex tasks, achieving faster generation speeds by over 20% when serving on NVIDIA GB200 and GB300 NVL72 systems (with help from Codex in optimizing load balancing heuristics). It delivers state-of-the-art performance with 82.7% accuracy on Terminal-Bench 2.0 for complex command-line workflows and 58.6% on SWE-Bench Pro for real-world GitHub issue resolution. In Codex, it excels at end-to-end engineering tasks—from implementation and refactoring to debugging—while holding context across large systems and reasoning through ambiguous failures. Safety remains a top priority: the model was rigorously evaluated against emerging cyber and biology risks, tested by redteamers, and refined with feedback from nearly 200 trusted partners, earning a "High" classification under OpenAI's Preparedness Framework for biological/chemical and cybersecurity capabilities. GPT‑5.5 is rolling out to Plus, Pro, Business, and Enterprise users in ChatGPT and Codex (with GPT‑5.5 Pro available to Pro, Business, and Enterprise), and API access will be available very soon at $5/1M input tokens and $30/1M output tokens for gpt-5.5 ($30/$180 for gpt-5.5-pro). OpenAI also expands "cyber-permissive" models via Trusted Access for Cyber, allowing verified users to access advanced security tools with fewer restrictions. Knowledge work benchmarks show strong results: 84.9% on GDPval, 78.7% on OSWorld-Verified, and 98.0% on Tau2-bench Telecom without prompt tuning.

2026/04/23 23:17

Bitwarden CLI、継続中の Checkmarz サプライチェーン攻撃で乗っ取られたと判明

## 日本語訳: セキュリティ研究者の InstallSocket が、継続中の「Checkmarx」キャンペーンの一環として、Bitwarden CLI ツール(@bitwarden/cli バージョン 2026.4.0)を対象とした重大なサプライチェーン攻撃を発見した。当該侵害は npm パッケージ内の `bw1.js` ファイルにあり、Bitwarden のビルドパイプラインにおける改ざんされた GitHub Action を利用して悪意のあるコードを注入したものである。これは CLI を使用する組織に対して直ちに脅威をもたらすものの、Chrome 拡張機能や MCP サーバーなどの他の配信形態は影響を受けていない。 悪意のあるペイロードは、主要なクラウドプロバイダー(AWS、Azure、GCP)、npm、SSH および Claude/MCP の設定ファイルにアクセスするためにメモリーをスクレイピングし、機密認証情報を収集することを目的としている。データを流出させる手法としては、「Dune 風」の命名規則を用いた GitHub API アップロードや、npm トークンを盗むためのパッケージのリパブリッシュが含まれる。このリスクに直面している組織は、InstallSocket からのさらなる技術分析的な確認を待たずに、直ちにビルドログを検証して侵害の指標(改ざんされたシェルプロフィール(`~/.bashrc`、`~/.zshrc`)、特定のエビディングファイル(`/tmp/tmp.987654321.lock`)、「Shai-Hulud」や"Butlerian Jihad"といったキーワードなど)を特定し、すべての公開された機密情報(SSH キー、トークン、CI/CD クレデンシャル等)を再発行するよう求める。

2026/04/24 5:14

「『インターネットを 1999 年あたりのまま使いこなすような』感覚を持つ」あるいは「ネットの使い方を、まるで 1999 年のあの頃のように(古き良き時代のように)捉えている」という意味で解釈できます。

## Japanese Translation: 著者は、現代のインターネット利用習慣が私達をアルゴリズムによる操作と「ドゥームスクロリング(絶え間ないスクロール)」という循環に陥れ、ウェブの可能性の僅かな部分にのみ留まらせていることを主張している。注意の代理権を取り戻すためには、社会メディアプラットフォームから、RSS フィードや IRC/XMPP プロトコル、HTTP/SMTP サービスといった、企業インセンティブではなく制約によって設計された直接データソースへ移行する必要がある。このアプローチは、深い高品質なコンテンツへのアクセスを保証すると同時に、反復的な LLM ポストのような低努力な AI 生成コンテンツ(スロープ)を能動的に拒否することを可能にする;著者は、「これはこれではなく、あれだ」といった類の明らかなフレーズが付けられたコンテンツを特に避けている。 歴史的には、1999 年の時点で人口のおよそ 4% がインターネットを利用していただけであり、その時点ではソーシャルメディアとアルゴリズムが現在の約 75% の浸透率を支配する以前のことだった。提案される道筋は、Miniflux などのツールを設定して意図的な購読を通じて独自の現実を編集することを受け入れ、信頼性の高いテキスト通信のために単純なプロトコルを採用すること(1980 年代後半以降の IRC;OMEMO 暗号化を実装したセルフホスト XMPP)、そしてMATRIX/Element といったより有益でないプラットフォームをあえて避ける代わりに確立された標準を採用することを含む。最後に、ユーザーは専門的な検索習慣を採用すべきであり、受動的な閲覧ではなく正確なクエリの作成を通じて意味のある情報を抽出し、技術大手をユーザー主導の注意経済に適応させる可能性がある方向へと推すものである。