-
Notifications
You must be signed in to change notification settings - Fork 1
# 283 SlackのDM送信を5分ごとに実行する処理の追加 #322
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from all commits
7cc59c8
191b35b
de5b954
18ca2a1
b2dc296
c680c76
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,37 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package scheduler | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "context" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "log" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Job は scheduler が定期実行する処理。usecase を import せず関数型で受け取り、 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // scheduler と業務ロジックを疎結合に保つ。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type Job func(ctx context.Context) error | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Scheduler は「名前・間隔・実行する処理」を保持する。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type Scheduler struct { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name string | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interval time.Duration | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| job Job | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // New はコンストラクタでSchedulerを生成する。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func New(name string, interval time.Duration, job Job) *Scheduler { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return &Scheduler{name: name, interval: interval, job: job} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Start は ticker ループを goroutine で起動し、即座に return する。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // interval ごとに job を実行し、job が返したエラーはログ出力のみ(ループは止めない)。 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (s *Scheduler) Start(ctx context.Context) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| go func() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ticker := time.NewTicker(s.interval) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer ticker.Stop() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for range ticker.C { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err := s.job(ctx); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Printf("[scheduler:%s] job error: %v", s.name, err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+25
to
+37
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Context のキャンセルに対応していない(goroutine リーク)
🔒 Context キャンセル対応の修正案 func (s *Scheduler) Start(ctx context.Context) {
go func() {
ticker := time.NewTicker(s.interval)
defer ticker.Stop()
- for range ticker.C {
- if err := s.job(ctx); err != nil {
- log.Printf("[scheduler:%s] job error: %v", s.name, err)
- }
+ for {
+ select {
+ case <-ticker.C:
+ if err := s.job(ctx); err != nil {
+ log.Printf("[scheduler:%s] job error: %v", s.name, err)
+ }
+ case <-ctx.Done():
+ log.Printf("[scheduler:%s] stopped: %v", s.name, ctx.Err())
+ return
+ }
}
}()
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: NUTFes/SeeFT
Length of output: 519
🏁 Script executed:
Repository: NUTFes/SeeFT
Length of output: 97
🏁 Script executed:
Repository: NUTFes/SeeFT
Length of output: 1150
🏁 Script executed:
Repository: NUTFes/SeeFT
Length of output: 807
🏁 Script executed:
Repository: NUTFes/SeeFT
Length of output: 38
🏁 Script executed:
Repository: NUTFes/SeeFT
Length of output: 1653
🏁 Script executed:
Repository: NUTFes/SeeFT
Length of output: 738
scheduler の Start() メソッドが context キャンセルに対応していないため、graceful shutdown が不可能
scheduler.go の
Start()メソッド(27-36行)は、渡された context を job に渡すだけで、スケジューラー自体が context のキャンセルをチェック(<-ctx.Done())していません。そのため、context.Background()以外の cancellable context を渡しても、ticker は無限に動作し続けます。さらに、main.go にはシグナルハンドリングや graceful shutdown の仕組みがなく、サーバー停止時に scheduler を適切に停止できません。
修正が必要な箇所:
Start()内の ticker ループに、context キャンセルをチェックする select 文を追加🤖 Prompt for AI Agents