asynctask

asynctask implements types and functions to assist with running functions as
goroutines to handle completion, errors, and timeouts.
Installation
The recommended way to install asynctask is with dep.
dep ensure -add github.com/dapr-project/asynctask@v1.0.0
Where v1.0.0 is the version you want to pin to. Alternatively you can go get
the package into your $GOPATH.
go get -u github.com/dapr-project/asynctask
Once installed you can import into your project.
import "github.com/dapr-project/asynctask"
Usage
Creating a Task
Use the asynctask.New(fn) function to create an *asynctask.Task, and supply
a function you wish to run as part of the task.
The task function passed to asynctask.New must take a *asynctask.Task as the
first parameter, then any custom parameters you wish after that.
func MyTaskFunc(task *asynctask.Task, arg1 string, arg2 int, arg3 *MyType) {
// ...
}
task := asynctask.New(MyTaskFunc)
// or a struct method...
func (s *MyStruct) MyTaskFunc(task *asynctask.Task, arg1 string, arg2 int, arg3 *MyType) {
// ...
}
task := asynctask.New(mystruct.MyTaskFunc)
Setting a Timeout
If you would like to set a timeout so the task will automatically fail when
the timeout duration has been exceeded, you can use the
task.SetTimeout(time.Duration) function.
task.SetTimeout(10 * time.Second)
Note: that even though the task will timeout, the goroutine will continue to
execute, until it naturally finishes or errors.
Starting a Task
Once you have a task you can call task.Start() to execute the function, and
proxy any arguments to the function.
You can pass the arguments required for the function as parameters to the
task.Start() call.
task.Start("string", 1234, &MyType{})
Signalling Completion, Results, and Errors in the Task
The asynctask.Task includes methods for signalling that the task has
completed, a result has been returned, or an error has occurred.
Done
To signal that your function is done, you can call the task.Done() function.
If you wish to return a value from the function, you should use
task.Return(val) instead.
func MyTaskFunc(task *asynctask.Task, arg1 string, arg2 int, arg3 *MyType) {
// ...
// signal that this function has completed...
task.Done()
}
Return
To signal that your function is done and return a value, you can call the
task.Return(val) function. This returned value will then be returned when the
task.Wait() call returns.
func MyTaskFunc(task *asynctask.Task, arg1 string, arg2 int, arg3 *MyType) {
// ...
// signal that this function has completed, and return a value...
task.Return(42)
}
The task.Return(val) function can take any value as it is stored as
interface{}, the returned asynctask.Result has helper methods to be able to
cast the value back into the original type for the caller.
Error
To signal that your function has encountered an error and you need to finish,
you can call the task.Error(err) function. This returned error will then be
returned when the task.Wait() call returns.
func MyTaskFunc(task *asynctask.Task, arg1 string, arg2 int, arg3 *MyType) {
// signal that this function has errored, and return an error...
if err != nil {
task.Error(err)
return
}
// ...
}
Waiting on a Task
To wait on a task to finish, call the task.Wait() function. This will return
either an *asynctask.Result or error.
task.Start(/* args */)
res, err := task.Wait()
The returned error could be an error returned from the task function, or an
error signalling that the function timed out. To check if the error is a timeout
error, use the asynctask.IsTimedOutErr(err) function.
res, err := task.Wait()
if err != nil {
if asynctask.IsTimedOutErr(err) {
// task function timed out...
return
}
// task function returned this error...
}
If the task function calls task.Return(val) to return a value, the result can
be used to get that returned value as the correct type.
Currently asynctask.Result provides a few helper methods to do the casting:
String() to get the value as a string
StringSlice() to get the value as a []string
Int() to get the value as an int
IntSlice() to get the value as a []int
Bool to get the value as a bool
If you would like to cast the value to another type, you can use res.Raw() to
return the interface{} to cast the value yourself.