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:
- Latency — the user waits for a potential GTFS download on sign-in
- 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
Related
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 viaPOST /gtfs/import.Implementation
Install
@nestjs/scheduleand add a scheduled task toGtfsService:Register
ScheduleModule.forRoot()inAppModule.Why this is safe to run frequently
GtfsServicealready usesIf-None-Match/If-Modified-Sinceconditional HTTP headers. If Metrolinx hasn't updated the feed since the last check, the server returns304 Not Modifiedand 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:
isDownloadingguard, blocking sign-in responsesThe cron approach avoids both. Metrolinx typically updates the feed overnight, so an hourly cron provides same-day freshness in practice.
Acceptance criteria
ScheduleModuleregistered inAppModuledownloadAndImportToDatabase()isDownloadingguard)Related