Skip to content

[FEATURE] Implement GTFS sync cron job using @nestjs/schedule #222

Description

@BreakableHoodie

Summary

Implement an automated hourly cron job to keep the GTFS database in sync with the latest Metrolinx feed. Currently downloadAndImportToDatabase() must be triggered manually via POST /gtfs/import.

Implementation

Install @nestjs/schedule and add a scheduled task to GtfsService:

npm install @nestjs/schedule --workspace=backend
import { Cron, CronExpression } from '@nestjs/schedule';

// In GtfsService:
@Cron(CronExpression.EVERY_HOUR)
async syncGtfs() {
  this.logger.log('Running scheduled GTFS sync...');
  await this.downloadAndImportToDatabase();
}

Register ScheduleModule.forRoot() in AppModule.

Why this is safe to run frequently

GtfsService already uses If-None-Match / If-Modified-Since conditional HTTP headers. If Metrolinx hasn't updated the feed since the last check, the server returns 304 Not Modified and the import is skipped immediately — no database work, minimal network cost. Hourly polling is cheap.

Why not login-triggered

Triggering on login has two problems:

  1. Latency — the user waits for a potential GTFS download on sign-in
  2. Stampede — multiple simultaneous logins could queue up against the isDownloading guard, blocking sign-in responses

The cron approach avoids both. Metrolinx typically updates the feed overnight, so an hourly cron provides same-day freshness in practice.

Acceptance criteria

  • ScheduleModule registered in AppModule
  • Cron fires hourly and calls downloadAndImportToDatabase()
  • Cron is skipped gracefully if a manual import is already in progress (isDownloading guard)
  • Logs on each run (skipped, updated, or errored)

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions