9.0 KiB
Timer Sensor Quick Start Guide
Last Updated: 2025-01-27
Audience: Developers
Overview
This guide will help you get the timer sensor up and running for development and testing.
Prerequisites
- Rust 1.70+ installed
- PostgreSQL 14+ running
- RabbitMQ 3.12+ running
- Attune API service running
Step 1: Start Dependencies
Using Docker Compose
# From project root
docker-compose up -d postgres rabbitmq
Manual Setup
# PostgreSQL (already running on localhost:5432)
# RabbitMQ (already running on localhost:5672)
Verify services are running:
# PostgreSQL
psql -h localhost -U postgres -c "SELECT version();"
# RabbitMQ
rabbitmqadmin list queues
Step 2: Start the API Service
# Terminal 1
cd attune
make run-api
# Or manually:
cd crates/api
cargo run
Verify API is running:
curl http://localhost:8080/health
Step 3: Create a Service Account for the Sensor
NOTE: Service accounts are not yet implemented. This step will be available after implementing the service account system.
For now, you'll need to use a user token or skip authentication during development.
When Service Accounts Are Implemented
# Get admin token (from login or existing session)
export ADMIN_TOKEN="your_admin_token_here"
# Create sensor service account
curl -X POST http://localhost:8080/service-accounts \
-H "Authorization: Bearer ${ADMIN_TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"name": "sensor:core.timer",
"scope": "sensor",
"description": "Timer sensor for development",
"ttl_days": 90,
"metadata": {
"trigger_types": ["core.timer"]
}
}'
# Save the returned token
export SENSOR_TOKEN="eyJhbGci..."
Step 4: Start the Timer Sensor
# Terminal 2
cd attune
# Set environment variables
export ATTUNE_API_URL="http://localhost:8080"
export ATTUNE_API_TOKEN="your_sensor_token_here" # Or user token for now
export ATTUNE_SENSOR_REF="core.timer"
export ATTUNE_MQ_URL="amqp://localhost:5672"
export ATTUNE_LOG_LEVEL="debug"
# Run the sensor
cargo run --package core-timer-sensor
You should see output like:
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Starting Attune Timer Sensor"}
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Configuration loaded successfully","sensor_ref":"core.timer","api_url":"http://localhost:8080"}
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"API connectivity verified"}
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Timer manager initialized"}
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Connected to RabbitMQ"}
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Started consuming messages from queue 'sensor.core.timer'"}
Step 5: Create a Timer-Based Rule
Via API
# Create a simple timer rule that fires every 5 seconds
curl -X POST http://localhost:8080/rules \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"ref": "timer_every_5s",
"label": "Timer Every 5 Seconds",
"description": "Test timer that fires every 5 seconds",
"pack": "core",
"trigger_type": "core.timer",
"trigger_params": {
"type": "interval",
"interval": 5,
"unit": "seconds"
},
"action_ref": "core.echo",
"action_params": {
"message": "Timer fired!"
},
"enabled": true
}'
Via CLI
# Not yet implemented
# attune rule create timer_every_5s --trigger core.timer --action core.echo
Step 6: Watch the Sensor Logs
In the sensor terminal, you should see:
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Handling RuleCreated","rule_id":123,"ref":"timer_every_5s"}
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Starting timer for rule 123"}
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Timer started for rule 123"}
{"timestamp":"2025-01-27T12:34:56Z","level":"info","message":"Interval timer loop started for rule 123","interval":5}
After 5 seconds:
{"timestamp":"2025-01-27T12:35:01Z","level":"info","message":"Timer fired for rule 123, created event 456"}
Step 7: Verify Events Are Created
# List events
curl http://localhost:8080/events \
-H "Authorization: Bearer ${TOKEN}"
# Should show events with trigger_type "core.timer"
Step 8: Test Rule Disable/Enable
Disable the rule
curl -X POST http://localhost:8080/rules/timer_every_5s/disable \
-H "Authorization: Bearer ${TOKEN}"
Sensor logs should show:
{"timestamp":"2025-01-27T12:35:10Z","level":"info","message":"Handling RuleDisabled","rule_id":123}
{"timestamp":"2025-01-27T12:35:10Z","level":"info","message":"Stopped timer for rule 123"}
Re-enable the rule
curl -X POST http://localhost:8080/rules/timer_every_5s/enable \
-H "Authorization: Bearer ${TOKEN}"
Sensor logs should show:
{"timestamp":"2025-01-27T12:35:20Z","level":"info","message":"Handling RuleEnabled","rule_id":123}
{"timestamp":"2025-01-27T12:35:20Z","level":"info","message":"Starting timer for rule 123"}
Step 9: Test Different Timer Types
Every 1 minute
{
"trigger_params": {
"type": "interval",
"interval": 1,
"unit": "minutes"
}
}
Every 1 hour
{
"trigger_params": {
"type": "interval",
"interval": 1,
"unit": "hours"
}
}
One-time at specific datetime
{
"trigger_params": {
"type": "date_time",
"fire_at": "2025-01-27T15:00:00Z"
}
}
Development Workflow
Making Changes to the Sensor
# 1. Make code changes in crates/core-timer-sensor/src/
# 2. Build and check for errors
cargo build --package core-timer-sensor
# 3. Run tests
cargo test --package core-timer-sensor
# 4. Restart the sensor
# Stop with Ctrl+C, then:
cargo run --package core-timer-sensor
Testing Edge Cases
-
Sensor restart with active rules:
- Create a rule
- Stop the sensor (Ctrl+C)
- Start the sensor again
- Verify it loads and starts the timer for existing rules
-
Multiple rules with different intervals:
- Create 3 rules with 5s, 10s, and 15s intervals
- Verify all timers fire independently
-
Rule updates:
- Update a rule's trigger_params
- Currently requires disable/enable cycle
- Future: should handle updates automatically
-
Network failures:
- Stop the API service
- Observe sensor logs (should show retry attempts)
- Restart API
- Verify sensor reconnects
Debugging
Enable Debug Logging
export ATTUNE_LOG_LEVEL="debug"
cargo run --package core-timer-sensor
Common Issues
"Failed to connect to Attune API"
- Verify API is running:
curl http://localhost:8080/health - Check
ATTUNE_API_URLis correct
"Failed to connect to RabbitMQ"
- Verify RabbitMQ is running:
rabbitmqctl status - Check
ATTUNE_MQ_URLis correct - Try:
amqp://guest:guest@localhost:5672/%2F
"Insufficient permissions to create event"
- Service account system not yet implemented
- Use a user token temporarily
- Or wait for service account implementation
"Timer not firing"
- Check sensor logs for "Timer started for rule X"
- Verify rule is enabled
- Check trigger_params format is correct
- Enable debug logging to see more details
"No timers loaded on startup"
- API endpoint
/rules?trigger_type=core.timernot yet implemented - Create a rule after sensor starts
- Timers will be managed via RabbitMQ messages
Next Steps
- Implement Service Account System - See
docs/service-accounts.md - Add Cron Timer Support - Implement cron parsing and scheduling
- Add Tests - Integration tests for full sensor workflow
- Add Metrics - Prometheus metrics for monitoring
- Production Deployment - systemd service, Docker image, Kubernetes deployment
Resources
- Sensor Interface Specification
- Service Accounts Documentation
- Timer Sensor README
- Sensor Authentication Overview
Troubleshooting Tips
View RabbitMQ Queues
# List all queues
rabbitmqadmin list queues
# Should see: sensor.core.timer
# View messages in queue
rabbitmqadmin get queue=sensor.core.timer count=10
View Sensor Queue Bindings
# List bindings for sensor queue
rabbitmqadmin list bindings | grep sensor.core.timer
# Should see bindings for:
# - rule.created
# - rule.enabled
# - rule.disabled
# - rule.deleted
Monitor API Logs
# In API terminal, should see:
# "Published RuleCreated message for rule timer_every_5s"
# "Published RuleEnabled message for rule timer_every_5s"
# "Published RuleDisabled message for rule timer_every_5s"
Test Token Manually
# Decode JWT to inspect claims
echo "eyJhbGci..." | jq -R 'split(".") | .[1] | @base64d | fromjson'
# Should show:
{
"sub": "sensor:core.timer",
"scope": "sensor",
"metadata": {
"trigger_types": ["core.timer"]
}
}