Skip to content

brian-nunez/btick

Repository files navigation

BTick Scheduler Service

BTick is a generic API-driven scheduler service for recurring HTTP jobs.

It provides:

  • Scheduler API (cmd/scheduler-api):
    • JSON API under /api/v1
    • server-rendered UI with templ + templui + tailwindcss + htmx
    • API key management and API key auth
  • Scheduler Worker (cmd/scheduler-worker):
    • Postgres polling for due jobs
    • safe multi-worker claim semantics
    • HTTP execution with retries and run history persistence
    • execution through task-orchestration

Architecture

  • Control plane: API service
  • Execution plane: Worker service
  • Source of truth: Postgres (jobs, job_runs, api_keys)
  • Scheduling model: persisted next_run_at + cron expression
  • No in-memory timer dependence

Required Libraries

Project Layout

cmd/
  scheduler-api/
  scheduler-worker/
internal/
  apikeys/
  auth/
  authorization/
  config/
  db/
  handlers/
    errors/
    v1/
  httpserver/
  jobs/
  runs/
  scheduler/
  worker/
migrations/
queries/
sdk/
  go/
    scheduler/
views/

Environment Variables

Shared:

  • DATABASE_URL (required)

API:

  • PORT (default 8080)
  • STATIC_ASSETS_PATH (default ./assets)
  • UI_SESSION_SECRET (default dev-session-secret-change-me)
  • UI_SESSION_TTL_HOURS (default 12)

Worker:

  • WORKER_ID (default scheduler-worker-1)
  • WORKER_CONCURRENCY (default 4)
  • WORKER_POLL_INTERVAL_MS (default 2000)
  • WORKER_STALE_CLAIM_MINUTES (default 5)
  • WORKER_MAX_CLAIMS_PER_TICK (default 20)
  • WORKER_TASK_LOG_PATH (default ./logs/tasks)
  • WORKER_TASK_STATE_DB_PATH (default ./data/task_orchestration.db)
  • WORKER_HTTP_TIMEOUT_SECONDS (default 90)

Run Locally

  1. Set DATABASE_URL.
  2. Start API:
go run ./cmd/scheduler-api
  1. Start worker:
go run ./cmd/scheduler-worker

Migrations run automatically on startup.

Run with Docker Compose

Build and run Postgres + API + worker:

docker compose up --build

Services:

  • Scheduler API: http://localhost:8080
  • Scheduler Worker: separate container (scheduler-worker)
  • Adminer: http://localhost:8010
  • Postgres: localhost:5432 (btick / btick / btick)

Notes:

  • Both API and worker run migrations on startup.
  • Update UI_SESSION_SECRET in compose.yml before production use.

Build Container Images

Build API image:

docker build -f Dockerfile.api -t btick-scheduler-api:local .

Build worker image:

docker build -f Dockerfile.worker -t btick-scheduler-worker:local .

API Endpoints

Health:

  • GET /api/v1/health
  • GET /healthz
  • GET /readyz

Jobs:

  • POST /api/v1/jobs
  • GET /api/v1/jobs
  • GET /api/v1/jobs/{jobId}
  • PATCH /api/v1/jobs/{jobId}
  • DELETE /api/v1/jobs/{jobId}
  • POST /api/v1/jobs/{jobId}/pause
  • POST /api/v1/jobs/{jobId}/resume
  • POST /api/v1/jobs/{jobId}/trigger

Runs:

  • GET /api/v1/jobs/{jobId}/runs
  • GET /api/v1/runs/{runId}

API Keys:

  • POST /api/v1/api-keys
  • GET /api/v1/api-keys
  • POST /api/v1/api-keys/{keyId}/revoke

Authentication

Protected API endpoints expect:

Authorization: Bearer <api-key>

Keys are generated once and only key_prefix + secure hash are stored.

UI Routes

  • /register
  • /login
  • /ui/jobs
  • /ui/jobs/new
  • /ui/jobs/{jobId}
  • /ui/jobs/{jobId}/edit
  • /ui/jobs/{jobId}/runs
  • /ui/runs/{runId}
  • /ui/api-keys
  • /ui/api-keys/new

SDK

Go SDK lives at:

  • sdk/go/scheduler

See sdk/go/scheduler/README.md for examples.

SQLC + Migrations

  • SQL schema migration files: migrations/
  • Query contracts: queries/
  • SQLC config: sqlc.yaml
  • Query implementation package: internal/db/sqlc

About

Scheduler for recurring HTTP jobs with distributed workers, retries, run history, API keys, and Go SDK.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors