Skip to content

ジョブの投入

enqueue

ts
import { enqueue } from 'tsumugi';

const id = await enqueue(env, {
  binding: 'MAIL',
  payload: { to: 'a@example.com', subject: 'hi' },
});

返値はジョブのIDです defineTsumugiが返すオブジェクトにも同じenqueueが用意されているので、tsumugi.enqueue(env, input)でも構いません

enqueueMany

複数件をまとめて入れるときはenqueueManyを使います

ts
const ids = await enqueueMany(env, [
  { binding: 'MAIL', payload: { to: 'a@example.com', subject: 'hi' } },
  { binding: 'MAIL', payload: { to: 'b@example.com', subject: 'hi' } },
]);

宛先のDurable Objectごとに集約して1回のRPCにまとめるので、件数が増えても往復は増えません enqueueを逐次で回すと実測78件/秒あたりでDurable Objectの1,000 req/sソフト上限に律速されます

戻り値は入力と同じ並び順です

オプション

名前既定内容
priority0数値優先度、大きいほど先に出る
maxAttempts3試行回数の上限
backoff指数、1秒起点、係数2、上限1時間、ジッタありリトライ間隔
timeoutMs60000待機を打ち切るまでの時間
delayMsなし実行開始を遅らせる
runAtなし絶対時刻での予約、delayMsとは排他
guaranteeat-least-once実行保証
concurrencyKeyなしキー単位の直列化に使う
uniqueKeyなし重複排除に使う
uniqueForMs24時間uniqueKeyの予約を保持する期間
partitionKeyなし分割している場合の投入先の決定に使う

予約実行

ts
// 1時間後
await enqueue(env, { binding: 'MAIL', payload, delayMs: 60 * 60 * 1000 });

// 指定時刻
await enqueue(env, { binding: 'MAIL', payload, runAt: Date.parse('2026-08-01T09:00:00+09:00') });

待機はDurable Objectのalarmが管理するので、Queuesの遅延配送の12時間上限には縛られません

重複排除

uniqueKeyを渡すと、同じキーのジョブが既にあるときは新規作成せず既存のジョブIDが返ります

ts
const id = await enqueue(env, {
  binding: 'SYNC',
  payload: { sku: 'X-1' },
  uniqueKey: 'sku:X-1',
});

衝突は異常ではなく正常系として扱います。例外は投げません 呼び出し側が毎回try/catchを書かずに済み、HTTPリクエストのリトライやWebhookの重複配送で二重登録されなくなります

予約はuniqueForMsが過ぎると消えるので、それ以降は同じキーでも新しいジョブになります

重複排除の判定はDurable Object内のテーブルで行います KVには条件付き書き込みの公開APIがなく、「無ければ入れる」を不可分に実行できないためです Durable Objectはシングルスレッドなので、検査と挿入が追加の仕組みなしで不可分になります

直列化

concurrencyKeyが同じジョブは、perKeyConcurrencyの上限まで同時に走ります 既定は1なので、同じキーのジョブは1件ずつ順に実行されます

ts
await enqueue(env, {
  binding: 'CHARGE',
  payload: { customerId: 'c1', amountJpy: 1200 },
  concurrencyKey: 'customer:c1',
});

これが正しく効くのはshard数が1のときです 2以上にした場合はshardもそのキーで決めないと保証がエラーにならないまま無効になるので、shardを読んでください

ジョブID

<binding>#<shard>:<localId>

例: MAIL#0:xxxxxxxxxxxxxxxxxxxxxxxx

どのDurable Objectが保持しているかをIDに含めてあるので、IDからDurable Objectのstubを直接取得できます グローバルな索引は不要です

その代わり、shard数を後から変えると既存IDの引き先が変わります 古いshardは残す必要があります

別Workerから入れる

投入だけを行うWorkerからはtsumugi/clientを使います Durable Object実装をバンドルせずに済みます。詳しくは別Workerからの投入を参照してください