Documentation
¶
Overview ¶
Async provides tools for asynchronous callback processing using Goroutines
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AsyncError ¶
type AsyncError struct {
// contains filtered or unexported fields
}
AsyncError is an async value that will eventually return an error It is similar to a Promise/Future which returns an error The value is supplied by calling SetValue. Once the value is supplied AsyncError is considered completed The value can be retrieved once AsyncError is completed via TryGetValue
func (*AsyncError) SetValue ¶
func (e *AsyncError) SetValue(err error)
Sets the value for the AsyncError. Marks AsyncError as Completed or Fulfilled. This method should only ever be called once per AsyncError instance. Calling this method more than once will panic
func (*AsyncError) TryGetValue ¶
func (e *AsyncError) TryGetValue() (bool, error)
Returns the Status of this AsyncError: Completed(true) or Pending(false) and the value of the AsyncError if it is Completed.
The returned bool is true if Completed, false if Pending If Completed the returned error is the Value of this AsyncError If AsyncError is not completed the returned error is nil.
type AsyncErrorResponseHandler ¶
type AsyncErrorResponseHandler func(error)
The function type of the callback invoked when an AsyncError is Completed
type Mailbox ¶
type Mailbox struct {
// contains filtered or unexported fields
}
An AsyncMailbox stores AsyncErrors and their associated callbacks and invokes them once the AsyncError is completed
Often times we may spawn go routines in an event loop to do some concurrent work, go routines provide no way to return a response, however we may want to be notified if the work the go routine was doing completed successfully or unsuccessfully, and then take some action based on that result. AsyncMailbox provides a construct to do this.
The below example is a storeValue function, which tries to store A value durably. A value is considered durably stored if it successfully writes to two of three replicas. We want to write to all replicas in parallel and return as soon as two writes succeed. We return an error if < 2 writes succeed
func storeValue(num int) error { successfulWrites := 0 returnedWrites := 0 mailbox := NewAsyncMailbox() writeCallback := func (err error) { if err != nil { successfulWrites++ } returnedWrites++ } // Send to Replica One go func(rsp *AsyncError){ rsp.SetValue(write(num, "replicaOne")) }(mailbox.NewAsyncError(writeCallback)) // Send to Replica Two go func(rsp *AsyncError){ rsp.SetValue(write(num, "replicaTwo")) }(mailbox.NewAsyncError(writeCallback)) // Send to Replica Three go func(rsp *AsyncError){ rsp.SetValue(write(num, "replicaThree")) }(mailbox.NewAsyncError(writeCallback)) // Value is Considered Durably Stored if at least two write calls succeeded for sucessfullWrites < 2 && returnedWrites < 3 { mailbox.ProcessMessages() } if successfulWrites >= 2 { return nil } else { return errors.New("Could Not Durably Store Value") } // a function which makes a call to a durable register // which is accessed via the network func write (num int, address string) error { ... }
A Mailbox is not a concurrent structure and should only ever be accessed from a single go routine. This ensures that the callbacks are always executed within the same context and only one at a time. A Mailbox for keeping track of in progress AsyncMessages. This structure is not thread-safe.
func NewMailbox ¶
func NewMailbox() *Mailbox
func (*Mailbox) NewAsyncError ¶
func (bx *Mailbox) NewAsyncError(cb AsyncErrorResponseHandler) *AsyncError
Creates a NewAsyncError and associates the supplied callback with it. Once the AsyncError has been completed, SetValue called, the callback will be invoked on the next execution of ProcessMessages
func (*Mailbox) ProcessMessages ¶
func (bx *Mailbox) ProcessMessages()
Processes the mailbox. For all messages with completed AsyncErrors the callback function and removes the message from the mailbox
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
An AsyncRunner is a helper class to spawn Go Routines to run AsyncFunctions and to associate callbacks with them. This builds ontop of AsyncMailbox to make simplify the code that needs to be written.
The below example is a storeValue function, which tries to store A value durably. A value is considered durably stored if it successfully writes to two of three replicas. We want to write to all replicas in parallel and return as soon as two writes succeed. We return an error if < 2 writes succeed
func storeValue(num int) error { successfulWrites := 0 returnedWrites := 0 runner := NewAsyncRunner() writeCb := func(err error) { if err != nil { successfulWrites++ } returnedWrites++ } runner.RunAsync(func() error { return write(num, "replicatOne") }, writeCb) runner.RunAsync(func() error { return write(num, "replicatTwo") }, writeCb) runner.RunAsync(func() error { return write(num, "replicaThree") }, writeCb) for successfulWrites < 2 && returnedWrites < 3 { runner.ProcessMessages() } if successfulWrites >= 2 { return nil } else { return errors.New("Could Not Durably Store Value") } }
// a function which makes a call to a durable register // which is accessed via the network func write (num int, address string) error { ... }
func (*Runner) NumRunning ¶
func (*Runner) ProcessMessages ¶
func (r *Runner) ProcessMessages()
Invokes all callbacks of completed asyncfunctions. Callbacks are ran synchronously and by the calling go routine
func (*Runner) RunAsync ¶
func (r *Runner) RunAsync(f func() error, cb AsyncErrorResponseHandler)
RunAsync creates a go routine to run the specified function f. The callback, cb, is invoked once f is completed by calling ProcessMessages.