System Architecture
Database schema, triggers, nightly scheduler, and the end-to-end data flow for Historical Summary
System Architecture
This page walks through every layer of the Historical Summary system, from the MySQL tables that store aggregated counts, through the triggers and nightly jobs that populate them, to the migration procedures that handle first-time onboarding for new labs.
High-Level Data Flow
Database Schema
operation_historical_summary
This is the central fact table. Think of it as a pre-aggregated star schema: every row represents "for lab X, on date Y, grouping Z had N occurrences of event E."
CREATE TABLE operation_historical_summary (
id BIGINT NOT NULL AUTO_INCREMENT,
dimension_a_id INT NOT NULL, -- Primary grouping entity (org/ref/branch/dept ID)
dimension_b_id INT DEFAULT NULL, -- Secondary entity (test/sample ID), NULL for bill counts
event_type VARCHAR(250) NOT NULL, -- e.g., 'organization_test', 'referral_sample_accessed'
event_value INT NOT NULL DEFAULT 0, -- The aggregated count
lab_id INT NOT NULL,
ordered_at DATE NOT NULL, -- The date (in lab timezone) when activity occurred
ordered_month DATE GENERATED ALWAYS AS (
DATE_FORMAT(ordered_at, '%Y-%m-01')
) STORED, -- Precomputed first-of-month for fast monthly grouping
PRIMARY KEY (id, ordered_at),
UNIQUE KEY (lab_id, ordered_at, dimension_a_id, dimension_b_id, event_type),
KEY idx_lab_event_month_granularity (lab_id, event_type, ordered_month,
dimension_a_id, dimension_b_id, event_value)
) PARTITION BY RANGE COLUMNS (ordered_at) (
PARTITION summary_table_previous VALUES LESS THAN ('2022-01-01'),
PARTITION summary_table_2022 VALUES LESS THAN ('2023-01-01'),
PARTITION summary_table_2023 VALUES LESS THAN ('2024-01-01'),
-- ... per-year partitions up to 'future' ...
PARTITION summary_table_future VALUES LESS THAN (MAXVALUE)
);Key design points:
- Yearly partitions keep queries fast; the nightly job only ever touches yesterday's partition.
- Composite unique key
(lab_id, ordered_at, dimension_a_id, dimension_b_id, event_type)enablesINSERT ... ON DUPLICATE KEY UPDATEfor idempotent upserts. - Stored generated column
ordered_monthavoids repeatedDATE_FORMAT()calls in monthly aggregation queries. The covering indexidx_lab_event_month_granularityuses this column.
operation_event_log
A simple append-only audit log for the nightly scheduler:
CREATE TABLE operation_event_log (
id BIGINT NOT NULL AUTO_INCREMENT,
event_name VARCHAR(200) NOT NULL, -- e.g., '[IST] Nightly-Operation-Summary-Job'
status VARCHAR(30) NOT NULL, -- 'STARTED' or 'COMPLETED'
created_at DATETIME NOT NULL,
PRIMARY KEY (id)
);Trigger System (Real-Time Delta Updates)
The trigger system ensures that when operational data changes after the nightly job has run, the summary table stays consistent. There are two triggers:
trg_lab_report_relation_after_update
Fires on: AFTER UPDATE on labReportRelation
What it handles:
| Change Detected | Action |
|---|---|
dismissed flag flipped | Increments or decrements all relevant test/sample event counts for that record's org, referral, branch, and department |
sampleCollected or sampleArrivedAndCollected changed | Moves counts between *_accessed and *_not_accessed event types |
Early exit conditions:
- None of
dismissed,sampleCollected, orsampleArrivedAndCollectedactually changed →LEAVE trigger billTimeisNULL→LEAVE trigger- The computed
ordered_atdate is today or in the future →LEAVE trigger(today's data is handled by the nightly job tomorrow)
Access status logic:
Accessed = sampleCollected = 1 OR sampleArrivedAndCollected = 1
Not Accessed = sampleCollected = 0 AND sampleArrivedAndCollected = 0trg_billing_after_update
Fires on: AFTER UPDATE on billing
What it handles:
| Change Detected | Action |
|---|---|
isCancel flag flipped | Adjusts *_bill counts for org, referral, and branch |
orgId_id changed | Decrements old org's counts, inserts/increments new org's test, sample, and bill counts |
docId_id changed | Same pattern for referral dimension |
branch_id changed | Same pattern for branch dimension |
When inserting new counts for re-assigned bills, the trigger recalculates from billingInfo (for tests) and collectedSample (for samples) to get accurate grouped counts.
Nightly Event Scheduler
operation_summary_nightly_event
Schedule: Runs every day at 04:00 UTC (approximately 09:30 IST).
Logic:
- Cursor over timezones - Groups all enabled labs by their
labTimeZone, producing(timezone, comma_separated_lab_ids)pairs. - Compute yesterday's boundaries - For each timezone group:
- Convert
UTC_TIMESTAMP()to local time - Build
local_startandlocal_endfor "yesterday" in that timezone - Convert back to UTC for the actual query
- Convert
- Call the aggregation procedure -
insert_operation_summary_for_all_events(utc_start, utc_end, tz, lab_ids) - Audit log - Writes
STARTEDandCOMPLETEDentries tooperation_event_log.
insert_operation_summary_for_all_events
Iterates over all 16 event types via an internal cursor and calls insert_operation_summary_for_event for each one, wrapped in a single START TRANSACTION / COMMIT block.
insert_operation_summary_for_event
The workhorse procedure. For each event type, it:
- Maps dimensions - Determines which columns become
dimension_a_idanddimension_b_id(e.g.,b.orgId_idfor organization,bI.testId_idfor test). - Builds dynamic SQL - Two query modes:
- Sample events join through
labReportRelation → billing → collectedSample → allTests, usingCOUNT(DISTINCT collectedSample.id)and adding sample access filters. - Non-sample events join through
billingInfo → billing → allTests, usingCOUNT(*)orCOUNT(DISTINCT b.Id)for bill counts.
- Sample events join through
- Executes with
INSERT ... ON DUPLICATE KEY UPDATE- idempotent; safe to re-run for the same day.
Migration Procedure (First-Time Onboarding)
When a lab is first enabled for Historical Summary via the Support Dashboard, they have months or years of historical billing data that the nightly job has never processed. The operation_summary_migration stored procedure handles this data backfill.
Activation Flow
operation_summary_migration
This stored procedure:
- Opens a cursor over
crelio_data_migrationswhereis_scheduled = 1andmigration_type = 'HISTORICAL_SUMMARY'. - For each lab, determines the earliest
billTimein thebillingtable as the start date. - Deletes any existing data in
operation_historical_summaryfor that lab (clean slate). - Calls
operation_summary_testing_long_range()to recompute the full history from start to today. - Updates the
crelio_data_migrationsrecord withis_scheduled=0,job_status='Completed', and the execution time.
operation_summary_migration_event
A MySQL scheduled event that runs daily at 03:30 UTC and simply calls operation_summary_migration(). This is 30 minutes before the nightly summary event, so new labs get their backfill processed before the regular daily job kicks in.
Feature Flag & Onboarding
enable_operation_summary
| Property | Value |
|---|---|
| Django model | LabFeatures.enable_operation_summary (BooleanField, default=False) |
| DB table | labFeatures |
| Frontend check | sessionState.enable_operation_summary (from session data) |
| Support Dashboard | Under "Workflow Configurations → Enable Workflows/Features" |
What Happens When the Flag is Toggled
In support_dashboard_settings_view.py, when the diff contains enable_operation_summary:
if "enable_operation_summary" in diff:
CrelioDataMigrations.objects.filter(
lab_id=lab_id, migration_type="HISTORICAL_SUMMARY"
).delete()
value and CrelioDataMigrations.objects.create(
lab_id=lab_id,
is_scheduled=True,
initiated_by_id=account_manager_id,
migration_type="HISTORICAL_SUMMARY",
)This schedules the lab for historical data backfill. The operation_summary_migration_event MySQL event (daily at 03:30 UTC) picks up these scheduled labs and runs the full recomputation.
Source File Index
| File | Purpose |
|---|---|
operation/sql/operation_historical_summary.sql | Master SQL: table DDL, triggers, procedures, and schedulers |
report/db/scheduler/operation_historical_summary.sql | Standalone nightly scheduler DDL |
report/db/procedures/operation_summary_testing.sql | Manual testing procedure for ad-hoc runs |
admin/account/models/lab_features.py | Feature flag model |
admin/account/views/account_configuration_constant.py | Support Dashboard config constants |