Queues.utils.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. import { Column } from 'react-data-grid'
  2. import { cn } from 'ui'
  3. import z from 'zod'
  4. import {
  5. QueueCreatedAtCell,
  6. QueueNameCell,
  7. QueueRLSCell,
  8. QueueSizeCell,
  9. QueueTypeCell,
  10. QueueWithMetrics,
  11. } from './QueueCells'
  12. import { PostgresQueue } from '@/data/database-queues/database-queues-query'
  13. export const formatQueueColumns = (): Column<QueueWithMetrics>[] => {
  14. return [
  15. {
  16. key: 'queue_name',
  17. name: 'Name',
  18. resizable: true,
  19. minWidth: 200,
  20. headerCellClass: undefined,
  21. renderHeaderCell: () => {
  22. return (
  23. <div className={cn('flex items-center justify-between font-normal text-xs w-full ml-8')}>
  24. <p className="text-foreground!">Name</p>
  25. </div>
  26. )
  27. },
  28. renderCell: (props) => {
  29. return <QueueNameCell queue={props.row} />
  30. },
  31. },
  32. {
  33. key: 'type',
  34. name: 'Type',
  35. resizable: true,
  36. minWidth: 120,
  37. headerCellClass: undefined,
  38. renderHeaderCell: () => {
  39. return (
  40. <div className={cn('flex items-center justify-between font-normal text-xs w-full')}>
  41. <p className="text-foreground!">Type</p>
  42. </div>
  43. )
  44. },
  45. renderCell: (props) => {
  46. return <QueueTypeCell queue={props.row} />
  47. },
  48. },
  49. {
  50. key: 'rls_enabled',
  51. name: 'RLS enabled',
  52. resizable: true,
  53. minWidth: 120,
  54. headerCellClass: undefined,
  55. renderHeaderCell: () => {
  56. return (
  57. <div className={cn('flex items-center justify-between font-normal text-xs w-full')}>
  58. <p className="text-foreground!">RLS enabled</p>
  59. </div>
  60. )
  61. },
  62. renderCell: (props) => {
  63. return <QueueRLSCell queue={props.row} />
  64. },
  65. },
  66. {
  67. key: 'created_at',
  68. name: 'Created at',
  69. resizable: true,
  70. minWidth: 180,
  71. headerCellClass: undefined,
  72. renderHeaderCell: () => {
  73. return (
  74. <div className={cn('flex items-center justify-between font-normal text-xs w-full')}>
  75. <p className="text-foreground!">Created at</p>
  76. </div>
  77. )
  78. },
  79. renderCell: (props) => {
  80. return <QueueCreatedAtCell queue={props.row} />
  81. },
  82. },
  83. {
  84. key: 'queue_size',
  85. name: 'Size',
  86. resizable: true,
  87. minWidth: 120,
  88. headerCellClass: undefined,
  89. renderHeaderCell: () => {
  90. return (
  91. <div className={cn('flex items-center justify-between font-normal text-xs w-full')}>
  92. <p className="text-foreground!">Size</p>
  93. </div>
  94. )
  95. },
  96. renderCell: (props) => {
  97. return <QueueSizeCell queue={props.row} />
  98. },
  99. },
  100. ]
  101. }
  102. export const prepareQueuesForDataGrid = (queues: PostgresQueue[]): QueueWithMetrics[] => {
  103. return queues.map((queue) => ({
  104. ...queue,
  105. id: queue.queue_name, // Use queue_name as unique id
  106. }))
  107. }
  108. // pgmq stores queue names as-provided in pgmq.meta and lowercases them only when
  109. // building the underlying q_/a_ relations, so uppercase queue names are fine —
  110. // the user-facing name is preserved and table-name lookups go through
  111. // pgmqQueueTable / pgmqArchiveTable which lowercase to match pgmq's behavior.
  112. export const QueueNameSchema = z
  113. .string()
  114. .trim()
  115. .min(1, 'Please provide a name for your queue')
  116. .max(47, "The name can't be longer than 47 characters")
  117. .regex(
  118. /^[a-zA-Z0-9_-]+$/,
  119. 'Name must contain only alphanumeric characters, underscores, and hyphens'
  120. )
  121. export const isQueueNameValid = (queueName: string) => {
  122. return QueueNameSchema.safeParse(queueName).success
  123. }
  124. // pgmq.format_table_name() lowercases its input, so the actual relations in the
  125. // pgmq schema are always q_/a_ followed by the lowercased queue name — even when
  126. // pgmq.meta stores the original casing. Use these helpers anywhere a queue name
  127. // is mapped to a relname.
  128. export const pgmqQueueTable = (queueName: string) => `q_${queueName.toLowerCase()}`
  129. export const pgmqArchiveTable = (queueName: string) => `a_${queueName.toLowerCase()}`