diff --git a/README.md b/README.md index 3242832..953e3b8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,31 @@ # Asynq [![Build Status](https://travis-ci.com/hibiken/asynq.svg?token=paqzfpSkF4p23s5Ux39b&branch=master)](https://travis-ci.com/hibiken/asynq) -Asynq is a simple asynchronous task queue library in Go. +Simple, efficent asynchronous task processing library in Go. + +## Table of Contents + +- [Overview](#overview) +- [Requirements](#requirements) +- [Installation](#installation) +- [Getting Started](#getting-started) +- [License](#license) + +## Overview + +Asynq provides a simple interface to asynchronous task processing. + +Asynq also ships with a CLI to monitor the queues and take manual actions if needed. + +Asynq provides: + +- Clear separation of task producer and consumer +- Ability to schedule task processing in the future +- Automatic retry of failed tasks with exponential backoff +- Ability to configure max retry count per task +- Ability to configure max number of worker goroutines to process tasks +- Unix signal handling to safely shutdown background processing +- Enhanced reliability TODO(hibiken): link to wiki page describing this. +- CLI to query and mutate queues state for mointoring and administrative purposes ## Requirements @@ -10,7 +35,7 @@ Asynq is a simple asynchronous task queue library in Go. ## Installation ``` -go get -u github.com/hibiken/asynq +go get github.com/hibiken/asynq ``` ## Getting Started @@ -29,14 +54,14 @@ func main() { Addr: "localhost:6379", }) - t1 := &asynq.Task{ + t1 := asynq.Task{ Type: "send_welcome_email", Payload: map[string]interface{}{ "recipient_id": 1234, }, } - t2 := &asynq.Task{ + t2 := asynq.Task{ Type: "send_reminder_email", Payload: map[string]interface{}{ "recipient_id": 1234, @@ -44,10 +69,13 @@ func main() { } // process the task immediately. - client.Process(t1, time.Now()) + err := client.Process(&t1, time.Now()) // process the task 24 hours later. - client.Process(t2, time.Now().Add(24 * time.Hour)) + err = client.Process(&t2, time.Now().Add(24 * time.Hour)) + + // specify the max number of retry (default: 25) + err = client.Process(&t1, time.Now(), asynq.MaxRetry(1)) } ``` @@ -59,24 +87,56 @@ func main() { Addr: "localhost:6379", }) - bg.Run(asynq.HandlerFunc(handler)) + // Blocks until signal TERM or INT is received. + // For graceful shutdown, send signal TSTP to stop processing more tasks + // before sending TERM or INT signal. + bg.Run(handler) } +``` -// if handler returns an error or panics, the task will be retried after some delay. +The argument to `(*asynq.Background).Run` is an interface `asynq.Handler` which has one method `ProcessTask`. + +```go +// ProcessTask should return nil if the processing of a task +// is successful. +// +// If ProcessTask return a non-nil error or panics, the task +// will be retried. +type Handler interface { + ProcessTask(*Task) error +} +``` + +The simplest way to implement a handler is to define a function with the same signature and use `asynq.HandlerFunc` adapter type when passing it to `Run`. + +```go func handler(t *asynq.Task) error { switch t.Type { - case "send_welcome_email": - id, err := t.Payload.GetInt("recipient_id") - if err != nil{ - return err - } - fmt.Printf("Send Welcome Email to %d\n", id) + case "send_welcome_email": + id, err := t.Payload.GetInt("recipient_id") + if err != nil { + return err + } + fmt.Printf("Send Welcome Email to %d\n", id) - // ... handle other task types. + // ... handle other types ... - default: - return fmt.Errorf("unexpected task type: %s", t.Type) + default: + return fmt.Errorf("unexpected task type: %s", t.Type) } return nil } + +func main() { + bg := asynq.NewBackground(10, &asynq.RedisOpt{ + Addr: "localhost:6379", + }) + + // Use asynq.HandlerFunc adapter for a handler function + bg.Run(asynq.HandlerFunc(handler)) +} ``` + +## License + +Asynq is released under the MIT license. See [LICENSE](https://github.com/hibiken/asynq/blob/master/LICENSE).