wormhole/node/pkg/common/scissors.go

59 lines
1.4 KiB
Go

package common
import (
"context"
"fmt"
"github.com/certusone/wormhole/node/pkg/supervisor"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
ScissorsErrors = promauto.NewCounterVec(
prometheus.CounterOpts{
Name: "scissor_errors_caught",
Help: "Total number of unhandled errors caught",
}, []string{"scissors", "name"})
)
// Start a go routine with recovering from any panic by sending an error to a error channel
func RunWithScissors(ctx context.Context, errC chan error, name string, runnable supervisor.Runnable) {
go func() {
defer func() {
if r := recover(); r != nil {
switch x := r.(type) {
case error:
errC <- fmt.Errorf("%s: %w", name, x)
default:
errC <- fmt.Errorf("%s: %v", name, x)
}
ScissorsErrors.WithLabelValues("scissors", name).Inc()
}
}()
err := runnable(ctx)
if err != nil {
errC <- err
}
}()
}
func WrapWithScissors(runnable supervisor.Runnable, name string) supervisor.Runnable {
return func(ctx context.Context) (result error) {
defer func() {
if r := recover(); r != nil {
switch x := r.(type) {
case error:
result = fmt.Errorf("%s: %w", name, x)
default:
result = fmt.Errorf("%s: %v", name, x)
}
ScissorsErrors.WithLabelValues("scissors", name).Inc()
}
}()
return runnable(ctx)
}
}