Skip to content

通知UseCaseの定期実行(5分間隔scheduler)をAPIプロセス内に実装 #271

@taminororo

Description

@taminororo

開発概要

目的

  • 既存の NotificationUseCase.ProcessUnsentNotifications5分間隔で自動実行 する仕組みを追加する
  • 現状は api/cmd/send-notifications/main.go手動で叩いた瞬間にだけ Slack DM が flush される状態。action_logs テーブルに is_sent = false のレコードが溜まり続けてしまう
  • インフラ部門にcron設定を依頼すると運用責任が分割されるため、Goプロセス内で完結する形で実装する

開発期間

  • 開始日:
  • 締切日:

考えられる開発内容

1. 設計方針

api/lib/externals/server/server.go が「Echoサーバの実行環境」を外部層に閉じ込めているのと同じパターンで、「定期実行ループ」を externals/scheduler/ に新規パッケージとして切り出す。

di.go には配線2〜3行のみ追加し、業務・運用ロジックを混入させない(a44d742slackServicedi.go から削除した経緯と整合させる)。

各層の責務:

責務
usecase/notification_usecase.go 「未送信ログを処理する」業務ロジック。変更なし
externals/scheduler/(新規) tickerループ、context管理、エラーログ
di/di.go UseCaseを組み立て、Schedulerに渡す(2〜3行追加)

2. 新規ファイルの実装

2.1 api/lib/externals/scheduler/scheduler.go

  • Job 型を func(ctx context.Context) error として定義
  • Scheduler 構造体(name, interval, job を保持)
  • New(name string, interval time.Duration, job Job) *Scheduler
  • Start(ctx context.Context) — goroutineで time.NewTicker ループを起動、即座にreturn
  • tick内のエラーは log.Printf でログ出力のみ(パニックさせない)

Job を関数型エイリアスにすることで、scheduler は usecase パッケージを import せずに済み、依存方向が di → scheduler di → usecase の二股になる。

3. di.go の配線追加

ファイル: api/lib/di/di.go

  • actionLogRepository(既存、L42)から NotificationUseCase を組み立て
  • slack.NewSlackService() を呼び出し(環境変数 SLACK_BOT_TOKEN 等)
  • scheduler.New(\"notification\", 5*time.Minute, uc.ProcessUnsentNotifications).Start(ctx)server.RunServer(router) の直前に追加

di.go に書くのは「組み立てて起動を1行で呼ぶ」だけ。tickerのfor文やerr処理は scheduler パッケージに閉じる。

4. 動作確認

  • APIコンテナ起動後、5分待って Slack DM が届くこと
  • action_logs.is_senttrue に更新されること
  • 未送信ログが0件のときに無駄なSlackリクエストが発生しないこと
  • cmd/send-notifications の手動実行(debug用途)が引き続き動作すること

5. ドキュメント更新

  • AGENTS.md または README に「APIは単一インスタンス前提(通知ticker起因で重複送信になる)」を1行追記

備考

  • docker-compose.prod.yml のAPIは1レプリカ運用のため、ticker方式で問題なし
  • 冪等性は notification_usecase.go:129MarkAsSent トランザクションに依存(現状の手動実行版と同じリスク水準)
  • 将来 ProcessUnsentNotifications の処理時間が5分を超えても、for range ticker.C の素朴ループで直列化されるため重複送信は発生しない
  • graceful shutdown(SIGTERM対応)は今回スコープ外。必要になったら context.WithCancel で後付け可能

参考

開発の流れ

  1. PMにIssue(タスク)をもらう
  2. 開発をする(↓の「リンク」の『開発のやり方』を見よう!)
  3. チェックボックスを押していこう
  4. ヤバい状況になったらIssueの右側にあるStatusを「Help」にしてPMにSlackで連絡しよう
  5. チェックボックスが全部押せたらプルリクを作ろう
  6. レビューを待とう
  7. 修正点があれば修正しよう。なければPMがマージします!お疲れ様!

SeeFTのタスク管理のルール

  1. タスクは全てGit-Hub Projectで管理する
  2. 全てのタスクに期日を決める
  3. 毎週タスクの進捗を確認する(MTに出られない人はSlackで報告)
  4. 毎週忙しさ(消化できるタスク量)を共有する
  5. Helpは余裕のある人がいれば巻き取る。いなければ期日を変更する

リンク

Metadata

Metadata

Assignees

No one assigned

    Labels

    Size-S開発時間の目安は5時間✨Backendバックエンドのタスク. 主にGo, TypeScriptを使用優先度0Must, Minimum・最低限実装しないといけない枠🔨新機能新機能の開発

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions