Skip to content

Scheduler & Automated Crons Engine

The Scheduler & Automated Crons Engine handles time-driven automation, timeseries database rollups, appointment reminders, and regulatory market monitors across Planovi.


Functions Matrix

Function NameSchedule / TriggerExecution WindowPrimary Output
run-schedulerCron (*/5 * * * *)Every 5 minutesDispatches queued background tasks from job_queue
reminder-schedulerCron (*/15 * * * *)Every 15 minutesSends meeting, voting, and payment reminders
tender-cronCron (0 8 * * *)Daily at 08:00 UTCScrapes and ingests public energy tender opportunities
aggregate-hourlyCron (5 * * * *)Hourly at minute 05Computes 1-hour rollups into telemetry_hourly
aggregate-dailyCron (15 0 * * *)Daily at 00:15 UTCComputes 24-hour rollups into telemetry_daily
mainHTTP GET / Health ProbeAd-hoc / MonitoringSystem health status, version, and routing index

1. Timeseries Aggregation Architecture

Because high-frequency telemetry generates gigabytes of raw records, analytics and charts are serviced via multi-stage time-bucket rollups:

flowchart TD
    Raw["telemetry_raw (15s-60s readings)"] -->|"aggregate-hourly (Hourly :05)"| Hourly["telemetry_hourly (1h buckets)"]
    Hourly -->|"aggregate-daily (Daily 00:15)"| Daily["telemetry_daily (24h buckets)"]
    
    Raw --> FastQueries["Realtime Gauges (Last 60 mins)"]
    Hourly --> IntradayCharts["Weekly & Monthly Load Curves"]
    Daily --> BillingEngine["Monthly Invoicing & Year-over-Year Audits"]

aggregate-hourly Aggregation Logic

  • Computes avg_power_kw, max_power_kw, total_generation_kwh, total_consumption_kwh, and net_balance_kwh.
  • Identifies missing interval readings and records data-quality completeness scores.

aggregate-daily Aggregation Logic

  • Aggregates 24 hourly buckets.
  • Calculates peak solar production hours, minimum night-time base load, and self-consumption ratio percentage ($\frac{\text{Self-Consumed}}{\text{Total Generated}} \times 100%$).

2. run-scheduler (Job Queue Processor)

Acts as a distributed, transaction-safe background worker:

sequenceDiagram
    autonumber
    participant Cron as Cron Dispatcher
    participant Worker as run-scheduler
    participant DB as "PostgreSQL (job_queue)"

    Cron->>Worker: Trigger POST /run-scheduler
    Worker->>DB: SELECT * FROM job_queue WHERE status = 'PENDING' AND run_at <= NOW() FOR UPDATE SKIP LOCKED LIMIT 10
    DB-->>Worker: Return locked job records
    loop For each job
        Worker->>Worker: Execute job handler (e.g. sync_external_profile)
        alt Success
            Worker->>DB: UPDATE job_queue SET status = 'COMPLETED', updated_at = NOW()
        else Failure
            Worker->>DB: UPDATE job_queue SET retry_count = retry_count + 1, status = CASE WHEN retry_count > 3 THEN 'FAILED' ELSE 'PENDING' END
        end
    end

3. reminder-scheduler

Scans upcoming events across cooperative and CRM modules:

  • Meeting & Voting Deadlines: Alerts cooperative members 24h and 2h before statutory voting sessions close.
  • Invoice Due Dates: Sends friendly reminder 3 days prior to invoice due date, and urgent notification 1 day post-overdue.
  • Calendar Appointments: Integrates with client booking schedules from the Flutter scheduler module.

4. main (Health & Routing Probe)

Serves as the root API gateway monitor:

  • Endpoint: /functions/v1/main
  • Response:
    {
    "service": "planovi-backend",
    "status": "healthy",
    "version": "1.4.0",
    "timestamp": "2026-09-16T10:00:00Z",
    "features": {
    "telemetry_ingest": "operational",
    "ai_balancer": "operational",
    "ocr_vision": "operational",
    "billing_engine": "operational"
    }
    }