From b1247d2d0d51108c910a73891ff3116e5f032ab1 Mon Sep 17 00:00:00 2001 From: "Kali Kaneko (leap communications)" Date: Sat, 12 Jan 2019 18:39:45 +0100 Subject: [pkg] all your deps are vendored to us --- vendor/github.com/getlantern/ops/ops.go | 154 ++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 vendor/github.com/getlantern/ops/ops.go (limited to 'vendor/github.com/getlantern/ops/ops.go') diff --git a/vendor/github.com/getlantern/ops/ops.go b/vendor/github.com/getlantern/ops/ops.go new file mode 100644 index 0000000..136302d --- /dev/null +++ b/vendor/github.com/getlantern/ops/ops.go @@ -0,0 +1,154 @@ +// Package ops provides a facility for tracking the processing of operations, +// including contextual metadata about the operation and their final success or +// failure. An op is assumed to have succeeded if by the time of calling Exit() +// no errors have been reported. The final status can be reported to a metrics +// facility. +package ops + +import ( + "sync" + "sync/atomic" + + "github.com/getlantern/context" +) + +var ( + cm = context.NewManager() + reporters []Reporter + reportersMutex sync.RWMutex +) + +// Reporter is a function that reports the success or failure of an Op. If +// failure is nil, the Op can be considered successful. +type Reporter func(failure error, ctx map[string]interface{}) + +// Op represents an operation that's being performed. It mimics the API of +// context.Context. +type Op interface { + // Begin marks the beginning of an Op under this Op. + Begin(name string) Op + + // Go starts the given function on a new goroutine. + Go(fn func()) + + // End marks the end of this op, at which point the Op will report its success + // or failure to all registered Reporters. + End() + + // Cancel cancels this op so that even if End() is called later, it will not + // report its success or failure. + Cancel() + + // Set puts a key->value pair into the current Op's context. + Set(key string, value interface{}) Op + + // SetDynamic puts a key->value pair into the current Op's context, where the + // value is generated by a function that gets evaluated at every Read. + SetDynamic(key string, valueFN func() interface{}) Op + + // FailIf marks this Op as failed if the given err is not nil. If FailIf is + // called multiple times, the latest error will be reported as the failure. + // Returns the original error for convenient chaining. + FailIf(err error) error +} + +type op struct { + ctx context.Context + canceled bool + failure atomic.Value +} + +// RegisterReporter registers the given reporter. +func RegisterReporter(reporter Reporter) { + reportersMutex.Lock() + reporters = append(reporters, reporter) + reportersMutex.Unlock() +} + +// Begin marks the beginning of a new Op. +func Begin(name string) Op { + return &op{ctx: cm.Enter().Put("op", name).PutIfAbsent("root_op", name)} +} + +func (o *op) Begin(name string) Op { + return &op{ctx: o.ctx.Enter().Put("op", name).PutIfAbsent("root_op", name)} +} + +func (o *op) Go(fn func()) { + o.ctx.Go(fn) +} + +// Go mimics the method from context.Manager. +func Go(fn func()) { + cm.Go(fn) +} + +func (o *op) Cancel() { + o.canceled = true +} + +func (o *op) End() { + if o.canceled { + return + } + + var reportersCopy []Reporter + reportersMutex.RLock() + if len(reporters) > 0 { + reportersCopy = make([]Reporter, len(reporters)) + copy(reportersCopy, reporters) + } + reportersMutex.RUnlock() + + if len(reportersCopy) > 0 { + var failure error + _failure := o.failure.Load() + ctx := o.ctx.AsMap(_failure, true) + if _failure != nil { + failure = _failure.(error) + _, errorSet := ctx["error"] + if !errorSet { + ctx["error"] = failure.Error() + } + } + for _, reporter := range reportersCopy { + reporter(failure, ctx) + } + } + + o.ctx.Exit() +} + +func (o *op) Set(key string, value interface{}) Op { + o.ctx.Put(key, value) + return o +} + +// SetGlobal puts a key->value pair into the global context, which is inherited +// by all Ops. +func SetGlobal(key string, value interface{}) { + cm.PutGlobal(key, value) +} + +func (o *op) SetDynamic(key string, valueFN func() interface{}) Op { + o.ctx.PutDynamic(key, valueFN) + return o +} + +// SetGlobalDynamic is like SetGlobal but uses a function to derive the value +// at read time. +func SetGlobalDynamic(key string, valueFN func() interface{}) { + cm.PutGlobalDynamic(key, valueFN) +} + +// AsMap mimics the method from context.Manager. +func AsMap(obj interface{}, includeGlobals bool) context.Map { + return cm.AsMap(obj, includeGlobals) +} + +func (o *op) FailIf(err error) error { + if err != nil { + o.failure.Store(err) + } + return err +} -- cgit v1.2.3