6.1 KiB
Sensor Service Cleanup: Standalone Sensors Only
Date: 2024-02-02
Status: Complete
Breaking Change: Yes - Removes poll-based sensor support
Overview
Removed the "builtin" poll-based sensor functionality from the sensor service. The sensor service now exclusively manages standalone sensor processes (like attune-core-timer-sensor) that run as independent daemons and communicate via the API.
Motivation
The original architecture had two sensor modes:
- Poll-based sensors: Scripts executed periodically by the sensor service, which would generate events directly
- Standalone sensors: Independent processes that communicate via API
This created architectural confusion where the sensor service was both:
- Managing sensor process lifecycles ✅
- Directly generating events from sensor output ❌
The correct architecture is that all sensors are independent processes that use the API to create events. The sensor service should only manage process lifecycles.
Changes Made
Files Deleted
event_generator.rs- Only used for poll-based sensors to directly create eventsrule_matcher.rs- Unused module for poll-based rule evaluationtimer_manager.rs- Unused (timer functionality now inattune-core-timer-sensorstandalone)sensor_runtime.rs- Only used for executing poll-based sensor scripts
Files Modified
lib.rs
- Removed exports for deleted modules
- Cleaner public API surface
service.rs
- Removed
EventGeneratordependency - Updated
SensorManagerinitialization to not require event generator - Removed
event_generator()accessor method - Updated documentation
sensor_manager.rs
Major architectural simplification:
- Removed:
EventGeneratordependency - Removed:
SensorRuntimedependency - Removed: Poll-based sensor support entirely
- Removed:
start_poll_based_sensor()method - Removed:
poll_sensor()method - Removed:
run_loop()polling loop - Kept: Standalone sensor support with token provisioning
- Simplified:
SensorInstancenow only supports standalone mode - Updated: Documentation to clarify standalone-only architecture
Key architectural changes:
// Before: Constructor needed event_generator
pub fn new(db: PgPool, event_generator: Arc<EventGenerator>) -> Self
// After: No event generation dependencies
pub fn new(db: PgPool) -> Self
The sensor manager now focuses on:
- Starting sensor processes when rules become active
- Stopping sensor processes when no rules need them
- Provisioning authentication tokens for sensor processes
- Monitoring sensor health via process lifecycle
- Logging sensor stdout/stderr
API Event Creation Fix
Also fixed a bug in api/src/routes/events.rs where the create_event endpoint wasn't parsing the trigger_instance_id parameter to set rule associations on events. Timer sensors send this parameter in format "rule_{id}", and now the API properly:
- Parses the rule ID from the string
- Looks up the rule reference from the database
- Sets
ruleandrule_reffields on the event record
This ensures timer events (and other rule-specific events) properly show their associated rule in the web UI.
Architecture After Cleanup
Sensor Service Responsibilities
- Lifecycle Management: Start/stop sensor processes based on active rules
- Token Provisioning: Create API tokens for sensors to authenticate
- Process Monitoring: Track sensor process health (stdout/stderr logging)
- Rule Synchronization: Listen for rule lifecycle events and adjust sensors
Sensor Process Responsibilities
- Event Generation: Monitor for conditions and create events via API
- Configuration: Read trigger instance configs and act accordingly
- Authentication: Use provisioned tokens to call API endpoints
- Independence: Run as standalone daemons, no coupling to sensor service
Example: Timer Sensor
The attune-core-timer-sensor standalone process:
- Runs independently as a daemon
- Receives API token and configuration via environment variables
- Monitors database for timer trigger instances
- Creates events by calling
POST /api/v1/eventsendpoint - Passes
trigger_instance_idto associate events with specific rules
Testing
- ✅ All sensor service tests pass (17 passed, 3 ignored)
- ✅ Workspace compiles cleanly with no warnings
- ✅ No breaking changes to sensor process interface
Impact
For Sensor Developers
✅ No change - Sensors were already expected to be standalone processes that call the API
For Sensor Service
✅ Simplified - Removed ~400 lines of poll-based sensor code
✅ Clearer responsibility - Only manages process lifecycles, doesn't generate events
✅ Better separation of concerns - Event generation is always through the API
For Event Creation
✅ Fixed bug - Rule associations now properly set on timer events
✅ Web UI - Events now display their associated rule correctly
Migration Notes
No migration needed - The poll-based sensor functionality was never used in production. All current sensors (e.g., attune-core-timer-sensor) are already standalone processes.
Files Changed
Deleted:
- crates/sensor/src/event_generator.rs
- crates/sensor/src/rule_matcher.rs
- crates/sensor/src/timer_manager.rs
- crates/sensor/src/sensor_runtime.rs
Modified:
- crates/sensor/src/lib.rs
- crates/sensor/src/service.rs
- crates/sensor/src/sensor_manager.rs
- crates/api/src/routes/events.rs
Related Documentation
docs/architecture/sensor-service.md- Should be updated to reflect standalone-only architecturedocs/architecture/webhook-system-architecture.md- Webhook sensors follow same patternpacks/core/sensors/interval_timer_sensor.yaml- Example of standalone sensor config
Future Considerations
- Sensor Discovery: Consider auto-discovery of sensor binaries in pack directories
- Health Checks: Add more sophisticated sensor health monitoring beyond process lifecycle
- Graceful Restart: Implement graceful sensor restart on configuration changes
- Resource Limits: Add CPU/memory limits for sensor processes