@@ -69,6 +69,7 @@ import { docsPath, EnvironmentParamSchema, v3BillingPath } from "~/utils/pathBui
69
69
import { PauseEnvironmentService } from "~/v3/services/pauseEnvironment.server" ;
70
70
import { PauseQueueService } from "~/v3/services/pauseQueue.server" ;
71
71
import { useCurrentPlan } from "../_app.orgs.$organizationSlug/route" ;
72
+ import { Header3 } from "~/components/primitives/Headers" ;
72
73
import { Input } from "~/components/primitives/Input" ;
73
74
import { useThrottle } from "~/hooks/useThrottle" ;
74
75
@@ -257,13 +258,30 @@ export default function Page() {
257
258
suffix = { env . paused && environment . queued > 0 ? "paused" : undefined }
258
259
animate
259
260
accessory = { < EnvironmentPauseResumeButton env = { env } /> }
260
- valueClassName = { env . paused ? "text-amber-500" : undefined }
261
+ valueClassName = { env . paused ? "text-warning" : undefined }
262
+ compactThreshold = { 1000000 }
263
+ />
264
+ < BigNumber
265
+ title = "Running"
266
+ value = { environment . running }
267
+ animate
268
+ valueClassName = {
269
+ environment . running === environment . concurrencyLimit ? "text-warning" : undefined
270
+ }
271
+ suffix = {
272
+ environment . running === environment . concurrencyLimit
273
+ ? "At concurrency limit"
274
+ : undefined
275
+ }
276
+ compactThreshold = { 1000000 }
261
277
/>
262
- < BigNumber title = "Running" value = { environment . running } animate />
263
278
< BigNumber
264
279
title = "Concurrency limit"
265
280
value = { environment . concurrencyLimit }
266
281
animate
282
+ valueClassName = {
283
+ environment . running === environment . concurrencyLimit ? "text-warning" : undefined
284
+ }
267
285
accessory = {
268
286
plan ? (
269
287
plan ?. v3Subscription ?. plan ?. limits . concurrentRuns . canExceed ? (
@@ -307,7 +325,37 @@ export default function Page() {
307
325
< TableRow >
308
326
< TableHeaderCell > Name</ TableHeaderCell >
309
327
< TableHeaderCell alignment = "right" > Queued</ TableHeaderCell >
310
- < TableHeaderCell alignment = "right" > Running</ TableHeaderCell >
328
+ < TableHeaderCell alignment = "right" > Running/limit</ TableHeaderCell >
329
+ < TableHeaderCell
330
+ alignment = "right"
331
+ tooltip = {
332
+ < div className = "max-w-xs space-y-2 p-1 text-left" >
333
+ < div className = "space-y-0.5" >
334
+ < Header3 > Environment</ Header3 >
335
+ < Paragraph
336
+ variant = "small"
337
+ className = "!text-wrap text-text-dimmed"
338
+ spacing
339
+ >
340
+ This queue is limited by your environment's concurrency limit of{ " " }
341
+ { environment . concurrencyLimit } .
342
+ </ Paragraph >
343
+ </ div >
344
+ < div className = "space-y-0.5" >
345
+ < Header3 > User</ Header3 >
346
+ < Paragraph
347
+ variant = "small"
348
+ className = "!text-wrap text-text-dimmed"
349
+ spacing
350
+ >
351
+ This queue is limited by a concurrency limit set in your code.
352
+ </ Paragraph >
353
+ </ div >
354
+ </ div >
355
+ }
356
+ >
357
+ Limited by
358
+ </ TableHeaderCell >
311
359
< TableHeaderCell
312
360
alignment = "right"
313
361
tooltip = {
@@ -334,88 +382,110 @@ export default function Page() {
334
382
>
335
383
Release on waitpoint
336
384
</ TableHeaderCell >
337
- < TableHeaderCell alignment = "right" > Concurrency limit</ TableHeaderCell >
338
385
< TableHeaderCell className = "w-[1%] pl-24" >
339
386
< span className = "sr-only" > Pause/resume</ span >
340
387
</ TableHeaderCell >
341
388
</ TableRow >
342
389
</ TableHeader >
343
390
< TableBody >
344
391
{ queues . length > 0 ? (
345
- queues . map ( ( queue ) => (
346
- < TableRow key = { queue . name } >
347
- < TableCell >
348
- < span className = "flex items-center gap-2" >
349
- { queue . type === "task" ? (
350
- < SimpleTooltip
351
- button = {
352
- < TaskIconSmall
353
- className = { cn (
354
- "size-[1.125rem] text-blue-500" ,
355
- queue . paused && "opacity-50"
356
- ) }
357
- />
358
- }
359
- content = { `This queue was automatically created from your "${ queue . name } " task` }
360
- />
361
- ) : (
362
- < SimpleTooltip
363
- button = {
364
- < RectangleStackIcon
365
- className = { cn (
366
- "size-[1.125rem] text-purple-500" ,
367
- queue . paused && "opacity-50"
368
- ) }
369
- />
370
- }
371
- content = { `This is a custom queue you added in your code.` }
372
- />
373
- ) }
374
- < span className = { queue . paused ? "opacity-50" : undefined } >
375
- { queue . name }
392
+ queues . map ( ( queue ) => {
393
+ const limit = queue . concurrencyLimit ?? environment . concurrencyLimit ;
394
+ const isAtLimit = queue . running === limit ;
395
+ return (
396
+ < TableRow key = { queue . name } >
397
+ < TableCell >
398
+ < span className = "flex items-center gap-2" >
399
+ { queue . type === "task" ? (
400
+ < SimpleTooltip
401
+ button = {
402
+ < TaskIconSmall
403
+ className = { cn (
404
+ "size-[1.125rem] text-blue-500" ,
405
+ queue . paused && "opacity-50"
406
+ ) }
407
+ />
408
+ }
409
+ content = { `This queue was automatically created from your "${ queue . name } " task` }
410
+ />
411
+ ) : (
412
+ < SimpleTooltip
413
+ button = {
414
+ < RectangleStackIcon
415
+ className = { cn (
416
+ "size-[1.125rem] text-purple-500" ,
417
+ queue . paused && "opacity-50"
418
+ ) }
419
+ />
420
+ }
421
+ content = { `This is a custom queue you added in your code.` }
422
+ />
423
+ ) }
424
+ < span className = { queue . paused ? "opacity-50" : undefined } >
425
+ { queue . name }
426
+ </ span >
427
+ { queue . paused ? (
428
+ < Badge variant = "extra-small" className = "text-warning" >
429
+ Paused
430
+ </ Badge >
431
+ ) : null }
432
+ { isAtLimit ? (
433
+ < Badge variant = "extra-small" className = "text-warning" >
434
+ At concurrency limit
435
+ </ Badge >
436
+ ) : null }
376
437
</ span >
377
- { queue . paused ? (
378
- < Badge variant = "extra-small" className = "text-warning" >
379
- Paused
380
- </ Badge >
381
- ) : null }
382
- </ span >
383
- </ TableCell >
384
- < TableCell
385
- alignment = "right"
386
- className = { queue . paused ? "opacity-50" : undefined }
387
- >
388
- { queue . queued }
389
- </ TableCell >
390
- < TableCell
391
- alignment = "right"
392
- className = { queue . paused ? "opacity-50" : undefined }
393
- >
394
- { queue . running }
395
- </ TableCell >
396
- < TableCell
397
- alignment = "right"
398
- className = { queue . paused ? "opacity-50" : undefined }
399
- >
400
- { queue . releaseConcurrencyOnWaitpoint ? "Yes" : "No" }
401
- </ TableCell >
402
- < TableCell
403
- alignment = "right"
404
- className = { queue . paused ? "opacity-50" : undefined }
405
- >
406
- { queue . concurrencyLimit ?? (
407
- < span className = "text-text-dimmed" >
408
- Max ({ environment . concurrencyLimit } )
438
+ </ TableCell >
439
+ < TableCell
440
+ alignment = "right"
441
+ className = { queue . paused ? "opacity-50" : undefined }
442
+ >
443
+ { queue . queued }
444
+ </ TableCell >
445
+ < TableCell
446
+ alignment = "right"
447
+ className = { cn (
448
+ queue . paused ? "tabular-nums opacity-50" : undefined ,
449
+ isAtLimit && "text-warning"
450
+ ) }
451
+ >
452
+ { queue . running } /
453
+ < span
454
+ className = { cn (
455
+ "tabular-nums text-text-dimmed" ,
456
+ isAtLimit && "text-warning"
457
+ ) }
458
+ >
459
+ { limit }
409
460
</ span >
410
- ) }
411
- </ TableCell >
412
- < TableCellMenu
413
- isSticky
414
- visibleButtons = { queue . paused && < QueuePauseResumeButton queue = { queue } /> }
415
- hiddenButtons = { ! queue . paused && < QueuePauseResumeButton queue = { queue } /> }
416
- />
417
- </ TableRow >
418
- ) )
461
+ </ TableCell >
462
+ < TableCell
463
+ alignment = "right"
464
+ className = { cn (
465
+ queue . paused ? "opacity-50" : undefined ,
466
+ isAtLimit && "text-warning"
467
+ ) }
468
+ >
469
+ { queue . concurrencyLimit ? "User" : "Environment" }
470
+ </ TableCell >
471
+ < TableCell
472
+ alignment = "right"
473
+ className = { queue . paused ? "opacity-50" : undefined }
474
+ >
475
+ { queue . releaseConcurrencyOnWaitpoint ? "Yes" : "No" }
476
+ </ TableCell >
477
+ < TableCellMenu
478
+ isSticky
479
+ visibleButtons = {
480
+ queue . paused && < QueuePauseResumeButton queue = { queue } />
481
+ }
482
+ hiddenButtons = {
483
+ ! queue . paused && < QueuePauseResumeButton queue = { queue } />
484
+ }
485
+ />
486
+ </ TableRow >
487
+ ) ;
488
+ } )
419
489
) : (
420
490
< TableRow >
421
491
< TableCell colSpan = { 6 } >
@@ -503,7 +573,7 @@ function EnvironmentPauseResumeButton({
503
573
type = "button"
504
574
variant = "secondary/small"
505
575
LeadingIcon = { env . paused ? PlayIcon : PauseIcon }
506
- leadingIconClassName = { env . paused ? "text-success" : "text-amber-500 " }
576
+ leadingIconClassName = { env . paused ? "text-success" : "text-warning " }
507
577
>
508
578
{ env . paused ? "Resume..." : "Pause environment..." }
509
579
</ Button >
@@ -512,8 +582,8 @@ function EnvironmentPauseResumeButton({
512
582
</ TooltipTrigger >
513
583
< TooltipContent className = { "text-xs" } >
514
584
{ env . paused
515
- ? `Resume processing runs in ${ environmentFullTitle ( env ) } . `
516
- : `Pause processing runs in ${ environmentFullTitle ( env ) } . ` }
585
+ ? `Resume processing runs in ${ environmentFullTitle ( env ) } `
586
+ : `Pause processing runs in ${ environmentFullTitle ( env ) } ` }
517
587
</ TooltipContent >
518
588
</ Tooltip >
519
589
</ TooltipProvider >
@@ -582,7 +652,7 @@ function QueuePauseResumeButton({
582
652
type = "button"
583
653
variant = "tertiary/small"
584
654
LeadingIcon = { queue . paused ? PlayIcon : PauseIcon }
585
- leadingIconClassName = { queue . paused ? "text-success" : "text-amber-500 " }
655
+ leadingIconClassName = { queue . paused ? "text-success" : "text-warning " }
586
656
>
587
657
{ queue . paused ? "Resume..." : "Pause..." }
588
658
</ Button >
@@ -703,7 +773,7 @@ export function QueueFilters() {
703
773
const search = searchParams . get ( "query" ) ?? "" ;
704
774
705
775
return (
706
- < div className = "flex w-full px-3 pb-3 " >
776
+ < div className = "flex w-full border-t border-grid-dimmed px-1.5 py-1.5 " >
707
777
< Input
708
778
name = "search"
709
779
placeholder = "Search queue name"
0 commit comments