# 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 ```yaml # config.yaml (optional - auto-detects if omitted) sensor: worker_name: "sensor-prod-01" capabilities: runtimes: ["python", "shell", "node"] heartbeat_interval: 30 ``` ```bash # Override runtime detection export ATTUNE_SENSOR_RUNTIMES="python,shell" # Start service (auto-registers on startup) cargo run --bin attune-sensor ``` --- ## Configuration ### Auto-Detection (Recommended) 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 ```yaml 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 ```bash # 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 ```sql -- 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 ```sql -- 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 ```bash # 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 ```bash # Check if binary is available which python3 which node # Override detection export ATTUNE_SENSOR_RUNTIMES="python,shell,node" ``` ### Worker Not Registering ```bash # Check migration applied psql -c "\d worker" attune # Should see 'worker_role' column # Apply migration sqlx migrate run ``` ### Heartbeat Not Updating ```bash # Check sensor service is running ps aux | grep attune-sensor # Check logs for errors journalctl -u attune-sensor -f | grep heartbeat ``` --- ## Migration Required ```bash # 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 ```rust 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: ```sql -- 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`