コンテンツにスキップ

トリガー・スケジューラ

主トリガは Backlog Webhook(status / コメント / 投稿日時更新の即応)。配信時刻トリガは EventBridge Scheduler の動的 at(投稿日時) scheduleScan Lambda は rate(1 day) の日次セーフティネットとして Webhook 取りこぼしを救済する。

トリガー種別

種別 起動条件 実装 反応時間
status 変化 Backlog 課題が automedia承認 に遷移 Backlog Webhook → webhook-backlog Lambda → EventBridge Schedule at(max(投稿日時, now+5s)) 登録 秒精度
コメントコマンド /automedia send 同上 → Deliver/Preview/Cancel Lambda invoke 秒精度
投稿日時到達 EventBridge Schedule at(投稿日時) Schedule 発火 → Deliver Lambda invoke 秒精度
セーフティネット rate(1 day) で Webhook 取りこぼしを救済 EventBridge Scheduler → Scan Lambda 最大 24h(漏れ救済)
LINE follow / message LINE Webhook LINE Webhook Lambda → 即応 reply or SQS 5 秒以内

稼働環境 — 担当者の PC は不要

重要

Backlog Webhook 受信は AWS API Gateway + webhook-backlog Lambda、配信時刻トリガは EventBridge Scheduler、配信実行は deliver Lambda(Claude Platform on AWS) であり、すべて spin-dd の AWS アカウント上で動く。担当者の PC を起動しておく必要はない。週末・深夜・祝日でも、誰がログインしていなくても自動で実行される。

Q A
週末でも投稿される? はい
深夜帯の配信は? 静粛時間帯を project.yml で除外しない限り配信される
担当者が休暇中でも? はい
ランナーは誰が動かす? AWS のマネージドサービス(API Gateway + EventBridge + Lambda)。自前 runner / EC2 は不要

Webhook 主体の設計

Backlog Webhook を主トリガ にすることで以下のメリットを実現:

観点
反応時間(status 変化) 秒精度 (Webhook 受信 → 即 Schedule upsert)
反応時間(コメントコマンド) 秒精度
Backlog API 呼び出し イベント駆動のみ + 日次セーフティネット 1 回
配信時刻精度 秒精度(動的 at(投稿日時) schedule)
取りこぼし Webhook 取りこぼし → 日次 Scan で救済

Backlog Webhook → Lambda の経路

sequenceDiagram
    participant U as 運用担当者
    participant BL as Backlog
    participant APIGW as API Gateway
    participant BWHL as Backlog Webhook Lambda
    participant EB as EventBridge Scheduler
    participant DLV as Deliver Lambda

    U->>BL: 課題を `automedia承認` に遷移 (投稿日時は未来)
    BL->>APIGW: webhook IssueUpdated
    APIGW->>BWHL: invoke
    BWHL->>BWHL: 署名検証 / tenant 解決
    BWHL->>EB: PutSchedule(at(投稿日時), input={tenant, issueKey})
    BWHL-->>APIGW: 200 OK

    Note over EB: 投稿日時に到達

    EB->>DLV: invoke (秒精度)
    DLV->>BL: 配信結果コメント + 自動配信実行日時 更新

EventBridge Schedule の運用

  • Schedule 名: automedia-deliver-${tenant}-${issueKey} で一意化
  • Schedule action: aws:lambda:InvokeFunctionDeliver Lambda を起動、payload に {tenant, issueKey} を含める
  • IssueUpdated で投稿日時が変わったら 同名 Schedule を update(create or replace)
  • IssueUpdated で status が戻ったら / cancel コマンドが来たら Schedule を delete
  • Schedule 発火後は自動削除されるが、念のため Deliver Lambda が完了時に delete を呼ぶ(残骸クリーンアップ)

タイムゾーン規約

  • Backlog「投稿日時」: 入力は JSTAsia/Tokyo)固定。Backlog UI も JST 表示
  • EventBridge Schedule: タイムゾーン指定可。at(2026-05-20T19:00:00) + timezone=Asia/Tokyo で登録
  • Lambda: 環境変数 TZ=Asia/Tokyo を設定 or Intl.DateTimeFormat で明示
  • プロジェクト別の上書き: .automedia/project.yml > default_timezone で対応可能(将来用)

Backlog Webhook Lambda の Schedule 登録擬似コード:

import { SchedulerClient, CreateScheduleCommand, UpdateScheduleCommand } from '@aws-sdk/client-scheduler';

const scheduler = new SchedulerClient({ region: 'ap-northeast-1' });

async function upsertDeliverSchedule(tenant: string, issueKey: string, scheduledJST: string) {
  const name = `automedia-deliver-${tenant}-${issueKey}`;
  const payload = JSON.stringify({ tenant, issueKey });
  const params = {
    Name: name,
    ScheduleExpression: `at(${scheduledJST})`,    // e.g. at(2026-05-20T19:00:00)
    ScheduleExpressionTimezone: 'Asia/Tokyo',
    Target: {
      Arn: process.env.DELIVER_LAMBDA_ARN!,
      RoleArn: process.env.SCHEDULER_ROLE_ARN!,
      Input: payload,
    },
    FlexibleTimeWindow: { Mode: 'OFF' },
  };
  try {
    await scheduler.send(new CreateScheduleCommand(params));
  } catch (e: any) {
    if (e.name === 'ConflictException') {
      await scheduler.send(new UpdateScheduleCommand(params));
    } else throw e;
  }
}

静粛時間帯(quiet hours)

業務的・倫理的に深夜配信を避けたい場合、.automedia/project.yml で静粛時間帯を定義する。Backlog Webhook Lambda が Schedule 登録前に判定する。

quiet_hours:
  enabled: true
  timezone: Asia/Tokyo
  ranges:
    - { from: "22:00", to: "08:00" }

判定:

  • 投稿日時が静粛時間帯に 入る 場合:
  • 既定: Schedule を登録せず、Backlog コメントで警告(「投稿日時を見直してください」)
  • オプション: 翌朝の quiet_hours.to まで遅延配信(Schedule の時刻を自動補正)

二重 invoke の防止(冪等性)

Backlog カスタムフィールド 自動配信実行日時 を冪等性キーとして使う。

  • Deliver Lambda は配信成功時に「自動配信実行日時 = now()」を書き込む
  • 同一の (tenant, issueKey) で複数経路(Webhook 起動 / Schedule 発火 / Scan 救済)から invoke されても、Deliver Lambda 側で DynamoDB lock を取得して二重実行を防止
  • 配信失敗時にリトライしたい場合は、人間が手動で 自動配信実行日時 をクリア、または failed ラベル付与で再 invoke 許可

同時 invoke の防止

Deliver Lambda は invoke 時に DynamoDB の条件付き put で (tenant, issueKey) の lock を取得:

await ddb.send(new PutItemCommand({
  TableName: 'automedia-deliver-locks',
  Item: { tenant, issueKey, takenAt: now, ttl: now + 3600 },
  ConditionExpression: 'attribute_not_exists(issueKey)',
}));

取得失敗時は no-op で終了。TTL 1 時間で自動失効。

Scheduler 設計(Phase 1b 全体)

Scheduler 設計

  • 主経路 (統一): Backlog Webhook → EventBridge Schedule 登録 → 投稿日時に発火 → Deliver
  • 即時送信も同経路: 投稿日時が過去 / コメント /automedia send の場合は at(now+5s) で登録 → 同じ EventBridge 経路で発火 (経路を分けない、Issue #104 確定)
  • セーフティネット: 日次 Scan Lambda が「漏れ」を検知(通常 0 件、検知時は CloudWatch Alarm)

manual トリガーのコマンド仕様

Backlog コメントは Backlog Webhook が IssueCommented イベントで受け、コマンドを parse する。

コマンド 説明 経路
/automedia send template=<id> [audience=<tag-expr>] 即時配信 Backlog Webhook → Deliver Lambda invoke
/automedia preview 草案の配信プレビューを返信 Backlog Webhook → Preview Lambda
/automedia cancel scheduled 状態の取り消し Backlog Webhook → EventBridge Schedule delete
/automedia status 現在の状態を返信 Backlog Webhook → 状態取得 → Backlog コメント

event トリガーの例

イベント アクション 経路
LINE follow 登録クーポンの送付 LINE → API Gateway → LINE Webhook Lambda(即応 reply)
特定アンケート回答 タグ付与 + 次回配信フラグ LINE → LINE Webhook Lambda → SQS → Deliver Lambda
HubSpot コンタクト更新 タグ同期 HubSpot → API Gateway → Webhook Lambda(後続フェーズ)

並行制御

  • 同一 ContentTask の同時実行防止: Deliver Lambda の DynamoDB 条件付き put(前述)
  • 同一テナントの並行配信数: Lambda の reserved concurrency でテナント別に制限可能
  • 外部 API レート制御: Deliver Lambda 内 TypeScript で吸収(指数バックオフ)