github.com/amp-space/amp-sdk-go@v0.7.6/stdlib/task/api.task.go (about) 1 // Features task.Context, a wrapper for goroutines inspired by a conventional parent-child process model 2 package task 3 4 import ( 5 "context" 6 "time" 7 8 "github.com/amp-space/amp-sdk-go/stdlib/log" 9 ) 10 11 // Starts a new Context with no parent Context. 12 func Start(task *Task) (Context, error) { 13 return Context((*ctx)(nil)).StartChild(task) 14 } 15 16 // Go is a convenience function that starts a new Context that runs the given function -- like starting a goroutine. 17 // 18 // If parent == null, then the new Context will have no parent. 19 func Go(parent Context, label string, fn func(ctx Context)) (Context, error) { 20 return parent.StartChild(&Task{ 21 Label: label, 22 OnRun: fn, 23 }) 24 } 25 26 // Task is a parameter block used to start a new Context and contains hooks for each stage of the Context's lifecycle. 27 type Task struct { 28 29 // If > 0, Context.CloseWhenIdle() will automatically called when the last remaining child is closed or when OnRun() completes, whichever occurs later. 30 // 31 // This will not enter into effect unless OnRun is given or a child is started. 32 IdleClose time.Duration 33 34 TaskRef any // TaskRef is offered for open-ended use 35 Label string // Label is used for logging and debugging 36 OnStart func(ctx Context) error // Blocking fn called in StartChild(). If err, ctx.Close() is called and Go() returns the err and OnRun is never called. 37 OnRun func(ctx Context) // Async work body. If non-nil, ctx.Close() will be automatically called after OnRun() completes 38 OnClosing func() // Called immediately after Close() is first called while self & children are still closing 39 OnChildClosing func(child Context) // Called immediately after the child's OnClosing() is called 40 OnClosed func() // Called after Close() and all children have completed Close() (but immediately before Done() is released) 41 } 42 43 // Context is an expanded form of a context.Context offering, featuring: 44 // - integrated logging, removing guesswork of which Context logged what 45 // - "child" Contexts such that Close() will cause a Context's children to close 46 // - automatic idle-close of Contexts after a period of inactivity 47 // - the OnClosing() hook, allowing cleanup to occur when a Context is closed but before its parent is closed. 48 // - PrintTreePeriodically() which visualizes a Context's child tree and is helpful for debugging in large projects. 49 type Context interface { 50 log.Logger 51 52 // Includes functionality and behavior of a context.Context. 53 context.Context 54 55 // Returns Task.Ref passed into StartChild() 56 TaskRef() interface{} 57 58 // The context's public label 59 Label() string 60 61 // A guaranteed unique ID assigned after Start() is called. 62 ContextID() int64 63 64 // Creates a new child Context with for given Task. 65 // If OnStart() returns an error error is encountered, then child.Close() is immediately called and the error is returned. 66 StartChild(task *Task) (Context, error) 67 68 // Convenience function for StartChild() and is equivalent to: 69 // 70 // parent.StartChild(label, &Task{ 71 // IdleClose: time.Nanosecond, 72 // OnRun: fn, 73 // }) 74 Go(label string, fn func(ctx Context)) (Context, error) 75 76 // Appends all currently open/active child Contexts to the given slice and returns the given slice. 77 // Naturally, the returned items are back-ward looking as any could close at any time. 78 // Context implementations wishing to remain lightweight may opt to not retain a list of children (and just return the given slice as-is). 79 GetChildren(in []Context) []Context 80 81 // Async call that initiates task shutdown and causes all children's Close() to be called. 82 // Close can be called multiple times but calls after the first are in effect ignored. 83 // First, children get Close() in breath-first order. 84 // After all children are done closing, OnClosing(), then OnClosed() are executed. 85 Close() error 86 87 // Inserts a pending Close() on this Context once it is idle after the given delay. 88 // Subsequent calls will update the delay but the previously pending delay must run out first. 89 // If at the end of the period Task.OnRun() is complete, there are no children, PreventIdleClose() is not in effect, then Close() is called. 90 CloseWhenIdle(delay time.Duration) 91 92 // Ensures that that this Context will not automatically idle-close until the given delay has passed. 93 // If previous PreventIdleClose calls were made, the more limiting delay is retained. 94 // 95 // Returns false if this Context has already been closed. 96 PreventIdleClose(delay time.Duration) bool 97 98 // Signals when Close() has been called. 99 // First, Children get Close(), then OnClosing, then OnClosed are executing 100 Closing() <-chan struct{} 101 102 // Signals when Close() has fully executed, no children remain, and OnClosed() has been completed. 103 Done() <-chan struct{} 104 }