Skip to main content

Daemon mode

Daemon mode runs Reqon as a long-running service, executing scheduled missions automatically.

Starting the daemon

reqon ./missions/ --daemon

How it works

  1. Daemon loads all missions from the specified path
  2. Parses schedule configurations
  3. Runs missions according to their schedules
  4. Continues until stopped

Command options

reqon ./missions/ --daemon [options]

Options:
--auth <file> Credentials file
--verbose Enable detailed logging
--check-interval How often to check schedules (default: 1000ms)

Example setup

Mission files

missions/
├── sync-customers.vague
├── sync-orders.vague
└── daily-report.vague

sync-customers.vague

mission SyncCustomers {
schedule: every 15 minutes

source API { auth: bearer, base: "https://api.example.com" }
store customers: file("customers")

action Sync {
get "/customers" { since: lastSync }
store response -> customers { key: .id, upsert: true }
}

run Sync
}

Running

reqon ./missions/ --daemon --auth ./credentials.json --verbose

Process management

Foreground

reqon ./missions/ --daemon

Press Ctrl+C to stop.

Background (Linux)

nohup reqon ./missions/ --daemon > reqon.log 2>&1 &

Systemd service

Create /etc/systemd/system/reqon.service:

[Unit]
Description=Reqon Data Sync Daemon
After=network.target

[Service]
Type=simple
User=reqon
WorkingDirectory=/opt/reqon
ExecStart=/usr/bin/npx reqon ./missions/ --daemon --auth ./credentials.json
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Enable and start:

sudo systemctl enable reqon
sudo systemctl start reqon

Docker

Dockerfile:

FROM node:20-alpine

WORKDIR /app
COPY package*.json ./
RUN npm install

COPY . .

CMD ["npx", "reqon", "./missions/", "--daemon"]

docker-compose.yml:

version: '3'
services:
reqon:
build: .
volumes:
- ./missions:/app/missions
- ./credentials.json:/app/credentials.json
- reqon-data:/app/.vague-data
environment:
- NODE_ENV=production
restart: unless-stopped

volumes:
reqon-data:

Graceful shutdown

Reqon handles SIGINT and SIGTERM:

  1. Stops accepting new runs
  2. Waits for in-progress missions to complete
  3. Saves state
  4. Exits cleanly
# Graceful stop
kill -TERM $(pgrep -f "reqon.*daemon")

# Or with systemd
systemctl stop reqon

Health checks

Status endpoint

Enable HTTP health endpoint:

reqon ./missions/ --daemon --health-port 8080

Check health:

curl http://localhost:8080/health
# {"status":"ok","uptime":3600,"missionsLoaded":3}

File-based health

mission HealthCheck {
schedule: every 1 minute

action Check {
store { status: "ok", timestamp: now() } -> health
}
}

Monitor the health store file.

Logging

Log levels

# Default logging
reqon ./missions/ --daemon

# Verbose logging
reqon ./missions/ --daemon --verbose

# Environment variable
REQON_LOG_LEVEL=debug reqon ./missions/ --daemon

Log output

[2024-01-20 09:00:00] [INFO] Starting Reqon daemon
[2024-01-20 09:00:00] [INFO] Loaded 3 missions
[2024-01-20 09:00:00] [INFO] SyncCustomers: Next run at 09:15:00
[2024-01-20 09:00:00] [INFO] SyncOrders: Next run at 09:05:00
[2024-01-20 09:00:00] [INFO] DailyReport: Next run at 2024-01-21 00:00:00
[2024-01-20 09:05:00] [INFO] SyncOrders: Starting run
[2024-01-20 09:05:02] [INFO] SyncOrders: Completed (2.1s)

Structured logging

REQON_LOG_FORMAT=json reqon ./missions/ --daemon
{"timestamp":"2024-01-20T09:00:00Z","level":"info","message":"Starting run","mission":"SyncCustomers"}

Monitoring

Metrics

Export metrics with --metrics-port:

reqon ./missions/ --daemon --metrics-port 9090

Prometheus format:

# HELP reqon_mission_runs_total Total mission runs
reqon_mission_runs_total{mission="SyncCustomers",status="success"} 142
reqon_mission_runs_total{mission="SyncCustomers",status="failure"} 3

# HELP reqon_mission_duration_seconds Mission run duration
reqon_mission_duration_seconds{mission="SyncCustomers",quantile="0.5"} 2.1

Alerting

Create alerting rules:

groups:
- name: reqon
rules:
- alert: ReqonMissionFailing
expr: rate(reqon_mission_runs_total{status="failure"}[5m]) > 0.1
for: 10m
labels:
severity: warning
annotations:
summary: "Mission {{ $labels.mission }} is failing"

Best practices

Use separate credentials

# Production credentials
reqon ./missions/ --daemon --auth ./prod-credentials.json

Run as non-root

# Create dedicated user
useradd -r -s /bin/false reqon

# Run as that user
sudo -u reqon reqon ./missions/ --daemon

Persistent storage

Ensure .vague-data is on persistent storage:

volumes:
- /var/lib/reqon:/app/.vague-data

Health monitoring

Always enable health checks:

reqon ./missions/ --daemon --health-port 8080

Log rotation

# Use logrotate
/var/log/reqon/*.log {
daily
rotate 7
compress
missingok
notifempty
}