Start the Workers Once and Cache the First History Pull

Worker boot and cached history load
Suggested cover: background workers starting once while a dashboard opens and caches its first history pull.

A one-file service still needs a clean handoff into the UI

After the detector and database layers are present, the next challenge is startup discipline. A single-file system can feel chaotic if threads begin on every refresh or if the UI code is forced to remember whether the backend is already alive.

The usual cure is small and effective: put a session flag in front of the worker startup, then keep the first data fetch behind a cache boundary. That gives the page a practical memory of what has already been done.

This is also one of the best places to add supporting code around the main fragments. Startup behavior benefits from extra explanatory snippets because it blends control flow, state and timing.

import psycopg2
from datetime import datetime

# Latin characters only
db_config = {
    "dbname": "faf",
    "user": "postgres",
    "password": "",
    "host": "localhost",
    "port": "5432"
}

This neighboring component echoes the font fallback idea without stepping into the numbered recovery chain too early.

That fallback is useful as a side note because it reminds the reader that startup code is not only about threads. It is also where tiny environmental assumptions should be handled gracefully.

def run_batch_pipeline():
    conn = None
    cur = None
    try:
        print("Start processing...")
        conn = psycopg2.connect(**db_config)
        cur = conn.cursor()

The seventh marked slice holds the streaming loop that opens the detector, capture and font fallback before handing rows to the database layer.

Notice how the loop stays readable because earlier responsibilities were already defined. The frame helper, annotation function and write function do the heavy lifting, so the worker loop mostly orchestrates.

Alternative component: describe the refresh contract explicitly

        sql = """
        INSERT INTO mart.traffic_history (report_hour, camera_id, vehicle_type, avg_speed, intensity, density)
        SELECT 
            date_trunc('hour', last_update), camera_id, vehicle_type,
            AVG(avg_speed), COUNT(*), AVG(count)
        FROM mart.current_traffic

This side block reads like an architectural note. The color shift keeps it separate from the numbered slices while still reinforcing the same section of the file.

Only after the worker loop is clear does it make sense to show the session gate and the cached data pull. That ordering helps because the UI startup now feels like a handoff instead of a collision.

        GROUP BY 1, 2, 3
        ON CONFLICT (report_hour, camera_id, vehicle_type) 
        DO UPDATE SET 
            avg_speed = EXCLUDED.avg_speed,
            intensity = EXCLUDED.intensity,
            density = EXCLUDED.density;
        """

The eighth marked slice holds the one-time thread startup, page title and cached history loader, which together form the bridge into the dashboard.

  • Guard worker startup with session state so rerenders do not spawn duplicate loops.
  • Cache the first history pull because dashboards usually need stable, recent data more than they need constant raw queries.
  • Let the worker loop orchestrate helpers instead of duplicating their logic inline.
Startup code feels lighter when it remembers what has already been started.