Skip to content

Commit

Permalink
Merge pull request #203 from rtibbles/no_deleted_model_tracking_in_de…
Browse files Browse the repository at this point in the history
…serialization

No deleted model tracking in deserialization
  • Loading branch information
rtibbles committed Oct 5, 2023
2 parents 4e51901 + ca558cc commit c38a957
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 10 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Release Notes

List of the most important changes for each release.

## 0.6.18
- Prevent creation of Deleted and HardDeleted models during deserialization to allow propagation of syncable objects that are recreated after a previous deletion without causing a merge conflict.

## 0.6.17
- Added `client-instance-id`, `server-instance-id`, `sync-filter`, `push` and `pull` arguments to `cleanupsyncs` management command
- Added option for resuming a sync to ignore the `SyncSession`'s existing `process_id`
Expand Down
2 changes: 1 addition & 1 deletion morango/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
from __future__ import unicode_literals

default_app_config = "morango.apps.MorangoConfig"
__version__ = "0.6.17"
__version__ = "0.6.18"
15 changes: 8 additions & 7 deletions morango/models/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from django.db.models import Func
from django.db.models import Max
from django.db.models import Q
from django.db.models import signals
from django.db.models import TextField
from django.db.models import Value
from django.db.models.deletion import Collector
Expand Down Expand Up @@ -468,13 +469,13 @@ def _deserialize_store_model(self, fk_cache, defer_fks=False): # noqa: C901
klass_model = syncable_models.get_model(self.profile, self.model_name)
# if store model marked as deleted, attempt to delete in app layer
if self.deleted:
# if hard deleted, propagate to related models
if self.hard_deleted:
try:
klass_model.objects.get(id=self.id).delete(hard_delete=True)
except klass_model.DoesNotExist:
pass
else:
# Don't differentiate between deletion and hard deletion here,
# as we don't want to add additional tracking for models in either case,
# just to actually delete them.
# Import here to avoid circular import, as the utils module
# imports core models.
from morango.sync.utils import mute_signals
with mute_signals(signals.post_delete):
klass_model.objects.filter(id=self.id).delete()
return None, deferred_fks
else:
Expand Down
43 changes: 43 additions & 0 deletions tests/testapp/tests/integration/test_syncsession.py
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,46 @@ def test_resume(self):
with second_environment():
self.assertEqual(5, SummaryLog.objects.filter(user=self.remote_user).count())
self.assertEqual(5, InteractionLog.objects.filter(user=self.remote_user).count())

def test_create_sync_delete_sync_recreate_sync(self):
with second_environment():
SummaryLog.objects.create(user=self.remote_user)
summ_log = SummaryLog.objects.first()
summ_log_id = summ_log.id
content_id = summ_log.content_id

self.assertEqual(0, SummaryLog.objects.filter(id=summ_log_id).count())

# first pull
pull_client = self.client.get_pull_client()
pull_client.initialize(self.filter)
transfer_session = pull_client.context.transfer_session
self.assertEqual(1, transfer_session.records_total)
self.assertEqual(0, transfer_session.records_transferred)
pull_client.run()
self.assertEqual(1, transfer_session.records_transferred)
pull_client.finalize()

# sanity check pull worked
self.assertEqual(1, SummaryLog.objects.filter(id=summ_log_id).count())

with second_environment():
SummaryLog.objects.get(id=summ_log_id).delete()

# now do another pull, which should pull in the deletion
second_pull_client = self.client.get_pull_client()
second_pull_client.initialize(self.filter)
second_pull_client.run()
second_pull_client.finalize()
self.assertEqual(0, SummaryLog.objects.filter(id=summ_log_id).count())

with second_environment():
sum_log = SummaryLog.objects.create(user=self.remote_user, content_id=content_id)
self.assertEqual(sum_log.id, summ_log_id)

# now do another pull, which should pull in the recreation
third_pull_client = self.client.get_pull_client()
third_pull_client.initialize(self.filter)
third_pull_client.run()
third_pull_client.finalize()
self.assertEqual(1, SummaryLog.objects.filter(id=summ_log_id).count())
3 changes: 1 addition & 2 deletions tests/testapp/tests/sync/test_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
from morango.constants import transfer_statuses
from morango.models.certificates import Filter
from morango.models.core import DeletedModels
from morango.models.core import HardDeletedModels
from morango.models.core import InstanceIDModel
from morango.models.core import RecordMaxCounter
from morango.models.core import Store
Expand Down Expand Up @@ -287,7 +286,7 @@ def test_store_hard_delete_propagates(self):
)
# make sure hard_deleted propagates to related models even if they are not hard_deleted
self.mc.deserialize_from_store()
self.assertTrue(HardDeletedModels.objects.filter(id=log.id).exists())
self.assertFalse(SummaryLog.objects.filter(id=log.id).exists())


class RecordMaxCounterUpdatesDuringSerialization(TestCase):
Expand Down

0 comments on commit c38a957

Please sign in to comment.