Duration Tracking Implementation
This implementation adds tracking for transit and storage times for trackers. It includes:
- New database columns for tracking durations
- Hourly batch processing to update duration totals
- GraphQL API for retrieving duration statistics
- UI components for displaying average transit and storage times
Database Migration
To apply the database changes, run:
# Install alembic if not already installed
pip install alembic
# Run the migration
alembic upgrade head
Setting Up the Cron Job
The duration tracking system requires an hourly cron job to update the duration totals. To set this up:
- Make sure the update script is executable:
chmod +x app/src/update_durations.py
- Add the following line to your crontab (edit with
crontab -e):
0 * * * * cd /path/to/tracker-graphql-2 && /usr/bin/python3 app/src/update_durations.py >> /var/log/tracker/durations.log 2>&1
Replace /path/to/tracker-graphql-2 with the actual path to your project directory.
Verification
After setting up:
-
Check that the new columns were added to the trackers table:
- current_state_start
- total_transit_time
- total_storage_time
-
Verify the cron job is running by checking the log file:
tail -f /var/log/tracker/durations.log
- Check the UI panels for "Average Transit Time" and "Average Storage Time" are displaying data.
Troubleshooting
-
If durations are not updating:
- Check the cron job logs
- Verify the database migration completed successfully
- Ensure the update_durations.py script has execute permissions
-
If UI panels show no data:
- Check the browser console for GraphQL errors
- Verify the durationStats query is working in GraphQL playground
- Check that the batch processing job is running successfully
Implementation Details
- Duration updates happen hourly via cron
- Times are stored in PostgreSQL interval type
- UI displays durations in days (converted from hours)
- Progress bars max out at 30 days (100%)
- Durations are filtered by the same criteria as the tracker list (brand, campaign, status)
Technical Implementation
The duration tracking system consists of several components (see Frontend Architecture for UI implementation details):
Database Schema
The following columns were added to the trackers table:
-- Timestamp when the current state (IN_TRANSIT or IN_STORAGE) began
current_state_start TIMESTAMP WITH TIME ZONE
-- Total time spent in transit (PostgreSQL interval type)
total_transit_time INTERVAL DEFAULT '0' NOT NULL
-- Total time spent in storage (PostgreSQL interval type)
total_storage_time INTERVAL DEFAULT '0' NOT NULL
An index was also created on current_state_start to optimize the batch processing:
CREATE INDEX idx_trackers_current_state_start ON trackers (current_state_start);
Duration Processor
The core logic for updating durations is in app/src/duration_processor.py. This module:
- Queries all trackers with
IN_TRANSITorIN_STORAGEstatus - For each tracker:
- Calculates the time since the last update
- Adds this time to either
total_transit_timeortotal_storage_timebased on current status - Updates
current_state_startto the current time
- Commits all updates in a single transaction
Cron Job
The app/src/update_durations.py script is a simple wrapper around the duration processor that's designed to be run as a cron job. It:
- Sets up logging
- Creates a database session
- Calls the duration processor
- Handles any exceptions
- Closes the database session
GraphQL API
The GraphQL API includes:
-
Fields on the
Trackertype for individual duration data:totalTransitTimetotalStorageTimecurrentStateStart
-
A
DurationStatstype for aggregated statistics:averageTransitTimeaverageStorageTimetotalTrackers
-
A
durationStatsquery that accepts filters similar to the tracker list