fix(sns): make Subscribe idempotent for same topic+protocol+endpoint#185
Open
naile wants to merge 1 commit intohectorvent:mainfrom
Open
fix(sns): make Subscribe idempotent for same topic+protocol+endpoint#185naile wants to merge 1 commit intohectorvent:mainfrom
naile wants to merge 1 commit intohectorvent:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR aligns Floci’s SNS Subscribe behavior with AWS by making it idempotent for the same TopicArn + Protocol + Endpoint, preventing duplicate subscriptions (and duplicate deliveries) across repeated runs.
Changes:
- Add an idempotency check in
SnsService.subscribeto return an existing matching subscription instead of creating a new one. - Add a unit test covering idempotent subscribe and distinct-endpoint behavior.
- Add an integration test covering idempotent subscribe via the SNS Query (form-encoded) protocol.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/main/java/io/github/hectorvent/floci/services/sns/SnsService.java |
Adds lookup-before-create logic so Subscribe returns an existing subscription for the same topic/protocol/endpoint. |
src/test/java/io/github/hectorvent/floci/services/sns/SnsServiceTest.java |
Adds unit tests validating idempotency and distinct subscriptions for different endpoints. |
src/test/java/io/github/hectorvent/floci/services/sns/SnsIntegrationTest.java |
Adds query-protocol integration coverage for idempotent Subscribe and ensures no duplicate <member> entries are returned. |
Comments suppressed due to low confidence (1)
src/test/java/io/github/hectorvent/floci/services/sns/SnsIntegrationTest.java:161
@Order(7)is now used by bothsubscribe_idempotentandlistSubscriptionsByTopic. JUnit does not guarantee a stable ordering between tests with the same order value, which can make the suite nondeterministic as it grows. Consider giving these tests distinct order values (or removing ordering reliance if possible).
@Test
@Order(7)
void subscribe_idempotent() {
String arn = given()
.contentType("application/x-www-form-urlencoded")
.formParam("Action", "Subscribe")
.formParam("TopicArn", topicArn)
.formParam("Protocol", "sqs")
.formParam("Endpoint", sqsQueueUrl)
.when()
.post("/")
.then()
.statusCode(200)
.extract().xmlPath()
.getString("SubscribeResponse.SubscribeResult.SubscriptionArn");
assert arn.equals(subscriptionArn) : "Expected existing subscription ARN but got a new one";
given()
.contentType("application/x-www-form-urlencoded")
.formParam("Action", "ListSubscriptionsByTopic")
.formParam("TopicArn", topicArn)
.when()
.post("/")
.then()
.statusCode(200)
.body(containsString("<member>"))
.body(not(containsString("</member><member>")));
}
@Test
@Order(7)
void listSubscriptionsByTopic() {
given()
src/test/java/io/github/hectorvent/floci/services/sns/SnsIntegrationTest.java
Show resolved
Hide resolved
src/test/java/io/github/hectorvent/floci/services/sns/SnsIntegrationTest.java
Outdated
Show resolved
Hide resolved
AWS Subscribe returns the existing subscription when called with the same TopicArn, Protocol, and Endpoint. Floci was always creating a new subscription, causing duplicates to accumulate across test re-runs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c9fc4d3 to
3b45303
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/test/java/io/github/hectorvent/floci/services/sns/SnsIntegrationTest.java:151
@Order(7)is now used by bothsubscribe_idempotentandlistSubscriptionsByTopic. WithOrderAnnotation, JUnit does not guarantee a deterministic execution order between tests that share the same order value, which can make the suite harder to reason about and potentially flaky as more stateful tests are added. Consider assigning a unique order and shifting subsequent order values accordingly.
@Test
@Order(7)
void subscribe_idempotent() {
String arn = given()
.contentType("application/x-www-form-urlencoded")
.formParam("Action", "Subscribe")
.formParam("TopicArn", topicArn)
.formParam("Protocol", "sqs")
.formParam("Endpoint", sqsQueueUrl)
.when()
.post("/")
.then()
.statusCode(200)
.extract().xmlPath()
.getString("SubscribeResponse.SubscribeResult.SubscriptionArn");
assert arn.equals(subscriptionArn) : "Expected existing subscription ARN but got a new one";
}
@Test
@Order(7)
void listSubscriptionsByTopic() {
given()
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.
Summary
Subscribealways created a new subscription, even when one already existed for the same TopicArn+Protocol+Endpoint. This caused duplicate subscriptions to accumulate across test re-runs, leading to duplicate message delivery.Type of change
fix:)feat:)feat!:orfix!:)AWS Compatibility
Real AWS
Subscribeis idempotent — calling it with the same TopicArn, Protocol, and Endpoint returns the existing subscription ARN. Verified against AWS documentation and LocalStack implementation.There are two real AWS behaviors we don't cover:
etc.), AWS throws InvalidParameterException.
Both are irrelevant until we add attribute support to the Subscribe handlers.
Companion compatibility test: hectorvent/floci-compatibility-tests#38
Checklist
./mvnw testpasses locally