No description
Find a file
Adriano Caloiaro 41b39d5177 fix: Use neoq-specific schema migrations able
When neoq is embedded in apps already use golang-migrate, they would
both attempt to use the `schema_migrations` table for migrations.

This commit moves neoq to its own `neoq_schema_migrations` table so as
not to clash with other golang-migrate users.
2023-09-09 11:43:48 +02:00
.github/workflows Support postgres backend schema migrations 2023-08-28 08:59:40 +02:00
backends fix: Use neoq-specific schema migrations able 2023-09-09 11:43:48 +02:00
examples break: Rename types.Backend -> neoq.Neoq 2023-09-07 12:36:02 +02:00
handler Fix retries in the event of handler panic (#48) 2023-04-29 12:47:52 -06:00
internal feat: Remove dead code 2023-09-02 14:59:32 +02:00
jobs Support job deadlines 2023-08-28 20:01:21 +02:00
logging Add log level support (#49) 2023-05-02 20:17:53 -06:00
testutils maint: clean up testutils/TestLogger 2023-09-07 12:36:02 +02:00
.gitignore Add redis support (#44) 2023-04-14 19:11:22 -06:00
.go-version Bump golang version 2023-02-19 10:04:35 -05:00
.golangci.yaml Move backends to separate packages 2023-03-01 10:34:27 -07:00
.goreleaser.yaml break: Rename types.Backend -> neoq.Neoq 2023-09-07 12:36:02 +02:00
doc.go Add redis support (#44) 2023-04-14 19:11:22 -06:00
env.sample Fix slog API change issue 2023-07-17 07:54:22 -06:00
go.mod feat: Improve postgres duplicate job detection performance 2023-09-02 14:59:32 +02:00
go.sum feat: Improve postgres duplicate job detection performance 2023-09-02 14:59:32 +02:00
LICENSE.txt Add full AGPL license text 2023-02-14 15:00:39 -08:00
Makefile break: Rename types.Backend -> neoq.Neoq 2023-09-07 12:36:02 +02:00
neoq.go break: Rename types.Backend -> neoq.Neoq 2023-09-07 12:36:02 +02:00
neoq_test.go break: Rename types.Backend -> neoq.Neoq 2023-09-07 12:36:02 +02:00
README.md break: Rename types.Backend -> neoq.Neoq 2023-09-07 12:36:02 +02:00

Neoq

Background job processing for Go

Go Reference Gitter chat

Usage

go get -u github.com/acaloiaro/neoq

About

Neoq is a queue-agnostic background job framework for Go.

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.

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.

What it does

  • Multiple Backends: In-memory, Postgres, Redis, or user-supplied custom backends.
  • Retries: Jobs may be retried a configurable number of times with exponential backoff and jitter to prevent thundering herds
  • 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
  • Periodic Jobs: Jobs can be scheduled periodically using standard cron syntax
  • Future Jobs: Jobs can be scheduled in the future
  • Concurrency: Concurrency is configurable for every queue
  • Job Deadlines: If a job doesn't complete before a specific time.Time, the job expires

Getting Started

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.

Additional documentation can be found in the wiki: https://github.com/acaloiaro/neoq/wiki

Error handling in this section is excluded for simplicity.

Add queue handlers

Queue handlers listen for Jobs on queues. Jobs may consist of any payload that is JSON-serializable.

Queue Handlers are simple Go functions that accept a Context parameter.

Example: Add a listener on the hello_world queue using the default in-memory backend

ctx := context.Background()
nq, _ := neoq.New(ctx, neoq.WithBackend(memory.Backend))
nq.Start(ctx, "hello_world", handler.New(func(ctx context.Context) (err error) {
  j, _ := jobs.FromContext(ctx)
  log.Println("got job id:", j.ID, "messsage:", j.Payload["message"])
  return
}))

Enqueue jobs

Enqueuing adds jobs to the specified queue to be processed asynchronously.

Example: Add a "Hello World" job to the hello_world queue using the default in-memory backend.

ctx := context.Background()
nq, _ := neoq.New(ctx, neoq.WithBackend(memory.Backend))
nq.Enqueue(ctx, &jobs.Job{
  Queue: "hello_world",
  Payload: map[string]interface{}{
    "message": "hello world",
  },
})

Redis

Example: Process jobs on the "hello_world" queue and add a job to it using the redis backend

ctx := context.Background()
nq, _ := neoq.New(ctx,
  neoq.WithBackend(redis.Backend),
  redis.WithAddr("localhost:6379"),
  redis.WithPassword(""))

nq.Start(ctx, "hello_world", handler.New(func(ctx context.Context) (err error) {
  j, _ := jobs.FromContext(ctx)
  log.Println("got job id:", j.ID, "messsage:", j.Payload["message"])
  return
}))

nq.Enqueue(ctx, &jobs.Job{
  Queue: "hello_world",
  Payload: map[string]interface{}{
    "message": "hello world",
  },
})

Postgres

Example: Process jobs on the "hello_world" queue and add a job to it using the postgres backend

ctx := context.Background()
nq, _ := neoq.New(ctx,
  neoq.WithBackend(postgres.Backend),
  postgres.WithConnectionString("postgres://postgres:postgres@127.0.0.1:5432/neoq"),
)

nq.Start(ctx, "hello_world", handler.New(func(ctx context.Context) (err error) {
  j, _ := jobs.FromContext(ctx)
  log.Println("got job id:", j.ID, "messsage:", j.Payload["message"])
  return
}))

nq.Enqueue(ctx, &jobs.Job{
  Queue: "hello_world",
  Payload: map[string]interface{}{
    "message": "hello world",
  },
})

Example Code

Additional example integration code can be found at https://github.com/acaloiaro/neoq/tree/main/examples

Status

This project is currently in alpha. Future releases may change the API.