SQS - Return multiple group-messages in the same request
This commit is contained in:
parent
5bd3588f74
commit
1ef3094e45
@ -6,6 +6,7 @@ import json
|
|||||||
import re
|
import re
|
||||||
import six
|
import six
|
||||||
import struct
|
import struct
|
||||||
|
from copy import deepcopy
|
||||||
from xml.sax.saxutils import escape
|
from xml.sax.saxutils import escape
|
||||||
|
|
||||||
from boto3 import Session
|
from boto3 import Session
|
||||||
@ -101,7 +102,6 @@ class Message(BaseModel):
|
|||||||
if data_type == "String" or data_type == "Number":
|
if data_type == "String" or data_type == "Number":
|
||||||
value = attr["string_value"]
|
value = attr["string_value"]
|
||||||
elif data_type == "Binary":
|
elif data_type == "Binary":
|
||||||
print(data_type, attr["binary_value"], type(attr["binary_value"]))
|
|
||||||
value = base64.b64decode(attr["binary_value"])
|
value = base64.b64decode(attr["binary_value"])
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
@ -722,6 +722,7 @@ class SQSBackend(BaseBackend):
|
|||||||
previous_result_count = len(result)
|
previous_result_count = len(result)
|
||||||
|
|
||||||
polling_end = unix_time() + wait_seconds_timeout
|
polling_end = unix_time() + wait_seconds_timeout
|
||||||
|
currently_pending_groups = deepcopy(queue.pending_message_groups)
|
||||||
|
|
||||||
# queue.messages only contains visible messages
|
# queue.messages only contains visible messages
|
||||||
while True:
|
while True:
|
||||||
@ -739,11 +740,11 @@ class SQSBackend(BaseBackend):
|
|||||||
# The message is pending but is visible again, so the
|
# The message is pending but is visible again, so the
|
||||||
# consumer must have timed out.
|
# consumer must have timed out.
|
||||||
queue.pending_messages.remove(message)
|
queue.pending_messages.remove(message)
|
||||||
|
currently_pending_groups = deepcopy(queue.pending_message_groups)
|
||||||
|
|
||||||
if message.group_id and queue.fifo_queue:
|
if message.group_id and queue.fifo_queue:
|
||||||
if message.group_id in queue.pending_message_groups:
|
if message.group_id in currently_pending_groups:
|
||||||
# There is already one active message with the same
|
# A previous call is still processing messages in this group, so we cannot deliver this one.
|
||||||
# group, so we cannot deliver this one.
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
queue.pending_messages.add(message)
|
queue.pending_messages.add(message)
|
||||||
|
@ -232,6 +232,14 @@ class SQSResponse(BaseResponse):
|
|||||||
|
|
||||||
queue_name = self._get_queue_name()
|
queue_name = self._get_queue_name()
|
||||||
|
|
||||||
|
if not message_group_id:
|
||||||
|
queue = self.sqs_backend.get_queue(queue_name)
|
||||||
|
if queue.attributes.get("FifoQueue", False):
|
||||||
|
return self._error(
|
||||||
|
"MissingParameter",
|
||||||
|
"The request must contain the parameter MessageGroupId.",
|
||||||
|
)
|
||||||
|
|
||||||
message = self.sqs_backend.send_message(
|
message = self.sqs_backend.send_message(
|
||||||
queue_name,
|
queue_name,
|
||||||
message,
|
message,
|
||||||
|
@ -1164,7 +1164,7 @@ def test_send_message_batch_with_empty_list():
|
|||||||
|
|
||||||
@mock_sqs
|
@mock_sqs
|
||||||
def test_batch_change_message_visibility():
|
def test_batch_change_message_visibility():
|
||||||
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "true":
|
if settings.TEST_SERVER_MODE:
|
||||||
raise SkipTest("Cant manipulate time in server mode")
|
raise SkipTest("Cant manipulate time in server mode")
|
||||||
|
|
||||||
with freeze_time("2015-01-01 12:00:00"):
|
with freeze_time("2015-01-01 12:00:00"):
|
||||||
@ -1174,9 +1174,15 @@ def test_batch_change_message_visibility():
|
|||||||
)
|
)
|
||||||
queue_url = resp["QueueUrl"]
|
queue_url = resp["QueueUrl"]
|
||||||
|
|
||||||
sqs.send_message(QueueUrl=queue_url, MessageBody="msg1")
|
sqs.send_message(
|
||||||
sqs.send_message(QueueUrl=queue_url, MessageBody="msg2")
|
QueueUrl=queue_url, MessageBody="msg1", MessageGroupId="group1"
|
||||||
sqs.send_message(QueueUrl=queue_url, MessageBody="msg3")
|
)
|
||||||
|
sqs.send_message(
|
||||||
|
QueueUrl=queue_url, MessageBody="msg2", MessageGroupId="group2"
|
||||||
|
)
|
||||||
|
sqs.send_message(
|
||||||
|
QueueUrl=queue_url, MessageBody="msg3", MessageGroupId="group3"
|
||||||
|
)
|
||||||
|
|
||||||
with freeze_time("2015-01-01 12:01:00"):
|
with freeze_time("2015-01-01 12:01:00"):
|
||||||
receive_resp = sqs.receive_message(QueueUrl=queue_url, MaxNumberOfMessages=2)
|
receive_resp = sqs.receive_message(QueueUrl=queue_url, MaxNumberOfMessages=2)
|
||||||
@ -1529,7 +1535,7 @@ def test_create_fifo_queue_with_dlq():
|
|||||||
|
|
||||||
@mock_sqs
|
@mock_sqs
|
||||||
def test_queue_with_dlq():
|
def test_queue_with_dlq():
|
||||||
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "true":
|
if settings.TEST_SERVER_MODE:
|
||||||
raise SkipTest("Cant manipulate time in server mode")
|
raise SkipTest("Cant manipulate time in server mode")
|
||||||
|
|
||||||
sqs = boto3.client("sqs", region_name="us-east-1")
|
sqs = boto3.client("sqs", region_name="us-east-1")
|
||||||
@ -1554,8 +1560,12 @@ def test_queue_with_dlq():
|
|||||||
)
|
)
|
||||||
queue_url2 = resp["QueueUrl"]
|
queue_url2 = resp["QueueUrl"]
|
||||||
|
|
||||||
sqs.send_message(QueueUrl=queue_url2, MessageBody="msg1")
|
sqs.send_message(
|
||||||
sqs.send_message(QueueUrl=queue_url2, MessageBody="msg2")
|
QueueUrl=queue_url2, MessageBody="msg1", MessageGroupId="group"
|
||||||
|
)
|
||||||
|
sqs.send_message(
|
||||||
|
QueueUrl=queue_url2, MessageBody="msg2", MessageGroupId="group"
|
||||||
|
)
|
||||||
|
|
||||||
with freeze_time("2015-01-01 13:00:00"):
|
with freeze_time("2015-01-01 13:00:00"):
|
||||||
resp = sqs.receive_message(
|
resp = sqs.receive_message(
|
||||||
@ -1686,20 +1696,24 @@ def test_receive_messages_with_message_group_id():
|
|||||||
queue.set_attributes(Attributes={"VisibilityTimeout": "3600"})
|
queue.set_attributes(Attributes={"VisibilityTimeout": "3600"})
|
||||||
queue.send_message(MessageBody="message-1", MessageGroupId="group")
|
queue.send_message(MessageBody="message-1", MessageGroupId="group")
|
||||||
queue.send_message(MessageBody="message-2", MessageGroupId="group")
|
queue.send_message(MessageBody="message-2", MessageGroupId="group")
|
||||||
|
queue.send_message(MessageBody="message-3", MessageGroupId="group")
|
||||||
|
queue.send_message(MessageBody="separate-message", MessageGroupId="anothergroup")
|
||||||
|
|
||||||
messages = queue.receive_messages()
|
messages = queue.receive_messages(MaxNumberOfMessages=2)
|
||||||
messages.should.have.length_of(1)
|
messages.should.have.length_of(2)
|
||||||
message = messages[0]
|
messages[0].attributes["MessageGroupId"].should.equal("group")
|
||||||
|
|
||||||
# received message is not deleted!
|
# Different client can not 'see' messages from the group until they are processed
|
||||||
|
messages_for_client_2 = queue.receive_messages(WaitTimeSeconds=0)
|
||||||
messages = queue.receive_messages(WaitTimeSeconds=0)
|
messages_for_client_2.should.have.length_of(1)
|
||||||
messages.should.have.length_of(0)
|
messages_for_client_2[0].body.should.equal("separate-message")
|
||||||
|
|
||||||
# message is now processed, next one should be available
|
# message is now processed, next one should be available
|
||||||
message.delete()
|
for message in messages:
|
||||||
|
message.delete()
|
||||||
messages = queue.receive_messages()
|
messages = queue.receive_messages()
|
||||||
messages.should.have.length_of(1)
|
messages.should.have.length_of(1)
|
||||||
|
messages[0].body.should.equal("message-3")
|
||||||
|
|
||||||
|
|
||||||
@mock_sqs
|
@mock_sqs
|
||||||
@ -1730,7 +1744,7 @@ def test_receive_messages_with_message_group_id_on_requeue():
|
|||||||
|
|
||||||
@mock_sqs
|
@mock_sqs
|
||||||
def test_receive_messages_with_message_group_id_on_visibility_timeout():
|
def test_receive_messages_with_message_group_id_on_visibility_timeout():
|
||||||
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "true":
|
if settings.TEST_SERVER_MODE:
|
||||||
raise SkipTest("Cant manipulate time in server mode")
|
raise SkipTest("Cant manipulate time in server mode")
|
||||||
|
|
||||||
with freeze_time("2015-01-01 12:00:00"):
|
with freeze_time("2015-01-01 12:00:00"):
|
||||||
@ -1746,12 +1760,12 @@ def test_receive_messages_with_message_group_id_on_visibility_timeout():
|
|||||||
messages.should.have.length_of(1)
|
messages.should.have.length_of(1)
|
||||||
message = messages[0]
|
message = messages[0]
|
||||||
|
|
||||||
# received message is not deleted!
|
# received message is not processed yet
|
||||||
|
messages_for_second_client = queue.receive_messages(WaitTimeSeconds=0)
|
||||||
|
messages_for_second_client.should.have.length_of(0)
|
||||||
|
|
||||||
messages = queue.receive_messages(WaitTimeSeconds=0)
|
for message in messages:
|
||||||
messages.should.have.length_of(0)
|
message.change_visibility(VisibilityTimeout=10)
|
||||||
|
|
||||||
message.change_visibility(VisibilityTimeout=10)
|
|
||||||
|
|
||||||
with freeze_time("2015-01-01 12:00:05"):
|
with freeze_time("2015-01-01 12:00:05"):
|
||||||
# no timeout yet
|
# no timeout yet
|
||||||
@ -1794,3 +1808,20 @@ def test_list_queues_limits_to_1000_queues():
|
|||||||
list(resource.queues.filter(QueueNamePrefix="test-queue")).should.have.length_of(
|
list(resource.queues.filter(QueueNamePrefix="test-queue")).should.have.length_of(
|
||||||
1000
|
1000
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@mock_sqs
|
||||||
|
def test_send_messages_to_fifo_without_message_group_id():
|
||||||
|
sqs = boto3.resource("sqs", region_name="eu-west-3")
|
||||||
|
queue = sqs.create_queue(
|
||||||
|
QueueName="blah.fifo",
|
||||||
|
Attributes={"FifoQueue": "true", "ContentBasedDeduplication": "true"},
|
||||||
|
)
|
||||||
|
|
||||||
|
with assert_raises(Exception) as e:
|
||||||
|
queue.send_message(MessageBody="message-1")
|
||||||
|
ex = e.exception
|
||||||
|
ex.response["Error"]["Code"].should.equal("MissingParameter")
|
||||||
|
ex.response["Error"]["Message"].should.equal(
|
||||||
|
"The request must contain the parameter MessageGroupId."
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user