Skip to content

Commit 476e7f3

Browse files
SQS: Allow usage of message-group-id param when using a Fair Queue (#12930)
1 parent dfad92b commit 476e7f3

File tree

6 files changed

+250
-98
lines changed

6 files changed

+250
-98
lines changed

localstack-core/localstack/services/sqs/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
ATTR_NAME_CHAR_REGEX = "^[\u00c0-\u017fa-zA-Z0-9_.-]*$"
1010
ATTR_NAME_PREFIX_SUFFIX_REGEX = r"^(?!(aws\.|amazon\.|\.)).*(?<!\.)$"
1111
ATTR_TYPE_REGEX = "^(String|Number|Binary).*$"
12-
FIFO_MSG_REGEX = "^[0-9a-zA-z!\"#$%&'()*+,./:;<=>?@[\\]^_`{|}~-]*$"
12+
FIFO_MSG_REGEX = "^[0-9a-zA-z!\"#$%&'()*+,./:;<=>?@[\\]^_`{|}~-]{1,128}$"
1313

1414
DEDUPLICATION_INTERVAL_IN_SEC = 5 * 60
1515

localstack-core/localstack/services/sqs/models.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -771,11 +771,6 @@ def put(
771771
f"Value {message_deduplication_id} for parameter MessageDeduplicationId is invalid. Reason: The "
772772
f"request includes a parameter that is not valid for this queue type."
773773
)
774-
if isinstance(message_group_id, str):
775-
raise InvalidParameterValueException(
776-
f"Value {message_group_id} for parameter MessageGroupId is invalid. Reason: The request include "
777-
f"parameter that is not valid for this queue type."
778-
)
779774

780775
standard_message = SqsMessage(time.time(), message)
781776

localstack-core/localstack/services/sqs/provider.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -621,17 +621,13 @@ def check_attributes(message_attributes: MessageBodyAttributeMap):
621621
raise InvalidParameterValueException(e.args[0])
622622

623623

624-
def check_fifo_id(fifo_id, parameter):
625-
if not fifo_id:
624+
def check_fifo_id(fifo_id: str | None, parameter: str):
625+
if fifo_id is None:
626626
return
627-
if len(fifo_id) > 128:
628-
raise InvalidParameterValueException(
629-
f"Value {fifo_id} for parameter {parameter} is invalid. Reason: {parameter} can only include alphanumeric and punctuation characters. 1 to 128 in length."
630-
)
631627
if not re.match(sqs_constants.FIFO_MSG_REGEX, fifo_id):
632628
raise InvalidParameterValueException(
633-
"Invalid characters found. Deduplication ID and group ID can only contain"
634-
"alphanumeric characters as well as TODO"
629+
f"Value {fifo_id} for parameter {parameter} is invalid. "
630+
f"Reason: {parameter} can only include alphanumeric and punctuation characters. 1 to 128 in length."
635631
)
636632

637633

tests/aws/services/sqs/test_sqs.py

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -544,14 +544,22 @@ def test_send_message_batch_with_oversized_contents_with_updated_maximum_message
544544

545545
snapshot.match("send_oversized_message_batch", response)
546546

547+
@pytest.mark.parametrize(
548+
"message_group_id",
549+
[
550+
pytest.param("", id="empty"),
551+
pytest.param("a" * 129, id="too_long"),
552+
pytest.param("group 123", id="spaces"),
553+
],
554+
)
547555
@markers.aws.validated
548-
def test_send_message_to_standard_queue_with_empty_message_group_id(
549-
self, sqs_create_queue, aws_client, snapshot
556+
def test_send_message_to_standard_queue_with_invalid_message_group_id(
557+
self, sqs_queue, aws_client, snapshot, message_group_id
550558
):
551-
queue = sqs_create_queue()
552-
553559
with pytest.raises(ClientError) as e:
554-
aws_client.sqs.send_message(QueueUrl=queue, MessageBody="message", MessageGroupId="")
560+
aws_client.sqs.send_message(
561+
QueueUrl=sqs_queue, MessageBody="message", MessageGroupId=message_group_id
562+
)
555563
snapshot.match("error-response", e.value.response)
556564

557565
@markers.aws.validated
@@ -786,9 +794,7 @@ def test_send_message_with_delay_0_works_for_fifo(self, sqs_create_queue, aws_sq
786794
assert message_sent_hash == message_received_hash
787795

788796
@markers.aws.validated
789-
@markers.snapshot.skip_snapshot_verify(paths=["$..Error.Detail"])
790-
def test_message_deduplication_id_too_long(self, sqs_create_queue, aws_client, snapshot):
791-
# see issue https://github.com/localstack/localstack/issues/6612
797+
def test_message_deduplication_id_success(self, sqs_create_queue, aws_client, snapshot):
792798
queue_name = f"queue-{short_uid()}.fifo"
793799
attributes = {"FifoQueue": "true"}
794800
queue_url = sqs_create_queue(QueueName=queue_name, Attributes=attributes)
@@ -800,36 +806,28 @@ def test_message_deduplication_id_too_long(self, sqs_create_queue, aws_client, s
800806
MessageDeduplicationId="a" * 128,
801807
)
802808

803-
with pytest.raises(ClientError) as e:
804-
aws_client.sqs.send_message(
805-
QueueUrl=queue_url,
806-
MessageBody="Hello World!",
807-
MessageGroupId="test",
808-
MessageDeduplicationId="a" * 129,
809-
)
810-
snapshot.match("error-response", e.value.response)
811-
809+
@pytest.mark.parametrize(
810+
"deduplication_id",
811+
[
812+
pytest.param("", id="empty"),
813+
pytest.param("a" * 129, id="too_long"),
814+
pytest.param("group 123", id="spaces"),
815+
],
816+
)
812817
@markers.aws.validated
813-
@markers.snapshot.skip_snapshot_verify(paths=["$..Error.Detail"])
814-
def test_message_group_id_too_long(self, sqs_create_queue, aws_client, snapshot):
815-
# see issue https://github.com/localstack/localstack/issues/6612
818+
def test_message_deduplication_id_invalid(
819+
self, sqs_create_queue, aws_client, snapshot, deduplication_id
820+
):
816821
queue_name = f"queue-{short_uid()}.fifo"
817822
attributes = {"FifoQueue": "true"}
818823
queue_url = sqs_create_queue(QueueName=queue_name, Attributes=attributes)
819824

820-
aws_client.sqs.send_message(
821-
QueueUrl=queue_url,
822-
MessageBody="Hello World!",
823-
MessageGroupId="a" * 128,
824-
MessageDeduplicationId="1",
825-
)
826-
827825
with pytest.raises(ClientError) as e:
828826
aws_client.sqs.send_message(
829827
QueueUrl=queue_url,
830828
MessageBody="Hello World!",
831-
MessageGroupId="a" * 129,
832-
MessageDeduplicationId="2",
829+
MessageGroupId="test",
830+
MessageDeduplicationId=deduplication_id,
833831
)
834832
snapshot.match("error-response", e.value.response)
835833

@@ -4741,6 +4739,13 @@ def test_non_existent_queue(self, aws_client, sqs_create_queue, sqs_queue_exists
47414739
aws_client.sqs_query.get_queue_attributes(QueueUrl=queue_url)
47424740
snapshot.match("queue-does-not-exist-query", e.value.response)
47434741

4742+
@markers.aws.validated
4743+
def test_fair_queue_with_message_group_id(self, sqs_queue, aws_sqs_client, snapshot):
4744+
send_result = aws_sqs_client.send_message(
4745+
QueueUrl=sqs_queue, MessageBody="message", MessageGroupId="test"
4746+
)
4747+
snapshot.match("send_message", send_result)
4748+
47444749

47454750
@pytest.fixture()
47464751
def sqs_http_client(aws_http_client_factory, region_name):

tests/aws/services/sqs/test_sqs.snapshot.json

Lines changed: 132 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -279,40 +279,6 @@
279279
}
280280
}
281281
},
282-
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_message_deduplication_id_too_long": {
283-
"recorded-date": "30-04-2024, 13:35:34",
284-
"recorded-content": {
285-
"error-response": {
286-
"Error": {
287-
"Code": "InvalidParameterValue",
288-
"Message": "Value aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa for parameter MessageDeduplicationId is invalid. Reason: MessageDeduplicationId can only include alphanumeric and punctuation characters. 1 to 128 in length.",
289-
"QueryErrorCode": "InvalidParameterValueException",
290-
"Type": "Sender"
291-
},
292-
"ResponseMetadata": {
293-
"HTTPHeaders": {},
294-
"HTTPStatusCode": 400
295-
}
296-
}
297-
}
298-
},
299-
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_message_group_id_too_long": {
300-
"recorded-date": "30-04-2024, 13:35:35",
301-
"recorded-content": {
302-
"error-response": {
303-
"Error": {
304-
"Code": "InvalidParameterValue",
305-
"Message": "Value aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa for parameter MessageGroupId is invalid. Reason: MessageGroupId can only include alphanumeric and punctuation characters. 1 to 128 in length.",
306-
"QueryErrorCode": "InvalidParameterValueException",
307-
"Type": "Sender"
308-
},
309-
"ResponseMetadata": {
310-
"HTTPHeaders": {},
311-
"HTTPStatusCode": 400
312-
}
313-
}
314-
}
315-
},
316282
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_create_queue_with_different_attributes_raises_exception[sqs]": {
317283
"recorded-date": "30-04-2024, 13:33:18",
318284
"recorded-content": {
@@ -974,23 +940,6 @@
974940
}
975941
}
976942
},
977-
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_send_message_to_standard_queue_with_empty_message_group_id": {
978-
"recorded-date": "08-11-2024, 12:04:39",
979-
"recorded-content": {
980-
"error-response": {
981-
"Error": {
982-
"Code": "InvalidParameterValue",
983-
"Message": "Value for parameter MessageGroupId is invalid. Reason: The request include parameter that is not valid for this queue type.",
984-
"QueryErrorCode": "InvalidParameterValueException",
985-
"Type": "Sender"
986-
},
987-
"ResponseMetadata": {
988-
"HTTPHeaders": {},
989-
"HTTPStatusCode": 400
990-
}
991-
}
992-
}
993-
},
994943
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_send_batch_missing_message_group_id_for_fifo_queue[sqs_query]": {
995944
"recorded-date": "30-04-2024, 13:33:45",
996945
"recorded-content": {
@@ -4012,5 +3961,137 @@
40123961
"ReceiptHandle": "<receipt-handle:1>"
40133962
}
40143963
}
3964+
},
3965+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_fair_queue_with_message_group_id[sqs]": {
3966+
"recorded-date": "30-07-2025, 09:52:06",
3967+
"recorded-content": {
3968+
"send_message": {
3969+
"MD5OfMessageBody": "78e731027d8fd50ed642340b7c9a63b3",
3970+
"MessageId": "<uuid:1>",
3971+
"ResponseMetadata": {
3972+
"HTTPHeaders": {},
3973+
"HTTPStatusCode": 200
3974+
}
3975+
}
3976+
}
3977+
},
3978+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_fair_queue_with_message_group_id[sqs_query]": {
3979+
"recorded-date": "30-07-2025, 09:52:07",
3980+
"recorded-content": {
3981+
"send_message": {
3982+
"MD5OfMessageBody": "78e731027d8fd50ed642340b7c9a63b3",
3983+
"MessageId": "<uuid:1>",
3984+
"ResponseMetadata": {
3985+
"HTTPHeaders": {},
3986+
"HTTPStatusCode": 200
3987+
}
3988+
}
3989+
}
3990+
},
3991+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_send_message_to_standard_queue_with_invalid_message_group_id[empty]": {
3992+
"recorded-date": "30-07-2025, 10:01:38",
3993+
"recorded-content": {
3994+
"error-response": {
3995+
"Error": {
3996+
"Code": "InvalidParameterValue",
3997+
"Message": "Value for parameter MessageGroupId is invalid. Reason: MessageGroupId can only include alphanumeric and punctuation characters. 1 to 128 in length.",
3998+
"QueryErrorCode": "InvalidParameterValueException",
3999+
"Type": "Sender"
4000+
},
4001+
"ResponseMetadata": {
4002+
"HTTPHeaders": {},
4003+
"HTTPStatusCode": 400
4004+
}
4005+
}
4006+
}
4007+
},
4008+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_send_message_to_standard_queue_with_invalid_message_group_id[too_long]": {
4009+
"recorded-date": "30-07-2025, 10:01:39",
4010+
"recorded-content": {
4011+
"error-response": {
4012+
"Error": {
4013+
"Code": "InvalidParameterValue",
4014+
"Message": "Value aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa for parameter MessageGroupId is invalid. Reason: MessageGroupId can only include alphanumeric and punctuation characters. 1 to 128 in length.",
4015+
"QueryErrorCode": "InvalidParameterValueException",
4016+
"Type": "Sender"
4017+
},
4018+
"ResponseMetadata": {
4019+
"HTTPHeaders": {},
4020+
"HTTPStatusCode": 400
4021+
}
4022+
}
4023+
}
4024+
},
4025+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_send_message_to_standard_queue_with_invalid_message_group_id[spaces]": {
4026+
"recorded-date": "30-07-2025, 10:01:39",
4027+
"recorded-content": {
4028+
"error-response": {
4029+
"Error": {
4030+
"Code": "InvalidParameterValue",
4031+
"Message": "Value group 123 for parameter MessageGroupId is invalid. Reason: MessageGroupId can only include alphanumeric and punctuation characters. 1 to 128 in length.",
4032+
"QueryErrorCode": "InvalidParameterValueException",
4033+
"Type": "Sender"
4034+
},
4035+
"ResponseMetadata": {
4036+
"HTTPHeaders": {},
4037+
"HTTPStatusCode": 400
4038+
}
4039+
}
4040+
}
4041+
},
4042+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_message_deduplication_id_invalid[empty]": {
4043+
"recorded-date": "30-07-2025, 10:25:50",
4044+
"recorded-content": {
4045+
"error-response": {
4046+
"Error": {
4047+
"Code": "InvalidParameterValue",
4048+
"Message": "Value for parameter MessageDeduplicationId is invalid. Reason: MessageDeduplicationId can only include alphanumeric and punctuation characters. 1 to 128 in length.",
4049+
"QueryErrorCode": "InvalidParameterValueException",
4050+
"Type": "Sender"
4051+
},
4052+
"ResponseMetadata": {
4053+
"HTTPHeaders": {},
4054+
"HTTPStatusCode": 400
4055+
}
4056+
}
4057+
}
4058+
},
4059+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_message_deduplication_id_invalid[too_long]": {
4060+
"recorded-date": "30-07-2025, 10:25:51",
4061+
"recorded-content": {
4062+
"error-response": {
4063+
"Error": {
4064+
"Code": "InvalidParameterValue",
4065+
"Message": "Value aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa for parameter MessageDeduplicationId is invalid. Reason: MessageDeduplicationId can only include alphanumeric and punctuation characters. 1 to 128 in length.",
4066+
"QueryErrorCode": "InvalidParameterValueException",
4067+
"Type": "Sender"
4068+
},
4069+
"ResponseMetadata": {
4070+
"HTTPHeaders": {},
4071+
"HTTPStatusCode": 400
4072+
}
4073+
}
4074+
}
4075+
},
4076+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_message_deduplication_id_invalid[spaces]": {
4077+
"recorded-date": "30-07-2025, 10:25:51",
4078+
"recorded-content": {
4079+
"error-response": {
4080+
"Error": {
4081+
"Code": "InvalidParameterValue",
4082+
"Message": "Value group 123 for parameter MessageDeduplicationId is invalid. Reason: MessageDeduplicationId can only include alphanumeric and punctuation characters. 1 to 128 in length.",
4083+
"QueryErrorCode": "InvalidParameterValueException",
4084+
"Type": "Sender"
4085+
},
4086+
"ResponseMetadata": {
4087+
"HTTPHeaders": {},
4088+
"HTTPStatusCode": 400
4089+
}
4090+
}
4091+
}
4092+
},
4093+
"tests/aws/services/sqs/test_sqs.py::TestSqsProvider::test_message_deduplication_id_success": {
4094+
"recorded-date": "30-07-2025, 10:26:48",
4095+
"recorded-content": {}
40154096
}
40164097
}

0 commit comments

Comments
 (0)