Documentation
¶
Overview ¶
Package async provide different kind of interface and implementation to manipulate a bit more safely the go routing.
First things provided by this package is an implementation of the pattern Async/Await you can find in Javascript It should be used when you need to run multiple asynchronous task and wait for each of them to finish. Example:
func doneAsync() (int, error) {
// asynchronous task
time.Sleep(3 * time.Second)
return 1, nil
}
func synchronousTask() {
next := async.Async(doneAsync)
// do some other stuff
// then wait for the end of the asynchronous task and get back the result
result, err := next.Await()
// do something with the result
fmt.Println("got",result,"err",err)
}
It is useful to use this implementation when you want to paralyze quickly some short function like paralyzing multiple HTTP requests. You definitely won't use this implementation if you want to create a cron or a long task. Instead, you should implement the interface SimpleTask or Task for doing that.
As a Task is designed to run in a long term, you will have to take care about a context and a cancel function passed in the parameter of the main method Execute. Note that the context and the cancel function are shared by every task. It's important to understand that because it means if a task is calling the cancel function, then it will close the context for all Task. It means also that all task should listen the context in order to react when the context is closed. Once the context is closed, the task should then perform some action to be stopped properly. Of course, it will depend on what you are implementing. Not all task need to do something when the context is closed. Also calling the cancel function in the task must have done only if your task is critical for your application and so if whatever reason the task doesn't work anymore, then the whole application must be stopped. If you are not in this situation, you shouldn't use the cancel function
As you may notice, a Task is an extension of the SimpleTask. In addition, of the method Execute (coming from the SimpleTask), a Task will need to implement the method Initialize and Finalize. It can be useful when you want to separate the different phases of the lifecycle of a Task. The Initialize method is called before running the Task (i.e. before calling the method Execute) The Finalize method is called once the context is closed
The Task are designed to work with the app.Runner which will create the root context and the cancel function. Basically you don't have to take care how to run the Task or how to create and share the same context.
Example:
How to implement a Task that would run periodically type myPeriodicTask struct { SimpleTask } func (t *myPeriodicTask) Execute(ctx context.Context, cancelFunc context.CancelFunc) error { // since my task is quite simple, and it will be called periodically, I don't need to listen the context. It is handled by the caller. (For more detail, see taskhelper.Start logrus.Info("I'm alive!") return nil } // like that the method Execute of myPeriodicTask will be called periodically every 30 seconds. app.NewRunner().WithCronTasks(30*time.Second, &myPeriodicTask).Start()
How to implement a Task that would run infinitely type myInfiniteTask struct { SimpleTask } func (t *myInfiniteTask) Execute(ctx context.Context, cancelFunc context.CancelFunc) error { for { select { case <-ctx.Done(): // the context is canceled, I need to stop my task return nil default: // my business code to run } return nil } app.NewRunner().WithTasks(&myInfiniteTask).Start()
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Future ¶ added in v0.3.0
type Future[T any] interface { Await() (T, error) AwaitWithContext(ctx context.Context) (T, error) }
func Async ¶
Async executes the asynchronous function
Example ¶
package main
import (
"fmt"
"github.com/perses/common/async"
)
func fn(s string, err error) func() (string, error) {
return func() (string, error) {
return s, err
}
}
func main() {
next1 := async.Async(fn("success", nil))
next2 := async.Async(fn("", fmt.Errorf("error")))
result1, err1 := next1.Await()
result2, err2 := next2.Await()
fmt.Println("async1:", result1, err1, "async2:", result2, err2)
}
Output: async1: success <nil> async2: error
type SimpleTask ¶
type SimpleTask interface {
// Stringer is implemented for logging purpose (able to identify the execute or in the logs)
fmt.Stringer
// Execute is the method called once or periodically to execute the task.
// ctx is the parent context, you usually use it to listen if the context is done.
// cancel will be used to cancel the ctx and to propagate the information to others Task that they have to stop since it will close the channel.
// Use it if you are going to implement a task that is critical to your application and if it stops then it should stop your whole application.
// A good example is the signalListener. You want to stop your application in case a sigterm is sent to the application. So in that particular case, the signalListener will call the cancelFunc.
Execute(ctx context.Context, cancelFunc context.CancelFunc) error
}
SimpleTask is the simple way to define an asynchronous task. The execution of the task is handled by the package async/taskhelper.
func NewSignalListener ¶
func NewSignalListener(signals ...os.Signal) SimpleTask
type Task ¶
type Task interface {
SimpleTask
// Initialize is called by the runner before the Task is running
Initialize() error
// Finalize is called by the runner when it ends (clean-up, wait children, ...)
Finalize() error
}
Task is a more complete way to define an asynchronous task. Use it when you want a finer control of each steps when the task will run.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package taskhelper provides struct and methods to help to synchronize different async.Task together and to simply start the async.Task properly This package should mainly used through the package app and not directly by the developer.
|
Package taskhelper provides struct and methods to help to synchronize different async.Task together and to simply start the async.Task properly This package should mainly used through the package app and not directly by the developer. |