GH-1143 Add IGNORE QueueNotFoundStrategy option for SQS#1640
Open
BK202503 wants to merge 1 commit into
Open
Conversation
Restore the Spring Cloud AWS 2.x behavior where a missing SQS queue at listener startup did not fail the application context. In 3.x today the two strategies are FAIL (throws on missing queue, blocks startup) and CREATE (calls CreateQueue on missing, requires sqs:CreateQueue IAM and can interfere with externally-managed queue configuration); neither fits the common case where a queue may legitimately be absent in some deployments — for example an optional feature queue, or a multi-region rollout that hasn't created the queue yet. Add a third strategy, IGNORE, that logs a warning and skips starting the listener container's message source for that queue. Subsequent polls return empty so the application keeps running cleanly. Wiring: - QueueNotFoundStrategy gets a new IGNORE constant with Javadoc that cross-references the 2.x default behavior. - QueueAttributesResolver.handleException, on QueueDoesNotExistException + IGNORE, logs a warning and fails the future with a new QueueNotFoundException (subtype of QueueAttributesResolvingException so existing catch sites keep working; the dedicated subtype is what the source uses to recognize the IGNORE signal). The CREATE path is unchanged. - QueueAttributesResolver.wrapException passes QueueNotFoundException through unwrapped instead of re-wrapping in QueueAttributesResolvingException, so the source sees the typed signal rather than a generic resolver failure. - AbstractSqsMessageSource.doStart catches CompletionException with QueueNotFoundException as its cause, flips a `skipped` flag, logs a warning, and returns without setting queueAttributes/queueUrl or configuring the conversion context. - AbstractSqsMessageSource.doPollForMessages short-circuits to an empty future when `skipped`, so the polling loop is a no-op for the lifetime of the source. Tests: - QueueAttributesResolverIntegrationTests#shouldIgnoreQueueWhenStrategyIsIgnore mirrors the existing #shouldNotCreateQueue pattern against LocalStack, asserting that resolving a non-existent queue with IGNORE surfaces a QueueNotFoundException whose cause is QueueDoesNotExistException (rather than the generic QueueAttributesResolvingException that FAIL produces). - The full QueueAttributesResolverIntegrationTests class (7 tests) passes locally on LocalStack. Docs: - sqs.adoc table entry for queueNotFoundStrategy gets a sentence on the IGNORE behavior next to the existing FAIL note. The property binding for `spring.cloud.aws.sqs.queue-not-found-strategy` picks up IGNORE automatically because SqsProperties already exposes the enum directly. Closes awspring#1143. Signed-off-by: BK202503 <199436087+BK202503@users.noreply.github.com>
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1143.
What
Adds a third option to
QueueNotFoundStrategy—IGNORE— that logs a warning and skips starting the listener container's message source when its queue does not exist, so application startup is not blocked. Subsequent polls for that source return empty.This restores the default behavior of Spring Cloud AWS 2.x (
spring-cloud-starter-aws-messaging) for users that rely on it during the 2.x → 3.x migration, as flagged by several commenters on #1143.Why
Today the two strategies are:
FAIL— throws on a missing queue and blocks application startup. Wrong for deployments where the queue is legitimately optional.CREATE— callsCreateQueueon a missing queue. Requiressqs:CreateQueueIAM and can interfere with externally-managed queue configuration / cross-team queue ownership.Neither fits the case where a queue may legitimately be absent in some deployments (optional feature queues, multi-region rollout where the queue hasn't been created yet, etc.) and the listener should simply skip rather than crash the app.
@tomazfernandes wrote on the issue: "I don't have a solution in mind, but happy to take a look at a PR with a proposal." — this is that proposal.
How
The main concern from the issue was "graciously handle the error thrown by the
QueueAttributesResolverand interrupting container startup". The patch routes that through a typed signal rather than reusing the generic resolver exception:QueueNotFoundStrategygets a newIGNOREconstant with Javadoc that cross-references the 2.x default behavior.QueueAttributesResolver.handleException, onQueueDoesNotExistException+IGNORE, logs a warning and fails the future with a newQueueNotFoundException(subtype ofQueueAttributesResolvingException, so existing catch sites keep working; the dedicated subtype is what lets the source distinguish "ignore this queue" from a generic resolver failure). TheCREATEpath is unchanged.QueueAttributesResolver.wrapExceptionpassesQueueNotFoundExceptionthrough unwrapped instead of re-wrapping inQueueAttributesResolvingException, so the source sees the typed signal.AbstractSqsMessageSource.doStartcatchesCompletionExceptionwithQueueNotFoundExceptionas its cause, flips askippedflag, logs a warning, and returns without settingqueueAttributes/queueUrlor configuring the conversion context.AbstractSqsMessageSource.doPollForMessagesshort-circuits to an empty future whenskipped, so the polling loop is a no-op for the lifetime of the source.The
@RetryableTopic-style orFAILpaths are untouched — only the newIGNOREconstant exercises the new branches. The property binding forspring.cloud.aws.sqs.queue-not-found-strategy=IGNOREpicks up automatically becauseSqsPropertiesalready exposes the enum directly.Test plan
QueueAttributesResolverIntegrationTests#shouldIgnoreQueueWhenStrategyIsIgnoremirrors the existing#shouldNotCreateQueuepattern against LocalStack, asserting that resolving a non-existent queue withIGNOREsurfaces aQueueNotFoundExceptionwhose cause isQueueDoesNotExistException(rather than the genericQueueAttributesResolvingExceptionthatFAILproduces).QueueAttributesResolverIntegrationTestsclass (7 tests) passes locally on LocalStack — the existingFAIL/CREATEpaths still produce their original exception types becausewrapExceptiononly passes throughQueueNotFoundExceptionspecifically../mvnw -B spotless:applyclean.Docs
docs/src/main/asciidoc/sqs.adoc— the table entry forqueueNotFoundStrategygets a sentence on theIGNOREbehavior next to the existingFAILnote.AI agent disclosure
I used an AI coding agent (Claude Code) to navigate the existing strategy / resolver / source code paths and draft this patch. I have read every line, verified the dispatch through the
CompletionExceptionunwrap indoStart, traced the property-binding to confirm noSqsPropertieschange is needed, and confirmed the new IGNORE test passes against LocalStack alongside the existing 6 resolver tests. I will be the one responding to review.