From aa738816ca3dd7c5ed803cffaa14c7ef8abc9f5f Mon Sep 17 00:00:00 2001 From: Ben Bangert Date: Tue, 19 Jul 2016 14:18:00 -0700 Subject: [PATCH] fix: overwrite existing messages instead of throwing an error DynamoDB throws a condition check failure if you put_item and it already exists. This can occur when we save a message that may already exist when a user hops servers without ack'ing. We should allow it since it consumes the same resources. Closes #535 --- autopush/db.py | 2 +- autopush/tests/test_db.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/autopush/db.py b/autopush/db.py index 9b48022c..20f96dcc 100644 --- a/autopush/db.py +++ b/autopush/db.py @@ -411,7 +411,7 @@ def store_message(self, uaid, channel_id, message_id, ttl, data=None, if data: item["headers"] = headers item["data"] = data - self.table.put_item(data=item) + self.table.put_item(data=item, overwrite=True) return True @track_provisioned diff --git a/autopush/tests/test_db.py b/autopush/tests/test_db.py index 3494955a..4ece6c8b 100644 --- a/autopush/tests/test_db.py +++ b/autopush/tests/test_db.py @@ -306,6 +306,35 @@ def test_message_storage(self): all_messages = list(message.fetch_messages(self.uaid)) eq_(len(all_messages), 0) + def test_message_storage_overwrite(self): + """Test that store_message can overwrite existing messages which + can occur in some reconnect cases but shouldn't error""" + chid = str(uuid.uuid4()) + chid2 = str(uuid.uuid4()) + m = get_rotating_message_table() + message = Message(m, SinkMetrics()) + message.register_channel(self.uaid, chid) + message.register_channel(self.uaid, chid2) + + data1 = str(uuid.uuid4()) + data2 = str(uuid.uuid4()) + ttl = int(time.time())+100 + time1, time2 = self._nstime(), self._nstime()+1 + message.store_message(self.uaid, chid, time1, ttl, data1, {}) + message.store_message(self.uaid, chid, time1, ttl, data2, {}) + message.store_message(self.uaid, chid2, time2, ttl, data1, {}) + + all_messages = list(message.fetch_messages(self.uaid)) + eq_(len(all_messages), 2) + + message.delete_messages_for_channel(self.uaid, chid2) + all_messages = list(message.fetch_messages(self.uaid)) + eq_(len(all_messages), 1) + + message.delete_message(self.uaid, chid, time1) + all_messages = list(message.fetch_messages(self.uaid)) + eq_(len(all_messages), 0) + def test_delete_user(self): chid = str(uuid.uuid4()) chid2 = str(uuid.uuid4())