開発概要
目的
- 既存の
NotificationUseCase.ProcessUnsentNotifications を 5分間隔で自動実行 する仕組みを追加する
- 現状は
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行のみ追加し、業務・運用ロジックを混入させない(a44d742 で slackService を di.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 を関数型エイリアスにすることで、scheduler は usecase パッケージを import せずに済み、依存方向が di → scheduler di → usecase の二股になる。
3. di.go の配線追加
ファイル: api/lib/di/di.go
di.go に書くのは「組み立てて起動を1行で呼ぶ」だけ。tickerのfor文やerr処理は scheduler パッケージに閉じる。
4. 動作確認
5. ドキュメント更新
備考
docker-compose.prod.yml のAPIは1レプリカ運用のため、ticker方式で問題なし
- 冪等性は
notification_usecase.go:129 の MarkAsSent トランザクションに依存(現状の手動実行版と同じリスク水準)
- 将来
ProcessUnsentNotifications の処理時間が5分を超えても、for range ticker.C の素朴ループで直列化されるため重複送信は発生しない
- graceful shutdown(SIGTERM対応)は今回スコープ外。必要になったら
context.WithCancel で後付け可能
参考
開発の流れ
- PMにIssue(タスク)をもらう
- 開発をする(↓の「リンク」の『開発のやり方』を見よう!)
- チェックボックスを押していこう
- ヤバい状況になったらIssueの右側にあるStatusを「Help」にしてPMにSlackで連絡しよう
- チェックボックスが全部押せたらプルリクを作ろう
- レビューを待とう
- 修正点があれば修正しよう。なければPMがマージします!お疲れ様!
SeeFTのタスク管理のルール
- タスクは全てGit-Hub Projectで管理する
- 全てのタスクに期日を決める
- 毎週タスクの進捗を確認する(MTに出られない人はSlackで報告)
- 毎週忙しさ(消化できるタスク量)を共有する
- Helpは余裕のある人がいれば巻き取る。いなければ期日を変更する
リンク
開発概要
目的
NotificationUseCase.ProcessUnsentNotificationsを 5分間隔で自動実行 する仕組みを追加するapi/cmd/send-notifications/main.goを手動で叩いた瞬間にだけ Slack DM が flush される状態。action_logsテーブルにis_sent = falseのレコードが溜まり続けてしまう開発期間
考えられる開発内容
1. 設計方針
api/lib/externals/server/server.goが「Echoサーバの実行環境」を外部層に閉じ込めているのと同じパターンで、「定期実行ループ」をexternals/scheduler/に新規パッケージとして切り出す。di.goには配線2〜3行のみ追加し、業務・運用ロジックを混入させない(a44d742でslackServiceをdi.goから削除した経緯と整合させる)。各層の責務:
usecase/notification_usecase.goexternals/scheduler/(新規)di/di.go2. 新規ファイルの実装
2.1
api/lib/externals/scheduler/scheduler.goJob型をfunc(ctx context.Context) errorとして定義Scheduler構造体(name,interval,jobを保持)New(name string, interval time.Duration, job Job) *SchedulerStart(ctx context.Context)— goroutineでtime.NewTickerループを起動、即座にreturnlog.Printfでログ出力のみ(パニックさせない)Jobを関数型エイリアスにすることで、scheduler は usecase パッケージを import せずに済み、依存方向がdi → schedulerdi → usecaseの二股になる。3. di.go の配線追加
ファイル:
api/lib/di/di.goactionLogRepository(既存、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. 動作確認
action_logs.is_sentがtrueに更新されることcmd/send-notificationsの手動実行(debug用途)が引き続き動作すること5. ドキュメント更新
AGENTS.mdまたはREADMEに「APIは単一インスタンス前提(通知ticker起因で重複送信になる)」を1行追記備考
docker-compose.prod.ymlのAPIは1レプリカ運用のため、ticker方式で問題なしnotification_usecase.go:129のMarkAsSentトランザクションに依存(現状の手動実行版と同じリスク水準)ProcessUnsentNotificationsの処理時間が5分を超えても、for range ticker.Cの素朴ループで直列化されるため重複送信は発生しないcontext.WithCancelで後付け可能参考
開発の流れ
SeeFTのタスク管理のルール
リンク