PostgreSQL Broker

A robust, event-driven job processing system for PostgreSQL that uses LISTEN/NOTIFY for real-time job execution. It supports multiple queues, priority-based scheduling, and can be used both as a standalone service or as a Go library.

Features

  • Multi-Database Support: Single broker process can manage multiple database connections
  • Event-Driven: Uses PostgreSQL LISTEN/NOTIFY for instant job notifications
  • Multiple Queues: Support for concurrent job processing across multiple queues per database
  • Priority Scheduling: Jobs can be prioritized for execution order
  • Job Dependencies: Jobs can depend on other jobs being completed first
  • Adapter Pattern: Clean interfaces for database and logging (easy to extend)
  • Standalone or Library: Use as a CLI tool or integrate into your Go application
  • Configuration Management: Viper-based config with support for YAML, JSON, and environment variables
  • Graceful Shutdown: Proper cleanup and job completion on shutdown
  • Instance Tracking: Monitor active broker instances through the database
  • Single Instance Per Database: Enforces one broker instance per database to prevent conflicts
  • Embedded SQL Installer: Database schema embedded in binary with built-in install command

Architecture

The broker supports multi-database architecture where a single broker process can manage multiple database connections. Each database has its own instance with dedicated queues, but only ONE broker instance is allowed per database.

┌─────────────────────────────────────────────────────────────────┐
│                      Broker Process                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                   │
│  ┌────────────────────────────┐  ┌───────────────────────────┐ │
│  │  Database Instance (DB1)   │  │  Database Instance (DB2)  │ │
│  ├────────────────────────────┤  ├───────────────────────────┤ │
│  │ ┌────┐ ┌────┐ ┌────┐      │  │ ┌────┐ ┌────┐            │ │
│  │ │ Q1 │ │ Q2 │ │ QN │      │  │ │ Q1 │ │ Q2 │            │ │
│  │ └────┘ └────┘ └────┘      │  │ └────┘ └────┘            │ │
│  │                            │  │                           │ │
│  │ ┌────────────────────────┐│  │ ┌────────────────────────┐│ │
│  │ │  PostgreSQL Adapter    ││  │ │  PostgreSQL Adapter    ││ │
│  │ │  - Connection Pool     ││  │ │  - Connection Pool     ││ │
│  │ │  - LISTEN/NOTIFY       ││  │ │  - LISTEN/NOTIFY       ││ │
│  │ └────────────────────────┘│  │ └────────────────────────┘│ │
│  └────────────┬───────────────┘  └──────────┬────────────────┘ │
│               │                              │                   │
└───────────────┼──────────────────────────────┼───────────────────┘
                │                              │
                ▼                              ▼
    ┌──────────────────────┐      ┌──────────────────────┐
    │  PostgreSQL (DB1)    │      │  PostgreSQL (DB2)    │
    │  - broker_jobs       │      │  - broker_jobs       │
    │  - broker_queueinstance│    │  - broker_queueinstance│
    │  - broker_schedule   │      │  - broker_schedule   │
    └──────────────────────┘      └──────────────────────┘

Key Points:

  • One broker process can manage multiple databases
  • Each database has exactly ONE active broker instance
  • Each database instance has its own queues and workers
  • Validation prevents multiple broker processes from connecting to the same database
  • Different databases can have different queue counts

Installation

From Source

git clone git.warky.dev/wdevs/pgsql-broker
cd pgsql-broker
make build

The binary will be available in bin/pgsql-broker.

As a Library

go get git.warky.dev/wdevs/pgsql-broker

Quick Start

1. Setup Database

Install the required tables and stored procedures:

# Using the CLI (recommended)
./bin/pgsql-broker install --config broker.yaml

# Or with make
make sql-install

# Verify installation
./bin/pgsql-broker install --verify-only --config broker.yaml

# Or manually with psql:
psql -f pkg/broker/install/sql/tables/00_install.sql
psql -f pkg/broker/install/sql/procedures/00_install.sql

2. Configure

Create a configuration file broker.yaml:

databases:
  - name: db1
    host: localhost
    port: 5432
    database: broker_db1
    user: postgres
    password: your_password
    sslmode: disable
    queue_count: 4

  # Optional: add more databases
  - name: db2
    host: localhost
    port: 5432
    database: broker_db2
    user: postgres
    password: your_password
    sslmode: disable
    queue_count: 2

broker:
  name: pgsql-broker
  enable_debug: false

logging:
  level: info
  format: json

Note: Each database requires a unique name identifier and can have its own queue_count configuration.

3. Run the Broker

# Using the binary
./bin/pgsql-broker start --config broker.yaml

# Or with make
make run

# Or with custom log level
./bin/pgsql-broker start --log-level debug

4. Add a Job

SELECT broker_add_job(
    'My Job',                    -- job_name
    'SELECT do_something()',     -- execute_str
    1,                           -- job_queue (default: 1)
    0,                           -- job_priority (default: 0)
    'sql',                       -- job_language (default: 'sql')
    NULL,                        -- run_as
    NULL,                        -- user_login
    NULL                         -- schedule_id
);

Usage as a Library

package main

import (
    "git.warky.dev/wdevs/pgsql-broker/pkg/broker"
    "git.warky.dev/wdevs/pgsql-broker/pkg/broker/adapter"
    "git.warky.dev/wdevs/pgsql-broker/pkg/broker/config"
)

func main() {
    // Load config
    cfg, _ := config.LoadConfig("broker.yaml")

    // Create logger
    logger := adapter.NewSlogLogger(slog.LevelInfo)

    // Create database adapter
    dbAdapter := adapter.NewPostgresAdapter(cfg.Database.ToPostgresConfig(), logger)

    // Create and start broker
    instance, _ := broker.New(cfg, dbAdapter, logger, "1.0.0")
    instance.Start()

    // ... wait for shutdown signal ...

    instance.Stop()
}

See the examples directory for complete examples.

Database Schema

Tables

  • broker_queueinstance: Tracks active broker queue instances (one per database)
  • broker_jobs: Job queue with status tracking
  • broker_schedule: Scheduled jobs (cron-like functionality)

Stored Procedures

  • broker_get: Fetch the next job from a queue
  • broker_run: Execute a job
  • broker_set: Set runtime options (user, application_name, etc.)
  • broker_add_job: Add a new job to the queue
  • broker_register_instance: Register a broker instance
  • broker_ping_instance: Update instance heartbeat
  • broker_shutdown_instance: Mark instance as shutdown

Configuration Reference

See broker.example.yaml for a complete configuration example.

Database Settings

The databases array can contain multiple database configurations. Each entry supports:

Setting Description Default
name Unique identifier for this database Required
host PostgreSQL host localhost
port PostgreSQL port 5432
database Database name Required
user Database user Required
password Database password -
sslmode SSL mode disable
max_open_conns Max open connections 25
max_idle_conns Max idle connections 5
conn_max_lifetime Connection max lifetime 5m
conn_max_idle_time Connection max idle time 10m
queue_count Number of queues for this database 4

Broker Settings

Global settings applied to all database instances:

Setting Description Default
name Broker instance name pgsql-broker
fetch_query_que_size Jobs per fetch cycle 100
queue_timer_sec Seconds between polls 10
queue_buffer_size Job buffer size 50
worker_idle_timeout_sec Worker idle timeout 10
notify_retry_seconds NOTIFY retry interval 30s
enable_debug Enable debug logging false

Development

Building

make build       # Build the binary
make clean       # Clean build artifacts
make deps        # Download dependencies
make fmt         # Format code
make vet         # Run go vet
make test        # Run tests

Project Structure

pgsql-broker/
├── cmd/broker/          # CLI application
├── pkg/broker/          # Core broker package
│   ├── adapter/         # Database & logger interfaces
│   ├── config/          # Configuration management
│   ├── models/          # Data models
│   ├── queue/           # Queue management
│   ├── worker/          # Worker implementation
│   └── install/         # Database installer with embedded SQL
│       └── sql/         # SQL schema (embedded in binary)
│           ├── tables/  # Table definitions
│           └── procedures/ # Stored procedures
├── examples/            # Usage examples
└── Makefile             # Build automation

Contributing

Contributions are welcome! Please ensure:

  • Code is formatted with go fmt
  • Tests pass with go test ./...
  • Documentation is updated

License

See LICENSE file for details.

Description
PostgreSQL Broker
Readme Apache-2.0 89 KiB
Languages
Go 69.4%
PLpgSQL 23%
Makefile 7.6%