Skip to content

Feat/sqs batch operations and queue management (#72)#96

Closed
alancoosta wants to merge 7 commits intoDaviReisVieira:mainfrom
alancoosta:feat/sqs-batch-operations-and-queue-management
Closed

Feat/sqs batch operations and queue management (#72)#96
alancoosta wants to merge 7 commits intoDaviReisVieira:mainfrom
alancoosta:feat/sqs-batch-operations-and-queue-management

Conversation

@alancoosta
Copy link
Copy Markdown
Contributor

Summary

Implements full SQS queue management in StackPort: create/delete queues (Standard & FIFO), batch message operations (send/delete), queue attributes editing, dead-letter queue (DLQ) auto-creation, and a favorites system for saving message templates. Compatible with LocalStack, MiniStack, Moto, or any AWS-compatible endpoint.

Closes #72


What changed

Backend (backend/routes/sqs.py)

Method Path Purpose
GET /api/sqs/queues List all queues with metadata
POST /api/sqs/queues Create queue (Standard/FIFO, DLQ, encryption, tags)
GET /api/sqs/queues/{queue_name} Get queue detail
DELETE /api/sqs/queues/{queue_name} Delete queue
PUT /api/sqs/queues/{queue_name}/attributes Update queue attributes
PUT /api/sqs/queues/{queue_name}/redrive-policy Set DLQ redrive policy
POST /api/sqs/queues/{queue_name}/purge Purge all messages
POST /api/sqs/queues/{queue_name}/messages Send single message
POST /api/sqs/queues/{queue_name}/messages/batch Send up to 10 messages
GET /api/sqs/queues/{queue_name}/messages Receive up to 10 messages
DELETE /api/sqs/queues/{queue_name}/messages Delete single message
DELETE /api/sqs/queues/{queue_name}/messages/batch Batch delete messages

Key features:

  • FIFO auto-append: Queue names for FIFO queues automatically get .fifo suffix appended
  • DLQ auto-creation: When creating a queue with DLQ enabled, a DLQ named {queueName}-dlq (or .fifo for FIFO queues) is automatically created
  • Redrive policy: Set or update DLQ configuration on existing queues
  • FIFO support: Content-based deduplication, message group ID, deduplication ID
  • Encryption: SQS-managed SSE or custom KMS key
  • Tagging: Create/update tags on queue creation
  • Batch operations: Send/delete up to 10 messages at once

Frontend (ui/src/components/service-views/SQSBrowser.tsx)

All components were created inside this component; we could move to another folder's components as soon.

Queue Management:

  • Create queue sheet with basic/advanced tabs (type, visibility timeout, retention, DLQ, encryption, tags)
  • FIFO queues auto-get .fifo suffix (user can still type it manually)
  • Edit settings sheet for queue attributes and DLQ
  • Delete queue with name-typed confirmation
  • Purge queue with name-typed confirmation
  • Queue list with pagination, search, favorites section (starred queues)

Message Operations:

  • Send single message with delay, FIFO attributes
  • Batch send up to 10 messages (flexible JSON format — auto-generates entry IDs)
  • Peek messages (visibility timeout = 0, non-consuming)
  • View message details (body, attributes, system attributes)
  • Delete single message
  • Bulk delete selected messages (checkboxes + "Delete Selected")
  • Checkbox selection with "select all" toggle

Favorites System:

  • Save message as favorite: Click star → pre-filled sheet with formatted JSON and default name
  • Create favorite from scratch: Single or batch message templates
  • View favorite: Read, edit name/body, copy to clipboard
  • Resend to queue: Send favorite to current queue (handles single & batch)
  • Delete favorite: Name confirmation required
  • LocalStorage persistence: Favorites stored in browser

UI Components:

  • Tabs: Messages, Favorites, Configuration, Tags
  • Message table with selection, preview, actions
  • Queue depth badges (Empty/Low/Medium/High)
  • Queue type badges (Standard/FIFO)
  • DLQ indicator badge on queue cards
  • Toast notifications (Sonner)
  • Export dropdown for queue list

Hooks (ui/src/hooks/useSQSFavoriteMessages.ts)

  • Custom hook for favorite messages in localStorage
  • CRUD: addFavorite, addFavorites, removeFavorite, updateFavorite
  • Auto-generates IDs and timestamps

API (ui/src/lib/api.ts)

New SQS functions:

  • fetchSQSQueues, fetchSQSQueueDetail
  • createSQSQueue, deleteSQSQueue
  • sendSQSMessage, sendSQSMessagesBatch
  • receiveSQSMessages, deleteSQSMessage, deleteSQSMessagesBatch
  • purgeSQSQueue
  • updateSQSQueueAttributes, updateSQSRedrivePolicy

Types (ui/src/lib/types.ts)

New interfaces:

  • SQSQueue, SQSQueueDetail
  • SQSMessage, SQSSendMessageRequest
  • SQSCreateQueueRequest, SQSCreateQueueResponse
  • SQSBatchSendRequest, SQSBatchSendResponse
  • SQSUpdateAttributesRequest
  • SQSFavoriteMessage

Tests (tests/test_sqs_routes.py)

Comprehensive backend tests (34 tests):

  • List queues, create queue (Standard/FIFO), get detail, delete
  • FIFO with content-based deduplication
  • Queue attributes (visibility timeout, retention, delay, max size, receive wait time)
  • Redrive policy (DLQ configuration)
  • Encryption (SQS-managed SSE, custom KMS)
  • Tags on queue creation
  • FIFO auto-append: Verifies .fifo suffix is added automatically
  • Send/receive/delete single message
  • Batch send/delete (up to 10, validation, partial failures)
  • Purge queue
  • Update queue attributes and redrive policy
  • Error handling (404s, validation)

Build

  • ui/dist/ updated with bundled assets
  • Makefile added for convenience (install, dev, build, lint)

Out of scope (per issue)

  • Queue policies (IAM-level)
  • Server-side encryption configuration (basic SSE toggle exists)
  • Cross-account access
  • Cost allocation tags (tags are implemented, cost allocation is not)
  • Message visibility timeout extension
  • Long polling beyond receive wait time
  • CloudWatch metrics/alarms

How to verify

  1. Run your emulator (e.g. ministack or localstack on :4566)
  2. Run StackPort: STACKPORT_PORT=8080 python -m backend.main
  3. Resources → SQS:
    • Create FIFO queue named orders → verify it becomes orders.fifo
    • Enable DLQ → verify {name}-dlq.fifo is auto-created
    • Edit queue settings and DLQ
    • Send single and batch messages
    • Peek/receive messages
    • Select and delete multiple messages
    • Click star to save message as favorite (verify JSON formatting)
    • View Favorites tab, resend to queue
    • Create/edit/delete favorites
    • Purge and delete queues
  4. Run pytest tests/test_sqs_routes.py -v (34 tests should pass)

Technical notes

  • FIFO auto-append: Backend appends .fifo if queue type is FIFO and name doesn't already end with it
  • Batch limits: Maximum 10 messages per batch send/delete (SQS API limit)
  • DLQ naming: Auto-created DLQ uses {parentQueueName}-dlq (or -dlq.fifo for FIFO queues)
  • Favorites storage: Browser localStorage under sqs-favorite-messages key
  • Queue favorites: Separate localStorage (sqs-favorites) for pinning queues to top of list
  • Batch send format: Flexible JSON — user's objects are stringified as message bodies, entry IDs are auto-generated

Related commits

  • 576d71c - Initial implementation: create/delete/update queues, batch operations, favorites
  • 8251972 - DLQ auto-creation and favorites improvements
  • 053aceb - FIFO auto-append fix and this README

Thanks for reviewing — happy to tweak wording or split changes if that helps review.

Copy link
Copy Markdown
Owner

@DaviReisVieira DaviReisVieira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @alancoosta, thanks for this awesome PR! 🎉 This is a massive contribution — full SQS queue management, batch operations, DLQ auto-creation, favorites system, and 34 backend tests. Really impressive scope and quality overall.

I did a thorough review and wanted to share some findings. Here's the breakdown:


Bugs

1. 🔴 CRITICAL — DLQ auto-creation gets empty ARN (backend/routes/sqs.py:189)

The SQS create_queue API only returns QueueUrl, never QueueArn. This means dlq_arn will always be "", producing a broken redrive policy with deadLetterTargetArn: "".

# Current (broken):
dlq_arn = dlq_response.get("QueueArn", "")

# Fix — fetch ARN after creation (like the "DLQ already exists" branch does):
dlq_url = dlq_response["QueueUrl"]
dlq_attrs = client.get_queue_attributes(QueueUrl=dlq_url, AttributeNames=["QueueArn"])
dlq_arn = dlq_attrs["Attributes"]["QueueArn"]

The same issue exists on line 220 for the main queue's ARN (queue_arn = response.get("QueueArn", "")).

2. 🟡 Redundant get_queue_url call (backend/routes/sqs.py:170-172)

Two consecutive identical calls — the first result is discarded:

client.get_queue_url(QueueName=dlq_queue_name)         # line 170 — result thrown away
dlq_url_response = client.get_queue_url(QueueName=dlq_queue_name)  # line 172 — same call

3. 🟡 window.prompt() / window.confirm() mixed with Sheet confirmations (SQSBrowser.tsx:2133, 1631)

The PR adds great Sheet-based confirmation dialogs for purge/delete queue/delete favorite, but then uses window.prompt("Type DELETE...") for batch message deletion and window.confirm() for single message deletion. This breaks the dark theme UX and is inconsistent. Both should use Sheet-based confirmations matching the other patterns in the PR.

4. 🟡 EditSettingsSheet always sends redrive policy update (SQSBrowser.tsx:726-734)

When dlqEnabled is false, it calls updateSQSRedrivePolicy(queue.name, null) which sends {"deadLetterTargetArn": null, "maxReceiveCount": null}. The backend then raises 400 because deadLetterTargetArn is empty (line 690-691). This causes a toast error every time you save settings on a queue without a DLQ. Fix: only call updateSQSRedrivePolicy when the DLQ state actually changed.


Code Quality

5. No Pydantic models for request bodies

All new endpoints use body: dict[str, Any] with manual validation. Other routes (dynamodb.py, s3.py) use Pydantic BaseModel classes — which gives automatic validation, better /api/docs output, and type safety. Not a blocker but a deviation from project conventions.

6. SQSBrowser.tsx is 3,025 lines

Nearly 3x the largest existing browser (S3Browser.tsx at 1,163 lines). I see the PR description acknowledges this. The 10+ sub-components (CreateQueueSheet, SendMessageSheet, EditSettingsSheet, etc.) would benefit from extraction to separate files. Could be a follow-up.

7. Duplicated queue card rendering

The queue card JSX is nearly identical between the favorites section (lines 2871-2923) and the all-queues section (lines 2934-2997). A shared QueueCard component would eliminate the duplication.

8. Redundant .filter() on already-filtered data (SQSBrowser.tsx:2937)

{paginatedQueues
  .filter((queue) => !favorites.has(queue.name))  // redundant — paginatedQueues comes from nonFavoriteQueues
  .map((queue) => { ... })}

paginatedQueues is sliced from nonFavoriteQueues which already excludes favorites.


Missing from Issue #72

  • Batch send FIFO params: The batch send sheet doesn't pass messageGroupId or messageDeduplicationId through to the backend. Only id and messageBody are extracted (line 964-975). The issue calls for "per-message delay and attributes."
  • Test for DLQ auto-creation path: This is why the ARN bug wasn't caught. A test with dlqEnabled=true would verify the full flow.

Files to Reconsider

  • SQS_FEATURES_README.md — Duplicates the PR description content. The PR description is the right place for this; the file shouldn't go into the repo.
  • Makefile — Introduces a new build system not documented in CLAUDE.md, duplicating existing instructions. If desired, it should be a separate PR.

What Looks Great

  • Backend architecture follows the existing patterns perfectly (router, get_client, error handling)
  • 34 tests with good coverage of happy paths, validation, 404s, batch limits, partial failures
  • TypeScript types are clean and well-structured
  • Favorites system is a nice UX addition beyond the issue scope
  • DLQ auto-creation is a thoughtful convenience feature
  • Queue favorites (pinning) is a nice touch
  • Export dropdown integration
  • All ESLint/TypeScript checks pass clean (no new errors)

Priority Summary

Priority Item
P0 Fix DLQ ARN bug (lines 189, 220)
P1 Fix redundant get_queue_url (line 170)
P1 Fix EditSettingsSheet null redrive policy causing 400
P1 Replace window.prompt/window.confirm with Sheets
P1 Add test for DLQ auto-creation
P2 Remove SQS_FEATURES_README.md and Makefile
P2 Pass FIFO params through batch send
P2 Remove redundant .filter()
P3 Extract sub-components (can be follow-up)
P3 Deduplicate queue card JSX
P3 Consider Pydantic models (can be follow-up)

This is really great work — the feature is comprehensive and well thought out. If you'd like any help tackling these fixes, I'm happy to jump in and help get this across the finish line. Or if you'd prefer to handle it yourself, totally works too — just let me know! 🚀

@alancoosta
Copy link
Copy Markdown
Contributor Author

alancoosta commented Apr 24, 2026

@DaviReisVieira Thank you!!
I would really appreciate it if you could continue this integration.
And you can adjust the things like you want.

One more suggestion for this PR is to create an option "Brach Create Queues"
It's very useful for local development.
Example:
image

@DaviReisVieira
Copy link
Copy Markdown
Owner

Closing this cross-fork PR — reopening from the main repo branch to fix CI targeting the wrong merge ref. All original work preserved, plus additional improvements (schema extraction, UI polish, multi-endpoint fixes).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SQS — Batch operations and queue management

2 participants