Skip to content

Background Scheduler

The Joynare Nexus Background Scheduler is a highly resilient, enterprise-grade trigger framework that enables scheduling automated executions of Go-based built-in services, flows, or adapter services.

It implements a hybrid architecture combining Static Declarative Configurations (ideal for infrastructure and utility tasks) and Dynamic Database-Backed Schedules (fully manageable at runtime via REST APIs without server restarts).


📅 Architecture Overview

The scheduler leverages a coordinated execution queue utilizing a specialized, thread-safe background cron daemon (based on github.com/robfig/cron/v3 with standard 5-field cron and interval supports).


🛠️ Configuration & Schema

1. Static Configuration (config/scheduler.yaml)

Static schedules are defined inside a declarative YAML file located at config/scheduler.yaml. On server startup, these definitions are automatically loaded, checked against the registry, and scheduled.

yaml
# config/scheduler.yaml
schedules:
  - name: "daily-customer-sync"
    description: "Triggers ProcessCustomer flow every day at midnight"
    service: "examples:ProcessCustomer"
    cron: "0 0 * * *"
    enabled: true
    input:
      sync_type: "full"
      
  - name: "metrics-cleanup"
    description: "Cleans up system transaction history logs every 5 minutes"
    service: "system.utils:CleanupMetrics"
    interval: "300s"
    enabled: true
    input: {}

2. Dynamic Database Schema (scheduler_tasks table)

When MySQL database system configurations are active, Joynare Nexus automatically provisions and manages a schema to track runtime dynamic schedules:

sql
CREATE TABLE IF NOT EXISTS scheduler_tasks (
    id VARCHAR(36) PRIMARY KEY,
    name VARCHAR(255) UNIQUE NOT NULL,
    description TEXT,
    service_key VARCHAR(255) NOT NULL,
    cron_expr VARCHAR(100) NULL,
    interval_seconds INT NULL,
    input_json TEXT NULL,
    enabled BOOLEAN DEFAULT TRUE,
    last_run TIMESTAMP NULL,
    next_run TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

⚡ Execution Mechanics

1. Trigger Specifications

You can configure schedules using either standard Cron Expressions or human-friendly Intervals:

  • Cron Expression: Standard 5-field crons (e.g. */10 * * * * for every 10 minutes, 0 9 * * 1-5 for weekdays at 9 AM).
  • Interval Strings: Values inside configuration or requests are converted dynamically:
    • Duration strings like "30s", "15m", "3h" (supporting s for seconds, m for minutes, h for hours).
    • Numeric expressions like 300 or "300" are parsed directly as seconds.

2. Execution Isolation & Tracing

Every background run spatchcocked by the scheduler compiles its own transaction pipeline:

  • Trace ID Generation: Each task sputters with a unique, traceable ID formatted as trace-sched-<task_id>-<unix_timestamp>. This allows full trace inspection inside transaction logging.
  • Non-Blocking Runners: Tasks execute inside their own decoupled goroutines. If a task runs longer than its interval, the scheduler executes the subsequent tick in parallel without blocking.
  • State Updates: Upon run completion, last_run and next_run timestamps are calculated and dynamically updated both in the memory list and the persistent SQL database.

🌐 REST API Reference

All schedule administrative endpoints are hosted on the Design API port (default 9092) and support preflight CORS options (Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS).

1. Get Schedules

Fetches a merged list of all static and dynamic schedules, complete with run statistics.

  • Method: GET
  • Endpoint: /api/admin/schedules
  • Response Format:
json
[
  {
    "id": "static-daily-customer-sync",
    "name": "daily-customer-sync",
    "description": "Triggers ProcessCustomer flow every day at midnight",
    "service": "examples:ProcessCustomer",
    "cron": "0 0 * * *",
    "interval": 0,
    "input": {
      "sync_type": "full"
    },
    "enabled": true,
    "isDynamic": false,
    "lastRun": "2026-05-18T00:00:00Z",
    "nextRun": "2026-05-19T00:00:00Z"
  },
  {
    "id": "e4a2fb98-75b2-4cd8-b0a3-bf2e89643441",
    "name": "dynamic-inventory-audit",
    "description": "Dynamic inventory checker every hour",
    "service": "inventory:AuditRecords",
    "cron": "",
    "interval": 3600,
    "input": {},
    "enabled": true,
    "isDynamic": true,
    "lastRun": "2026-05-18T16:00:00Z",
    "nextRun": "2026-05-18T17:00:00Z"
  }
]

2. Save/Update Dynamic Schedule

Creates a new dynamic database task or updates an existing one if the id field matches. Saving a schedule automatically triggers a thread-safe reload of the background daemon.

  • Method: POST
  • Endpoint: /api/admin/schedules
  • Request Body:
json
{
  "id": "e4a2fb98-75b2-4cd8-b0a3-bf2e89643441", 
  "name": "dynamic-inventory-audit",
  "description": "Dynamic inventory checker every hour",
  "service": "inventory:AuditRecords",
  "cron": "",
  "interval": 3600,
  "input": {},
  "enabled": true
}
  • Response:
json
{
  "status": "success",
  "message": "Schedule saved successfully",
  "id": "e4a2fb98-75b2-4cd8-b0a3-bf2e89643441"
}

3. Toggle Schedule

Enables or disables a schedule. Disabling it stops scheduling ticks while keeping its database history.

  • Method: POST
  • Endpoint: /api/admin/schedules/{id}/toggle
  • Request Body (Optional):
json
{
  "enabled": false
}
  • Response:
json
{
  "status": "success",
  "message": "Schedule toggle updated successfully",
  "enabled": false
}

4. Trigger Manual Execute

Invokes the schedule instantly on a detached background goroutine for testing or manual operations, without altering its next scheduled execution time.

  • Method: POST
  • Endpoint: /api/admin/schedules/{id}/run
  • Response:
json
{
  "status": "success",
  "message": "Schedule execution triggered manually in the background"
}

5. Delete Dynamic Schedule

Removes a task from the database and stops background worker triggers immediately.

  • Method: DELETE
  • Endpoint: /api/admin/schedules/{id}
  • Response:
json
{
  "status": "success",
  "message": "Schedule deleted successfully"
}

Released under the ISC License.