Speeds up and de-flakes the unit-test suite: testcontainers booted once per vitest worker (per-test isolation kept only where a test runs background redis work that outlives it), a duration-weighted shard sequencer so each shard does roughly equal work, the slowest suites split, two genuine flakes fixed (`streamBatchItems` shared-redis leak; run-engine waits that relied on fixed sleeps), and transient DockerHub pulls retried. **Timings (CI, per-shard wall):** worst unit-test shard ~771s → ~294s; packages/webapp shards ~250-270s, most internal ~190-240s. All 25 shards green. A shard breaks down as ~70s fixed setup (install / image-pull / generate) + ~70s cold `^build` + the actual container tests. So the remaining cost is mostly the tests themselves plus that fixed setup. **Next (separate, timings):** - **typecheck (~6m24s)** — the slowest check overall; bound by full-graph `tsc`, not the TS version (a TS6 branch is still ~6m17s). The real lever is **tsgo** (the Go compiler). - Possible later: turbo CI caching could trim the ~70s cold build on *warm* runs, but it's conditional (cold runs rebuild anyway) and doesn't touch setup or test time — secondary. `cli-v3` e2e and `sdk-compat` are path-gated (don't run on test-infra changes) and already comfortably fast.
@internal/schedule-engine
The @internal/schedule-engine package encapsulates all scheduling logic for Trigger.dev, providing a clean API boundary for managing scheduled tasks and their execution.
Architecture
The ScheduleEngine follows the same pattern as the RunEngine, providing:
- Centralized Schedule Management: All schedule-related operations go through the ScheduleEngine
- Redis Worker Integration: Built-in Redis-based distributed task scheduling
- Distributed Execution: Prevents thundering herd issues by distributing executions across time windows
- Comprehensive Testing: Built-in utilities for testing schedule behavior
Key Components
ScheduleEngine Class
The main interface for all schedule operations:
import { ScheduleEngine } from "@internal/schedule-engine";
const engine = new ScheduleEngine({
prisma,
redis: {
/* Redis configuration */
},
worker: {
/* Worker configuration */
},
distributionWindow: { seconds: 30 }, // Optional: default 30s
});
// Register next schedule instance
await engine.registerNextTaskScheduleInstance({ instanceId });
// Upsert a schedule
await engine.upsertTaskSchedule({
projectId,
schedule: {
taskIdentifier: "my-task",
cron: "0 */5 * * *",
timezone: "UTC",
environments: ["env-1", "env-2"],
},
});
Distributed Scheduling
The engine includes built-in distributed scheduling to prevent all scheduled tasks from executing at exactly the same moment:
import { calculateDistributedExecutionTime } from "@internal/schedule-engine";
const exactTime = new Date("2024-01-01T12:00:00Z");
const distributedTime = calculateDistributedExecutionTime(exactTime, 30); // 30-second window
Schedule Calculation
High-performance CRON schedule calculation with optimization for old timestamps:
import {
calculateNextScheduledTimestampFromNow,
nextScheduledTimestamps,
} from "@internal/schedule-engine";
const nextRun = calculateNextScheduledTimestampFromNow("0 */5 * * *", "UTC");
const upcoming = nextScheduledTimestamps("0 */5 * * *", "UTC", nextRun, 5);
Integration with Webapp
The ScheduleEngine should be the API boundary between the webapp and schedule logic. Services in the webapp should call into the ScheduleEngine rather than implementing schedule logic directly.
Migration Path
Currently, the webapp uses individual services like:
RegisterNextTaskScheduleInstanceServiceTriggerScheduledTaskService- Schedule calculation utilities
These should be replaced with ScheduleEngine method calls:
// Old approach
const service = new RegisterNextTaskScheduleInstanceService(tx);
await service.call(instanceId);
// New approach
await scheduleEngine.registerNextTaskScheduleInstance({ instanceId });
Configuration
The ScheduleEngine expects these configuration options:
prisma: PrismaClient instanceredis: Redis connection configurationworker: Worker configuration (concurrency, polling intervals)distributionWindow: Optional time window for distributed executiontracer: Optional OpenTelemetry tracermeter: Optional OpenTelemetry meter
Testing
The package includes comprehensive test utilities and examples. See the test directory for usage examples.