Files
attune/docs/QUICKREF-sensor-worker-registration.md
2026-02-04 17:46:30 -06:00

5.0 KiB

QUICKREF: Sensor Worker Registration

Quick reference for sensor worker runtime capability reporting


What It Does

Sensor services now register themselves in the database and report which runtimes (Python, Node.js, Shell, Native) they have available. This enables:

  • Runtime capability tracking per sensor worker
  • Health monitoring via heartbeats
  • Foundation for distributed sensor scheduling (future)

TL;DR

# config.yaml (optional - auto-detects if omitted)
sensor:
  worker_name: "sensor-prod-01"
  capabilities:
    runtimes: ["python", "shell", "node"]
  heartbeat_interval: 30
# Override runtime detection
export ATTUNE_SENSOR_RUNTIMES="python,shell"

# Start service (auto-registers on startup)
cargo run --bin attune-sensor

Configuration

No configuration needed. Sensor service will:

  • Auto-detect Python (checks for python3/python)
  • Auto-detect Node.js (checks for node)
  • Always include Shell and Native

Explicit Configuration

sensor:
  worker_name: "sensor-{hostname}"     # Default: sensor-{hostname}
  host: "10.0.1.42"                    # Default: hostname
  max_concurrent_sensors: 10            # Default: 10
  heartbeat_interval: 30                # Default: 30 seconds
  capabilities:
    runtimes: ["python", "shell"]       # Override auto-detection

Environment Override

# Highest priority - overrides config and auto-detection
export ATTUNE_SENSOR_RUNTIMES="shell,native"  # Comma-separated

Runtime Detection Priority

  1. ATTUNE_SENSOR_RUNTIMES env var (highest)
  2. config.sensor.capabilities.runtimes (medium)
  3. Auto-detection (lowest)

Database Schema

-- Sensor workers use the unified worker table
SELECT * FROM worker WHERE worker_role = 'sensor';

-- Columns:
--   id, name, worker_type, worker_role, host, status
--   capabilities JSONB: {"runtimes": ["python", "shell"], ...}
--   last_heartbeat: Updated every 30s (configurable)

Querying Sensor Workers

-- Active sensor workers
SELECT name, host, capabilities->'runtimes' AS runtimes
FROM worker
WHERE worker_role = 'sensor' AND status = 'active';

-- Workers with Python runtime
SELECT name FROM worker
WHERE worker_role = 'sensor'
  AND capabilities->'runtimes' ? 'python';

-- Stale workers (no heartbeat in 5 min)
SELECT name, last_heartbeat
FROM worker
WHERE worker_role = 'sensor'
  AND last_heartbeat < NOW() - INTERVAL '5 minutes';

Lifecycle

Service Start → Register (INSERT/UPDATE worker)
              ↓
           Heartbeat Loop (every 30s)
              ↓
Service Stop → Deregister (SET status = 'inactive')

Monitoring

Logs

# Registration
grep "Registering sensor worker" logs
grep "Sensor worker registered with ID" logs

# Heartbeat
grep "Sensor worker heartbeat" logs

# Deregistration
grep "Deregistering sensor worker" logs

Metrics

  • Active workers: SELECT COUNT(*) FROM worker WHERE worker_role = 'sensor' AND status = 'active'
  • Heartbeat lag: NOW() - last_heartbeat
  • Runtime availability: Count workers per runtime

Troubleshooting

Runtime Not Detected

# Check if binary is available
which python3
which node

# Override detection
export ATTUNE_SENSOR_RUNTIMES="python,shell,node"

Worker Not Registering

# Check migration applied
psql -c "\d worker" attune
# Should see 'worker_role' column

# Apply migration
sqlx migrate run

Heartbeat Not Updating

# Check sensor service is running
ps aux | grep attune-sensor

# Check logs for errors
journalctl -u attune-sensor -f | grep heartbeat

Migration Required

# Apply migration (adds worker_role column)
sqlx migrate run

# Update SQLx metadata
cargo sqlx prepare --workspace

Migration: 20260131000001_add_worker_role.sql


Files

  • Implementation: crates/sensor/src/sensor_worker_registration.rs
  • Service integration: crates/sensor/src/service.rs
  • Config: crates/common/src/config.rs (SensorConfig struct)
  • Migration: migrations/20260131000001_add_worker_role.sql
  • Docs: docs/sensors/sensor-worker-registration.md

Example: Custom Capabilities

use attune_sensor::SensorWorkerRegistration;

let mut registration = SensorWorkerRegistration::new(pool, &config);
registration.register().await?;

// Add custom capability
registration.add_capability("gpu_enabled".to_string(), json!(true));
registration.update_capabilities().await?;

Future: Distributed Scheduling

Once implemented, sensors will be scheduled on workers with required runtime:

-- Find workers for Python sensor
SELECT * FROM worker
WHERE worker_role IN ('sensor', 'hybrid')
  AND status = 'active'
  AND capabilities->'runtimes' ? 'python'
ORDER BY last_heartbeat DESC;

See Also

  • Full docs: docs/sensors/sensor-worker-registration.md
  • Worker registration: crates/worker/src/registration.rs (similar pattern)
  • Sensor runtime: docs/sensors/sensor-runtime.md