jazzband / django-push-notifications

Send push notifications to mobile devices through GCM or APNS in Django.
MIT License
2.24k stars 609 forks source link

Changing UNIQUE_REG_ID in settings makes the DB schema inconsistent #595

Open ge0rg opened 3 years ago

ge0rg commented 3 years ago

The settings variable UNIQUE_REG_ID is required to enforce that no duplicate registrations end up in the devices table (which is crucial for "noisy" notifications). However, changing the setting does not yield the desired effect on an existing project. If you add UNIQUE_REG_ID=True to your application settings, this will not be enforced by the underlying database.

The reason for this is that the value of UNIQUE_REG_ID is evaluated only once, when the respective migration is applied, and never checked again: https://github.com/jazzband/django-push-notifications/blob/master/push_notifications/migrations/0007_uniquesetting.py#L16

There is no runtime / migration time code to check whether the value has changed and the migration needs to be re-generated / re-run.

The workaround I had to do was the following:

  1. Unroll the migration:
./manage.py migrate push_notifications 0006_webpushdevice
  1. Remove duplicate registrations from the database, so that the migration won't fail due to the new constraints. There was no easy way to return duplicates via ORM queries, so here's the psql command:
DELETE FROM push_notifications_gcmdevice
WHERE id IN (
    SELECT min(id) FROM push_notifications_gcmdevice
    GROUP BY registration_id HAVING COUNT(registration_id)>1
);
  1. Roll out the new settings.py

  2. Re-apply the migration:

./manage.py migrate push_notifications