I've been fighting with a weird bug in my app: if I'm sending a push notification to 2+ users, only the first one receives the notification.
The bug was that I .pop
ed the message
key from the data.
Here's how it works (pseudo-code):
def send(users: [User], data: dict):
notifications = reduce(lambda acc, user: acc + [Notification(user, data)], users, [])
db.bulk_insert(notifications)
for notification in notifications:
notification.send()
...
def Notification.send(self):
message = self.data.pop('message')
Firebase.send(message, self.data)
The first notification will be sent and I thought that message
would be popped out of self.data
, but actually it would be popped out of the dict that self.data
points to! That means that every Notification object that has been initialized in the send
function using Notification(user, data)
(and not Notification(user, data.copy())
) would not have data['message']
anymore, leading to unexpected behavior.
If you really need to get rid of a key in a dict, you should .copy()
it before mutating.
If you don't - just stick to .get()
.
Good catch Defman!
Keep in mind that
copy()
does not create a deep copy so if you modify theNotification
objects... both references will point to the sameNotification
object that you modified :DIf you have memory constraints and you want to let the GC do its work you could investigate the usage of weakref: