2
0
mirror of https://github.com/hibiken/asynq.git synced 2024-11-10 11:31:58 +08:00

Merge pull request #3 from hibiken/feature/recover

Protect handler call against panic
This commit is contained in:
Ken Hibino 2019-11-27 14:05:39 -08:00 committed by GitHub
commit 871162cd67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 68 additions and 1 deletions

View File

@ -88,7 +88,7 @@ func (p *processor) exec() {
} }
<-p.sema // release token <-p.sema // release token
}() }()
err := p.handler(task) // TODO(hibiken): maybe also handle panic? err := perform(p.handler, task)
if err != nil { if err != nil {
retryTask(p.rdb, msg, err) retryTask(p.rdb, msg, err)
} }
@ -103,3 +103,15 @@ func (p *processor) restore() {
log.Printf("[ERROR] could not move tasks from %q to %q\n", inProgress, defaultQueue) log.Printf("[ERROR] could not move tasks from %q to %q\n", inProgress, defaultQueue)
} }
} }
// perform calls the handler with the given task.
// If the call returns without panic, it simply returns the value,
// otherwise, it recovers from panic and returns an error.
func perform(handler TaskHandler, task *Task) (err error) {
defer func() {
if x := recover(); x != nil {
err = fmt.Errorf("panic: %v", x)
}
}()
return handler(task)
}

55
processor_test.go Normal file
View File

@ -0,0 +1,55 @@
package asynq
import (
"fmt"
"testing"
)
func TestPerform(t *testing.T) {
tests := []struct {
desc string
handler TaskHandler
task *Task
wantErr bool
}{
{
desc: "handler returns nil",
handler: func(t *Task) error {
fmt.Println("processing...")
return nil
},
task: &Task{Type: "gen_thumbnail", Payload: map[string]interface{}{"src": "some/img/path"}},
wantErr: false,
},
{
desc: "handler returns error",
handler: func(t *Task) error {
fmt.Println("processing...")
return fmt.Errorf("something went wrong")
},
task: &Task{Type: "gen_thumbnail", Payload: map[string]interface{}{"src": "some/img/path"}},
wantErr: true,
},
{
desc: "handler panics",
handler: func(t *Task) error {
fmt.Println("processing...")
panic("something went terribly wrong")
},
task: &Task{Type: "gen_thumbnail", Payload: map[string]interface{}{"src": "some/img/path"}},
wantErr: true,
},
}
for _, tc := range tests {
got := perform(tc.handler, tc.task)
if !tc.wantErr && got != nil {
t.Errorf("%s: perform() = %v, want nil", tc.desc, got)
continue
}
if tc.wantErr && got == nil {
t.Errorf("%s: perform() = nil, want non-nil error", tc.desc)
continue
}
}
}