# README

Async

Why you want to use this package

Package async simplifies the implementation of orchestration patterns for concurrent systems. It is similar to Java Future or JS Promise, which makes life much easier when dealing with asynchronous operation and concurrent processing. Golang is excellent in terms of parallel programming. However, dealing with goroutines and channels could be a big headache when business logic gets complicated. Wrapping them into higher-level functions improves code readability significantly and makes it easier for engineers to reason about the system's behaviours.

Currently, this package includes:

  • Asynchronous tasks with cancellations, context propagation and state.
  • Task chaining by using continuations.
  • Fork/join pattern - running a batch of tasks in parallel and blocking until all finish.

Concept

Task is a basic concept like Future in Java. You can create a Task using an executable function which takes in context.Context, then returns error and an optional result.

task := NewTask(func(context.Context) (animal, error) {
    // run the job
    return res, err
})

silentTask := NewSilentTask(func(context.Context) error {
    // run the job
    return err
})

Get the result

The function will be executed asynchronously. You can query whether it's completed by calling task.State(), which is a non-blocking function. Alternative, you can wait for the response using task.Outcome() or silentTask.Wait(), which will block the execution until the task is done. These functions are quite similar to the equivalents in Java Future.isDone() or Future.get().

Cancelling

There could be case that we don't care about the result anymore some time after execution. In this case, a task can be aborted by invoking task.Cancel().

Chaining

To have a follow-up action after a task is done, you can use the provided family of Continue functions. This could be very useful to create a chain of processing, or to have a teardown process at the end of a task.

Fork join

ForkJoin is meant for running multiple subtasks concurrently. They could be different parts of the main task which can be executed independently. The following code example illustrates how you can send files to S3 concurrently with a few lines of code.

func uploadFilesConcurrently(files []string) {
    var tasks []Task[string]
    for _, file := range files {
        f := file
        
        tasks = append(tasks, NewTask(func(ctx context.Context) (string, error) {
            return upload(ctx, f)
        }))
    }

    ForkJoin(context.Background(), tasks)
}

func upload(ctx context.Context, file string) (string, error){
    // do file uploading
    return "", nil
}

# Functions

CancelAll cancels all given tasks.
Completed returns a completed task with the given result and error.
ContinueInSilence proceeds with the next task once the current one is finished.
ContinueWith proceeds with the next task once the current one is finished.
ContinueWithNoResult proceeds with the next task once the current one is finished.
ContinueWithResult proceeds with the next task once the current one is finished.
ForkJoin executes given tasks in parallel and waits for ALL to complete before returning.
ForkJoinFailFast executes given tasks in parallel and waits for the 1st task to fail and returns immediately or for ALL to complete successfully before returning.
Invoke creates a new Task and runs it asynchronously.
InvokeInSilence creates a new SilentTask and runs it asynchronously.
NewMockSilentTask creates a new instance of MockSilentTask.
NewMockTask creates a new instance of MockTask.
NewSilentTask creates a new SilentTask.
NewSilentTasks creates a group of new SilentTask.
NewTask creates a new Task.
NewTasks creates a group of new Task.
WaitAll waits for all executed tasks to finish.

# Constants

IsCancelled represents a task which was cancelled or has timed out.
IsCompleted represents a task which was completed successfully or errored out.
IsCreated represents a newly created task.
IsRunning represents a task which is currently running.

# Variables

ErrDefaultCancelReason is default reason when none is provided.

# Structs

MockSilentTask is an autogenerated mock type for the SilentTask type.
MockTask is an autogenerated mock type for the Task type.

# Interfaces

SilentTask represents a unit of work to complete in silence like background works that return no values.go:generate mockery --name SilentTask --case underscore --inpackage.
Task represents a unit of work that is expected to return a value of a particular type.go:generate mockery --name Task --case underscore --inpackage.

# Type aliases

PanicRecoverWork represents a unit of work to be executed when a panic occurs.
SilentWork represents a unit of work to execute in silence like background works that return no values.
State represents the state enumeration for a task.
Work represents a unit of work to execute that is expected to return a value of a particular type.