2023-02-13 20:24:49 +00:00
# Neoq
2023-02-22 15:39:59 +00:00
Background job processing for Go
2023-02-18 17:45:17 +00:00
[](https://pkg.go.dev/github.com/acaloiaro/neoq) [](https://app.gitter.im/#/room/#neoq:gitter.im)
2023-02-13 20:24:49 +00:00
2023-09-16 17:09:46 +00:00
# Getting Started
2023-02-13 20:24:49 +00:00
2023-09-16 17:09:46 +00:00
See the [Getting Started ](https://github.com/acaloiaro/neoq/wiki/Getting-Started ) wiki to get started.
2023-02-13 20:24:49 +00:00
# About
2023-09-18 23:34:24 +00:00
Neoq is a queue-agnostic background job library for Go, with a pleasant API and powerful features.
2023-02-13 20:24:49 +00:00
2023-04-15 17:30:31 +00:00
Queue-agnostic means that whether you're using an in-memory queue for developing and testing, or Postgres or Redis queue in production -- your job processing code doesn't change. Job handlers are agnostic to the queue providing jobs. It also means that you can mix queue types within a single application. If you have ephemeral or periodic tasks, you may want to process them in an in-memory queue, and use Postgres or Redis queues for jobs requiring queue durability.
2023-02-13 20:24:49 +00:00
2023-04-15 17:30:31 +00:00
Neoq aims to be _simple_ , _reliable_ , _easy to integrate_ , and demand a _minimal infrastructure footprint_ by providing queue backends that match your existing tech stack.
2023-02-13 20:24:49 +00:00
2023-02-22 15:39:59 +00:00
# What it does
2023-02-13 20:24:49 +00:00
2023-04-15 01:11:22 +00:00
- **Multiple Backends**: In-memory, Postgres, Redis, or user-supplied custom backends.
2023-02-13 20:24:49 +00:00
- **Retries**: Jobs may be retried a configurable number of times with exponential backoff and jitter to prevent thundering herds
2023-04-15 01:11:22 +00:00
- **Job uniqueness**: jobs are fingerprinted based on their payload and status to prevent job duplication (multiple jobs with the same payload are not re-queued)
- **Job Timeouts**: Queue handlers can be configured with per-job timeouts with millisecond accuracy
2023-02-17 19:11:55 +00:00
- **Periodic Jobs**: Jobs can be scheduled periodically using standard cron syntax
2023-04-15 17:30:31 +00:00
- **Future Jobs**: Jobs can be scheduled in the future
2023-02-13 20:24:49 +00:00
- **Concurrency**: Concurrency is configurable for every queue
2023-08-27 08:31:52 +00:00
- **Job Deadlines**: If a job doesn't complete before a specific `time.Time` , the job expires
2023-02-13 20:24:49 +00:00
# Getting Started
2023-04-15 17:30:31 +00:00
Getting started is as simple as declaring queue handlers and adding jobs. You can create multiple neoq instances with different backends to meet your application's needs. E.g. an in-memory backend instance for ephemeral jobs and a Postgres backend instance for queue durability between application restarts.
2023-02-13 20:24:49 +00:00
Additional documentation can be found in the wiki: https://github.com/acaloiaro/neoq/wiki
Error handling in this section is excluded for simplicity.
2023-02-14 00:18:13 +00:00
## Add queue handlers
2023-02-13 20:24:49 +00:00
2023-02-22 15:39:59 +00:00
Queue handlers listen for Jobs on queues. Jobs may consist of any payload that is JSON-serializable.
2023-02-13 20:24:49 +00:00
Queue Handlers are simple Go functions that accept a `Context` parameter.
2023-02-25 03:33:38 +00:00
**Example**: Add a listener on the `hello_world` queue using the default in-memory backend
2023-02-13 20:24:49 +00:00
```go
2023-02-22 15:39:59 +00:00
ctx := context.Background()
2023-09-07 09:50:31 +00:00
nq, _ := neoq.New(ctx, neoq.WithBackend(memory.Backend))
2023-09-15 14:26:23 +00:00
nq.Start(ctx, handler.New("greetings", func(ctx context.Context) (err error) {
2023-04-02 00:54:05 +00:00
j, _ := jobs.FromContext(ctx)
2023-02-13 20:24:49 +00:00
log.Println("got job id:", j.ID, "messsage:", j.Payload["message"])
return
}))
```
2023-02-14 00:18:13 +00:00
## Enqueue jobs
2023-02-13 20:24:49 +00:00
2023-04-15 17:30:31 +00:00
Enqueuing adds jobs to the specified queue to be processed asynchronously.
2023-02-25 03:33:38 +00:00
2023-09-15 14:26:23 +00:00
**Example**: Add a "Hello World" job to the `greetings` queue using the default in-memory backend.
2023-02-13 20:24:49 +00:00
```go
2023-02-22 15:39:59 +00:00
ctx := context.Background()
2023-09-07 09:50:31 +00:00
nq, _ := neoq.New(ctx, neoq.WithBackend(memory.Backend))
2023-04-15 01:11:22 +00:00
nq.Enqueue(ctx, & jobs.Job{
2023-09-15 14:26:23 +00:00
Queue: "greetings",
Payload: map[string]any{
2023-04-15 01:11:22 +00:00
"message": "hello world",
},
})
```
## Redis
2023-09-15 14:26:23 +00:00
**Example**: Process jobs on the "greetings" queue and add a job to it using the redis backend
2023-04-15 01:11:22 +00:00
```go
ctx := context.Background()
nq, _ := neoq.New(ctx,
neoq.WithBackend(redis.Backend),
redis.WithAddr("localhost:6379"),
2023-04-15 17:30:31 +00:00
redis.WithPassword(""))
2023-04-15 01:11:22 +00:00
2023-09-15 14:26:23 +00:00
nq.Start(ctx, handler.New("greetings", func(ctx context.Context) (err error) {
2023-04-15 01:11:22 +00:00
j, _ := jobs.FromContext(ctx)
log.Println("got job id:", j.ID, "messsage:", j.Payload["message"])
return
}))
2023-03-01 18:08:05 +00:00
nq.Enqueue(ctx, & jobs.Job{
2023-09-15 14:26:23 +00:00
Queue: "greetings",
2023-02-13 20:24:49 +00:00
Payload: map[string]interface{}{
"message": "hello world",
},
})
```
2023-02-25 03:33:38 +00:00
## Postgres
2023-09-15 14:26:23 +00:00
**Example**: Process jobs on the "greetings" queue and add a job to it using the postgres backend
2023-02-25 03:33:38 +00:00
```go
ctx := context.Background()
nq, _ := neoq.New(ctx,
neoq.WithBackend(postgres.Backend),
2023-04-02 01:03:55 +00:00
postgres.WithConnectionString("postgres://postgres:postgres@127.0.0.1:5432/neoq"),
2023-02-25 03:33:38 +00:00
)
2023-09-15 14:26:23 +00:00
nq.Start(ctx, handler.New("greetings", func(ctx context.Context) (err error) {
2023-04-02 00:54:05 +00:00
j, _ := jobs.FromContext(ctx)
2023-02-25 03:33:38 +00:00
log.Println("got job id:", j.ID, "messsage:", j.Payload["message"])
return
}))
nq.Enqueue(ctx, & jobs.Job{
2023-09-15 14:26:23 +00:00
Queue: "greetings",
2023-02-25 03:33:38 +00:00
Payload: map[string]interface{}{
"message": "hello world",
},
})
```
2023-02-13 23:40:20 +00:00
# Example Code
Additional example integration code can be found at https://github.com/acaloiaro/neoq/tree/main/examples
# Status
2023-04-15 17:30:31 +00:00
This project is currently in alpha. Future releases may change the API.