Skip to content

Repository files navigation

gua

Stars Build Status Go License: MIT Backed by PostgreSQL Docker docs English docs 繁體中文

Distributed crontab-style scheduler in Go, backed by PostgreSQL (via River).

Jobs are registered against a group and fire at a planned time (one-shot @once, cron, or @every). When a job fires, gua delivers a trigger envelope to the consumer over one of two transports:

  • HTTPPOST <target> with a JSON body
  • gRPCOnJobTrigger (Push: gua dials the consumer's gRPC server)

Both carry the same fields: job_id, job_name, group_name, plan_time, exec_time, payload. The consumer's HTTP 2xx / gRPC JobResult is the execution result, recorded in a short-retention history for monitoring.

This is the PostgreSQL line. A Redis-backed version lives on the harden branch; see docs/pg-migration.md for why and how the store moved to Postgres.

Architecture

architecture

  • Register / CRUD (consumer → gua) — RegisterGroup, AddJob, EditJob, PauseJob, ActiveJob, DeleteJob, ListJobs over HTTP REST (/v1/...) or the equivalent gRPC GuaAdmin.
  • Delivery (gua → consumer, when a job fires) — the trigger envelope as a JSON POST (HTTP) or GuaCallback.OnJobTrigger (gRPC Push).
  • NATS-free — gua nodes are stateless: they all dequeue from one Postgres with FOR UPDATE SKIP LOCKED, so each job runs exactly once across the fleet — no slot election, no per-node buckets, no de-dup fence.

Add a node and it just starts pulling; a crashed node's in-flight jobs are reclaimed by River's rescuer. Full write-up (pipeline, HA, schema) in docs/ARCHITECTURE.md.

Requirements

  • PostgreSQL (the only backend) — reachable via PG_DSN; River runs its own migrations on startup, so no manual schema step.
  • Go 1.x to build from source (see go.mod for the version).

Quick start (Docker Compose)

Brings up Postgres + gua (River runs its own migrations on startup) — no setup:

docker compose -f docker-compose/docker-compose.yml up --build

See it work — register a group, schedule a one-shot job ~5s out, then watch it fire:

curl localhost:7777/version
# 1. register a group
curl -XPOST localhost:7777/v1/groups -d '{"group_name":"demo"}'
# 2. schedule a job that POSTs a trigger envelope in ~5s. Point request_url at a
#    catcher you control (e.g. grab a URL from https://webhook.site) to watch it land:
curl -XPOST localhost:7777/v1/groups/demo/jobs -d "{\"name\":\"hi\",\"exec_time\":$(( $(date +%s) + 5 )),\"request_url\":\"HTTP@https://webhook.site/your-id\",\"interval_pattern\":\"@once\",\"payload\":\"hello\"}"
# 3. after it fires, confirm in the execution history
curl localhost:7777/v1/groups/demo/history

Or open the console at http://localhost:7777/ui to register, schedule, and watch history live.

Run (binary)

$ ./gua start -e env.example     # with an env file
$ ./gua start                    # or rely on the process environment

Needs a reachable Postgres (PG_DSN); River runs its own migrations on startup. See env.example for all knobs (Postgres, history retention, logging).

Container image

The repo's docker-compose.yml and example/ build from source (for dev / the demo). To deploy without building, pull the published image from Docker Hub — syhlion/gua, tagged per release (:4.0.0 / :4 / :latest):

docker pull syhlion/gua:latest
# give it a reachable Postgres; it runs its own migrations on startup:
docker run --rm -p 7777:7777 -p 6666:6666 \
  -e PG_DSN='postgres://user:pass@your-postgres:5432/gua?sslmode=disable' \
  -e HTTP_LISTEN=:7777 -e GRPC_LISTEN=:6666 -e MACHINE_CODE=gua-1 \
  syhlion/gua:latest start

To pull instead of build in your own compose, swap the build: block for image: syhlion/gua:<tag>.

Ops

  • Health: GET /version (build/version) · web console GET /ui.
  • Monitoring: GET /v1/status (queue health) · GET /v1/groups/{group}/history (recent executions). Full reference in docs/MONITORING.md.

Logging

Output is selectable and rotated, via env:

Env Values
LOG_OUTPUT stdout (default) / file / both
LOG_FILE path (for file / both)
LOG_FORMAT json (default) / text
LOG_LEVEL debug / info (default) / warn / error
LOG_ROTATE_MAX_SIZE_MB / _MAX_BACKUPS / _MAX_AGE_DAYS / _COMPRESS rotation

Docs

Tests

go test ./...                                          # unit (cron parser)
# integration / stress need Postgres:
GUA_PG_DSN='postgres://user:pass@host:5432/db?sslmode=disable' go test ./delayquene/ -run TestRiver
GUA_STRESS=1 GUA_STRESS_N=2000 GUA_PG_DSN=... go test ./delayquene/ -run TestRiverStress -v

About

Distributed crontab-style job scheduler in Go on PostgreSQL (River); HTTP/gRPC trigger delivery | Go 實作的分散式 crontab 排程器,後端 PostgreSQL(River),HTTP/gRPC 觸發投遞

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages