Recover from panics that happen during fetch#39
Recover from panics that happen during fetch#39edsrzf wants to merge 4 commits intovektah:masterfrom
Conversation
This also adds a new optional Recover field to Config structs, to allow
control over transforming recovered values into errors. When it's nil,
fmt.Errorf("%v", v) is used.
|
I'm not sure why CI is failing, but I can't reproduce it locally and can't see how it would be related to this change. |
There was a problem hiding this comment.
The test failure is random. It will pass if you re-run the test. It would be good to add a test for this PR though. 1 for no handler and 1 for custom panic handler.
$ go test ./... -test.count 100
? github.com/vektah/dataloaden [no test files]
ok github.com/vektah/dataloaden/example 4.148s
? github.com/vektah/dataloaden/example/pkgname [no test files]
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=20) %!s(int=4)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
--- FAIL: TestUserLoader (0.04s)
--- FAIL: TestUserLoader/it_sent_two_batches (0.00s)
Error Trace: usersliceloader_test.go:90
Error: "[%!s(int=5) %!s(int=50)]" should have 3 item(s), but has 2
Test: TestUserLoader/it_sent_two_batches
FAIL
FAIL github.com/vektah/dataloaden/example/slice 4.155s
ok github.com/vektah/dataloaden/pkg/generator 4.264s
| MaxBatch int | ||
|
|
||
| // Recover is a function to transform a recovered value into an error. | ||
| // If a function is not supplied, the value is formatted with fmt.Errorf("%v", v). |
There was a problem hiding this comment.
We should specify that if a function is provided, it must not return nil.
pkg/generator/template.go
Outdated
| package {{.Package}} | ||
|
|
||
| import ( | ||
| "fmt" |
There was a problem hiding this comment.
Looks like the rest of the imports use 4 spaces rather than tabs. It's not great, but let's stay consistent for now?
|
Added tests and hey, whaddya know, there was a bug. |
|
I see one reason these tests are so flaky: they are abusing go's test parallelism. Depending on the number of cores (and therefore default test parallelism), different behaviours will happen. When a test calls t.Parallel(), it blocks and is resumed later. Running the tests with |
|
Hello, guys. |
| b.error = []error{fmt.Errorf("%v", r)} | ||
| } | ||
| } | ||
| close(b.done) |
There was a problem hiding this comment.
this line will cause "panic: close of closed channel", should inside the if-recover case.
There was a problem hiding this comment.
Have you tried this code and run into it? The channel needs to always be closed when the function exits. Otherwise Load calls will never return.
We've since forked this code and are running panic-handling almost identical to this in production with no issues.
There was a problem hiding this comment.
Hi, i have tried the patch, but I got "panic: close of closed channel".
From my opinion, it's because if l.fetch(b.keys) successfully execute, the channel will be closed, but inside defer func, we close it again. So, the second time we close it, we have to make sure there was panic, means inside r := recover(); && r != nil.
|
Any news on this one? |
|
Can it be merged? |
Now a panic inside fetch doesn't take down the whole process.
This also adds a new optional
Recoverfield to Config structs to allow control over transforming recovered values into errors. When it'snil,fmt.Errorf("%v", v)is used.Fixes #31.