import {useEffect, useState} from 'react' import {Loader2, Send, Trash2} from 'lucide-react' import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query' import {deleteSqsMessage, listCloudResources, purgeSqsQueue, receiveSqsMessages, sendSqsMessage, startSqsMoveTask, updateCloudResource} from '@/api/cloudProxyClient' import type {CloudResource, SqsMessageAttribute} from '@/types/resource' export function SqsQueuePanel({resource, runtimeReachable}: {resource?: CloudResource; runtimeReachable: boolean}) { const [body, setBody] = useState('') const [attributes, setAttributes] = useState('{}') const [groupId, setGroupId] = useState('') const [deduplicationId, setDeduplicationId] = useState('') const [messages, setMessages] = useState>>([]) const [purgeConfirm, setPurgeConfirm] = useState(false) const [dlqArn, setDlqArn] = useState('') const [maxReceiveCount, setMaxReceiveCount] = useState('2') const [moveDestination, setMoveDestination] = useState('') const queryClient = useQueryClient() const queuesQuery = useQuery({queryKey: ['cloud-resources', 'aws', 'messaging'], queryFn: ({signal}) => listCloudResources('aws', 'messaging', undefined, signal), enabled: Boolean(resource) && runtimeReachable}) const isQueue = resource?.service === 'messaging' && (resource.type === 'queue' || resource.type === 'fifo-queue') const isFifo = resource?.type === 'fifo-queue' useEffect(() => { setBody(''); setAttributes('{}'); setGroupId(''); setDeduplicationId(''); setMessages([]); setPurgeConfirm(false); setDlqArn(''); setMoveDestination('') }, [resource?.id]) const send = useMutation({mutationFn: () => sendSqsMessage('aws', resource!.id, {messageBody: body, messageAttributes: parseAttributes(attributes), ...(isFifo ? {messageGroupId: groupId, ...(deduplicationId ? {messageDeduplicationId: deduplicationId} : {})} : {})}), onSuccess: () => { setBody(''); void queryClient.invalidateQueries({queryKey: ['cloud-resources', 'aws', 'messaging']})}}) const receive = useMutation({mutationFn: () => receiveSqsMessages('aws', resource!.id, 10), onSuccess: (received) => { setMessages(received); void queryClient.invalidateQueries({queryKey: ['cloud-resources', 'aws', 'messaging']})}}) const remove = useMutation({mutationFn: (message: Awaited>[number]) => deleteSqsMessage('aws', resource!.id, message.receiptHandle), onSuccess: (_, message) => { setMessages((current) => current.filter((item) => item.receiptHandle !== message.receiptHandle)); void queryClient.invalidateQueries({queryKey: ['cloud-resources', 'aws', 'messaging']})}}) const purge = useMutation({mutationFn: () => purgeSqsQueue('aws', resource!.id), onSuccess: () => { setMessages([]); setPurgeConfirm(false); void queryClient.invalidateQueries({queryKey: ['cloud-resources', 'aws', 'messaging']})}}) const configureDlq = useMutation({mutationFn: () => updateCloudResource('aws', 'messaging', resource!.id, {redrivePolicy: {deadLetterTargetArn: dlqArn, maxReceiveCount}}), onSuccess: () => queryClient.invalidateQueries({queryKey: ['cloud-resources', 'aws', 'messaging']})}) const move = useMutation({mutationFn: () => startSqsMoveTask('aws', resource!.id, moveDestination || undefined)}) if (!isQueue) return null const queues = (queuesQuery.data ?? []).filter((queue) => queue.id !== resource.id && queue.type === resource.type && typeof queue.metadata.arn === 'string') const error = send.error ?? receive.error ?? remove.error ?? purge.error ?? configureDlq.error ?? move.error return

SQS Messages

Send and receive

Polling receives messages and starts their configured visibility timeout. Messages are deleted only when you explicitly delete them.

{ event.preventDefault(); if (body && (!isFifo || groupId)) send.mutate() }}>