neoq

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 17, 2023 License: AGPL-3.0 Imports: 6 Imported by: 1

README

Neoq

Background job processing for Go

Go Reference Gitter chat

Installation

go get github.com/acaloiaro/neoq

About

Neoq is a background job framework for Go applications. Its purpose is to minimize the infrastructure necessary to run production applications. It does so by implementing queue durability with modular backends.

This allows application to use the same type of data store for both application data and backround job processing. At the moment an in-memory and Postgres backends are provided. However, the goal is to have backends for every major datastore: Postgres, Redis, MySQL, etc.

Neoq does not aim to be the fastest background job processor. It aims to be fast, reliable, and demand a minimal infrastructure footprint.

What it does

  • Background job Processing: Neoq has an in-memory and Postgres backend out of the box. Users may supply their own without changing neoq directly.
  • 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 unprocessed jobs with the same payload cannot be queued)
  • Deadlines: Queue handlers can be configured with per-job time deadlines with millisecond accuracy
  • Configurable transaction idle time: Don't let your background worker transactions run away with db resources. By default, worker transactions may idle for 60 seconds.
  • Periodic Jobs: Jobs can be scheduled periodically using standard cron syntax
  • Future Jobs: Jobs can be scheduled either for the future or immediate execution
  • Concurrency: Concurrency is configurable for every queue

Getting Started

Getting started is as simple as declaring queue handlers and adding jobs.

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)
nq.Start(ctx, "hello_world", handler.New(func(ctx context.Context) (err error) {
  j, _ := handler.JobFromContext(ctx)
  log.Println("got job id:", j.ID, "messsage:", j.Payload["message"])
  return
}))

Enqueue jobs

Enqueuing jobs 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)
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),
  config.WithConnectionString("postgres://postgres:postgres@127.0.0.1:5432/neoq"),
)

nq.Start(ctx, "hello_world", handler.New(func(ctx context.Context) (err error) {
  j, _ := handler.JobFromContext(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. It currently leaks some resources. It can handle unimportant workloads.

Documentation

Overview

Package neoq provides background job processing for Go applications.

Neoq's goal is to minimize the infrastructure necessary to add background job processing to Go applications. It does so by implementing queue durability with modular backends, rather than introducing a strict dependency on a particular backend such as Redis.

An in-memory and Postgres backend are provided out of the box.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrConnectionStringRequired = errors.New("a connection string is required for this backend. See [config.WithConnectionString]")
	ErrNoBackendSpecified       = errors.New("please specify a backend by using [config.WithBackend]")
)

Functions

func New

func New(ctx context.Context, opts ...config.Option) (b types.Backend, err error)

New creates a new backend instance for job processing.

By default, neoq initializes memory.Backend if New() is called without a backend configuration option.

Use neoq.WithBackend to initialize different backends.

For available configuration options see config.ConfigOption.

Example
ctx := context.Background()
nq, err := New(ctx, WithBackend(memory.Backend))
if err != nil {
	fmt.Println("initializing a new Neoq with no params should not return an error:", err)
	return
}
defer nq.Shutdown(ctx)

fmt.Println("neoq initialized with default memory backend")
Output:

neoq initialized with default memory backend
Example (Postgres)
ctx := context.Background()
var pgURL string
var ok bool
if pgURL, ok = os.LookupEnv("TEST_DATABASE_URL"); !ok {
	fmt.Println("Please set TEST_DATABASE_URL environment variable")
	return
}

nq, err := New(ctx, WithBackend(postgres.Backend), config.WithConnectionString(pgURL))
if err != nil {
	fmt.Println("neoq's postgres backend failed to initialize:", err)
	return
}
defer nq.Shutdown(ctx)

fmt.Println("neoq initialized with postgres backend")
Output:

neoq initialized with postgres backend

func WithBackend

func WithBackend(initializer config.BackendInitializer) config.Option

WithBackend configures neoq to initialize a specific backend for job processing.

Neoq provides two config.BackendInitializer that may be used with WithBackend

Example
ctx := context.Background()
nq, err := New(ctx, WithBackend(memory.Backend))
if err != nil {
	fmt.Println("initializing a new Neoq with no params should not return an error:", err)
	return
}
defer nq.Shutdown(ctx)

fmt.Println("neoq initialized with memory backend")
Output:

neoq initialized with memory backend
Example (Postgres)
ctx := context.Background()
var pgURL string
var ok bool
if pgURL, ok = os.LookupEnv("TEST_DATABASE_URL"); !ok {
	fmt.Println("Please set TEST_DATABASE_URL environment variable")
	return
}

nq, err := New(ctx, WithBackend(postgres.Backend), config.WithConnectionString(pgURL))
if err != nil {
	fmt.Println("initializing a new Neoq with no params should not return an error:", err)
	return
}
defer nq.Shutdown(ctx)

fmt.Println("neoq initialized with postgres backend")
Output:

neoq initialized with postgres backend

func WithJobCheckInterval

func WithJobCheckInterval(interval time.Duration) config.Option

WithJobCheckInterval configures the duration of time between checking for future jobs

Types

This section is empty.

Directories

Path Synopsis
Package backends provides concrete implementations of pkg/github.com/acaloiaro/neoq/types.Backend
Package backends provides concrete implementations of pkg/github.com/acaloiaro/neoq/types.Backend
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL