fix(sqs): per-(account, region) state infra; scope SQS queues to the request region - #2675
Merged
Merged
Conversation
vieiralucas
force-pushed
the
fix-region-scoped-state
branch
from
October 4, 2026 07:27
2c275d7 to
cddee99
Compare
vieiralucas
force-pushed
the
fix-region-scoped-state
branch
2 times, most recently
from
October 4, 2026 13:02
f285e06 to
4f8497b
Compare
Add RegionalState<T> / MultiRegionState<T> so a regional service keeps an independent state per account and region, with ARN-addressed lookups and a SplitByRegion migration that moves legacy account-wide snapshots into the region each resource's ARN names.
Queues live per (account, region): the same queue name coexists in two regions, ListQueues/GetQueueUrl/queue-addressed calls see only the request region, and every delivery or lookup by queue ARN (SNS/EventBridge/S3 fanout, Lambda ESM poller, Pipes, resource policies, IAM resource tags) uses the ARN's region and account instead of the server region. Step Functions resolves a QueueUrl in the execution's region. v2 snapshots migrate each queue into the region its ARN names.
…shot migration; document SQS regions
…caller's region has no such queue
- /_fakecloud/sqs/messages entries carry the queue's region and ARN (queue URLs carry no region), in the server and all seven SDKs. - force-dlq acts on one account and region (accountId/region query parameters, default the server's) instead of every same-named queue. - A new account's first region inherits shared resources from the default account, as a new account did before the region split.
vieiralucas
force-pushed
the
fix-region-scoped-state
branch
from
October 4, 2026 13:32
4f8497b to
b3b7f3e
Compare
Queues are regional: each region's stack instance queue is listed by an SQS client of that region (one per account and region), instead of expecting one us-east-1 client to see both.
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
Bug audit 2026-10-01 Tier 0.1 (and the shared infra for 0.2-0.6).
MultiAccountStatekeys state by account only, so regional services that key resources by name collide across regions and their lists leak other regions. This PR adds the reusable per-(account, region) mechanism and converts SQS as the first service; the other services follow in stacked PRs.Shared infra (
fakecloud_core::multi_account)RegionalState<T>: one account's state split per region (plain JSON object keyed by region, no tuple keys).region()never creates,region_mut()creates on first use.MultiRegionState<T> = MultiAccountState<RegionalState<T>>withregional/regional_mut/regional_get_mut,by_arn/by_arn_mut(ARN's account + region, never creates),iter_regional,default_regional[_mut].SplitByRegiontrait +MultiAccountState::into_regional()/RegionalState::from_legacy()move each resource of a legacy account-wide state into the region its ARN names (records without one go to the server's default region).MultiAccountState::map_intofor type-changing migrations.SQS
ListQueues,GetQueueUrland every queue-addressed call see only the request region. A queue ARN of another region (or account) no longer resolves to a same-name local queue.<endpoint>/<account>/<name>(byte-identical, tfacc'sQueueNameFromURLneeds exactly 3 path segments; one fakecloud endpoint serves every region). The request region picks which region's queue a URL addresses; the ARN always names its own region.SqsDelivery::queue_arn_for_urlnow takes the region; Step Functions resolves a QueueUrl in the execution's region.resource_exists) takes the stack region.parse_sqs_snapshot), message move tasks follow their source queue./_fakecloud/sqs/messages, expiration tick, force-dlq) cover every account and region; wire shapes unchanged, so no SDK change.Test plan
cargo test -p fakecloud-core --lib(new RegionalState tests: isolation, by_arn, JSON round-trip, legacy split)cargo test -p fakecloud-sqs(205 pass; new: two-region coexistence/list/GetQueueUrl/delete, cn-partition queue unreachable from us-east-1, delivery by ARN region, v1/v2 snapshot migration)sqs_regional(new: two SDK clients in different regions, SNS fanout lands in the ARN region, legacy v2 snapshot loads into ARN regions, restart keeps regions) plussqs,sqs_persistence,sqs_message_move,sqs_kms: all passcargo nextest run -p fakecloud-conformance -E 'test(sqs)': 28/28cargo clippy --workspace --all-targets -- -D warnings;cargo fmtDocs:
website/content/docs/services/sqs.md(Regions section),website/content/docs/reference/persistence.md(new Regional state migration section; also lists the already-merged CloudFormation split). SDKs unaffected (no wire-shape change).Summary by cubic
Adds a reusable per-(account, region) state container and scopes SQS queues to the request region, so the same queue name can exist independently in different regions without state leaking across them. Previously queues were keyed by account only, which caused regional services to collide.
Under the new behavior
ListQueues,GetQueueUrl, and every queue-addressed call see only the request region, and all ARN-based lookups and deliveries (SNS/EventBridge/S3 fanout, Lambda ESM poller, Pipes, resource policies, IAM tag lookups) resolve the queue in its ARN's region and account. QueueUrl stays<endpoint>/<account>/<name>: the request region picks which queue a URL addresses, falling back to the queue of that account and name in the one other region that has it (Nonewhen ambiguous), while the ARN always names its own region. CloudFormation creates, updates, and drift-checks queues in the stack's region (stack sets check each instance's account and region); Step Functions resolves a QueueUrl in the execution's region.Introspection now carries regions:
/_fakecloud/sqs/messagesentries includeregionandqueueArn, andforce-dlqtargets one account and region viaaccountId/regionquery parameters instead of every same-named queue. A new account's first region inherits shared resources from the default account.Migration
MultiAccountState::map_into/RegionalState::map), placing each queue into the region its ARN names.force_dlqby account and region.Written for commit 893200c. Summary will update on new commits.