wormhole/node/pkg/common/scissors.go

67 lines
1.3 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.NewCounter(
prometheus.CounterOpts{
Name: "scissor_errors_caught",
Help: "Total number of unhandled errors caught",
})
)
// 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.Inc()
}
}()
err := runnable(ctx)
if err != nil {
errC <- err
}
}()
}
type (
Scissors struct {
runnable supervisor.Runnable
}
)
func WrapWithScissors(runnable supervisor.Runnable) supervisor.Runnable {
s := Scissors{runnable: runnable}
return s.Run
}
func (e *Scissors) Run(ctx context.Context) (result error) {
defer func() {
if r := recover(); r != nil {
switch x := r.(type) {
case error:
result = x
default:
result = fmt.Errorf("%v", x)
}
ScissorsErrors.Inc()
}
}()
return e.runnable(ctx)
}