@@ -9,14 +9,19 @@ import { BackgroundWorkerId } from "@trigger.dev/core/v3/isomorphic";
99import type { BackgroundWorker , TaskQueue , TaskQueueType } from "@trigger.dev/database" ;
1010import cronstrue from "cronstrue" ;
1111import { Prisma , PrismaClientOrTransaction } from "~/db.server" ;
12+ import { env } from "~/env.server" ;
1213import { sanitizeQueueName } from "~/models/taskQueue.server" ;
1314import { AuthenticatedEnvironment } from "~/services/apiAuth.server" ;
1415import { logger } from "~/services/logger.server" ;
1516import { generateFriendlyId } from "../friendlyIdentifiers" ;
1617import {
18+ parseDurationToMs ,
1719 removeQueueConcurrencyLimits ,
20+ removeQueueRateLimitConfig ,
1821 updateEnvConcurrencyLimits ,
1922 updateQueueConcurrencyLimits ,
23+ updateQueueRateLimitConfig ,
24+ type QueueRateLimitConfig ,
2025} from "../runQueue.server" ;
2126import { calculateNextBuildVersion } from "../utils/calculateNextBuildVersion" ;
2227import { clampMaxDuration } from "../utils/maxDuration" ;
@@ -250,11 +255,12 @@ async function createWorkerTask(
250255 let queue = queues . find ( ( queue ) => queue . name === task . queue ?. name ) ;
251256
252257 if ( ! queue ) {
253- // Create a TaskQueue
258+ // Create a TaskQueue with rate limit config if provided
254259 queue = await createWorkerQueue (
255260 {
256261 name : task . queue ?. name ?? `task/${ task . id } ` ,
257262 concurrencyLimit : task . queue ?. concurrencyLimit ,
263+ rateLimit : task . queue ?. rateLimit ,
258264 } ,
259265 task . id ,
260266 task . queue ?. name ? "NAMED" : "VIRTUAL" ,
@@ -364,9 +370,28 @@ async function createWorkerQueue(
364370 ? Math . max ( Math . min ( queue . concurrencyLimit , environment . maximumConcurrencyLimit ) , 0 )
365371 : queue . concurrencyLimit ;
366372
373+ // Parse rate limit config if provided
374+ let rateLimitConfig : QueueRateLimitConfig | null = null ;
375+ if ( queue . rateLimit ) {
376+ try {
377+ rateLimitConfig = {
378+ limit : queue . rateLimit . limit ,
379+ periodMs : parseDurationToMs ( queue . rateLimit . period ) ,
380+ burst : queue . rateLimit . burst ,
381+ } ;
382+ } catch ( error ) {
383+ logger . error ( "createWorkerQueue: invalid rate limit period format" , {
384+ queueName,
385+ rateLimit : queue . rateLimit ,
386+ error,
387+ } ) ;
388+ }
389+ }
390+
367391 const taskQueue = await upsertWorkerQueueRecord (
368392 queueName ,
369393 baseConcurrencyLimit ?? null ,
394+ rateLimitConfig ,
370395 orderableName ,
371396 queueType ,
372397 worker ,
@@ -376,6 +401,7 @@ async function createWorkerQueue(
376401 const newConcurrencyLimit = taskQueue . concurrencyLimit ;
377402
378403 if ( ! taskQueue . paused ) {
404+ // Handle concurrency limit sync
379405 if ( typeof newConcurrencyLimit === "number" ) {
380406 logger . debug ( "createWorkerQueue: updating concurrency limit" , {
381407 workerId : worker . id ,
@@ -397,8 +423,36 @@ async function createWorkerQueue(
397423 } ) ;
398424 await removeQueueConcurrencyLimits ( environment , taskQueue . name ) ;
399425 }
426+
427+ // Handle rate limit config sync to Redis
428+ if ( env . TRIGGER_DISABLE_QUEUE_RATE_LIMITS === "1" ) {
429+ // Rate limiting disabled: remove any existing config from Redis
430+ // This ensures clean state when toggling the flag
431+ logger . debug ( "createWorkerQueue: rate limiting disabled by env flag, removing config" , {
432+ workerId : worker . id ,
433+ taskQueue : taskQueue . name ,
434+ orgId : environment . organizationId ,
435+ projectId : environment . projectId ,
436+ environmentId : environment . id ,
437+ } ) ;
438+ await removeQueueRateLimitConfig ( environment , taskQueue . name ) ;
439+ } else if ( rateLimitConfig ) {
440+ // Rate limiting enabled and config exists: sync to Redis
441+ logger . debug ( "createWorkerQueue: updating rate limit config" , {
442+ workerId : worker . id ,
443+ taskQueue : taskQueue . name ,
444+ orgId : environment . organizationId ,
445+ projectId : environment . projectId ,
446+ environmentId : environment . id ,
447+ rateLimitConfig,
448+ } ) ;
449+ await updateQueueRateLimitConfig ( environment , taskQueue . name , rateLimitConfig ) ;
450+ } else {
451+ // Rate limiting enabled but no config: remove any stale config
452+ await removeQueueRateLimitConfig ( environment , taskQueue . name ) ;
453+ }
400454 } else {
401- logger . debug ( "createWorkerQueue: queue is paused, not updating concurrency limit " , {
455+ logger . debug ( "createWorkerQueue: queue is paused, not updating limits " , {
402456 workerId : worker . id ,
403457 taskQueue,
404458 orgId : environment . organizationId ,
@@ -413,6 +467,7 @@ async function createWorkerQueue(
413467async function upsertWorkerQueueRecord (
414468 queueName : string ,
415469 concurrencyLimit : number | null ,
470+ rateLimitConfig : QueueRateLimitConfig | null ,
416471 orderableName : string ,
417472 queueType : TaskQueueType ,
418473 worker : BackgroundWorker ,
@@ -431,6 +486,15 @@ async function upsertWorkerQueueRecord(
431486 } ,
432487 } ) ;
433488
489+ // Serialize rate limit config for storage (or null to clear)
490+ const rateLimitData = rateLimitConfig
491+ ? {
492+ limit : rateLimitConfig . limit ,
493+ periodMs : rateLimitConfig . periodMs ,
494+ burst : rateLimitConfig . burst ,
495+ }
496+ : Prisma . JsonNull ;
497+
434498 if ( ! taskQueue ) {
435499 taskQueue = await prisma . taskQueue . create ( {
436500 data : {
@@ -439,6 +503,7 @@ async function upsertWorkerQueueRecord(
439503 name : queueName ,
440504 orderableName,
441505 concurrencyLimit,
506+ rateLimit : rateLimitData ,
442507 runtimeEnvironmentId : worker . runtimeEnvironmentId ,
443508 projectId : worker . projectId ,
444509 type : queueType ,
@@ -463,6 +528,8 @@ async function upsertWorkerQueueRecord(
463528 // If overridden, keep current limit and update base; otherwise update limit normally
464529 concurrencyLimit : hasOverride ? undefined : concurrencyLimit ,
465530 concurrencyLimitBase : hasOverride ? concurrencyLimit : undefined ,
531+ // Always update rate limit config (not overrideable for now)
532+ rateLimit : rateLimitData ,
466533 } ,
467534 } ) ;
468535 }
@@ -474,6 +541,7 @@ async function upsertWorkerQueueRecord(
474541 return await upsertWorkerQueueRecord (
475542 queueName ,
476543 concurrencyLimit ,
544+ rateLimitConfig ,
477545 orderableName ,
478546 queueType ,
479547 worker ,
0 commit comments