Skip to content

Commit 3960350

Browse files
committed
LITE-31232 Units for bulk_relate_cqrs_serialization
1 parent 49c84fa commit 3960350

File tree

2 files changed

+146
-13
lines changed

2 files changed

+146
-13
lines changed

dj_cqrs/utils.py

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,19 @@ def apply_query_timeouts(model_cls): # pragma: no cover
8888
class _BulkRelateCM(ContextDecorator):
8989
def __init__(self, cqrs_id=None):
9090
self._cqrs_id = cqrs_id
91-
self._mapping = defaultdict(lambda: defaultdict(list))
91+
self._mapping = defaultdict(lambda: defaultdict(set))
9292
self._cache = {}
9393

94-
def register(self, instance, using):
94+
def register(self, instance, using=None):
9595
instance_cqrs_id = getattr(instance, 'CQRS_ID', None)
96-
if self._cqrs_id and instance_cqrs_id != self._cqrs_id:
96+
if (not instance_cqrs_id) or (self._cqrs_id and instance_cqrs_id != self._cqrs_id):
9797
return
9898

99-
self._mapping[instance_cqrs_id][using].append(instance.pk)
99+
self._mapping[instance_cqrs_id][using].add(instance.pk)
100100

101-
def get_cached_instance(self, instance, using):
101+
def get_cached_instance(self, instance, using=None):
102102
instance_cqrs_id = getattr(instance, 'CQRS_ID', None)
103-
if self._cqrs_id and instance_cqrs_id != self._cqrs_id:
103+
if (not instance_cqrs_id) or (self._cqrs_id and instance_cqrs_id != self._cqrs_id):
104104
return
105105

106106
instance_pk = instance.pk
@@ -115,15 +115,20 @@ def get_cached_instance(self, instance, using):
115115
qs = instance.__class__._default_manager.using(using)
116116
instances_cache = {
117117
instance.pk: instance
118-
for instance in instance.__class__.relate_cqrs_serialization(qs).filter(
118+
for instance in instance.__class__.relate_cqrs_serialization(qs)
119+
.filter(
119120
pk__in=cached_pks,
120-
).order_by().all()
121+
)
122+
.order_by()
123+
.all()
121124
}
122-
self._cache.update({
123-
instance_cqrs_id: {
124-
using: instances_cache,
125-
},
126-
})
125+
self._cache.update(
126+
{
127+
instance_cqrs_id: {
128+
using: instances_cache,
129+
},
130+
}
131+
)
127132
return instances_cache.get(instance_pk)
128133

129134
def __enter__(self):

tests/test_utils.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,18 @@
1010
from uuid import UUID
1111

1212
import pytest
13+
from django.db import transaction
1314

15+
from dj_cqrs.state import cqrs_state
1416
from dj_cqrs.utils import (
1517
apply_query_timeouts,
18+
bulk_relate_cqrs_serialization,
1619
get_delay_queue_max_size,
1720
get_json_valid_value,
1821
get_message_expiration_dt,
1922
get_messages_prefetch_count_per_worker,
2023
)
24+
from tests.dj_master import models as master_models
2125
from tests.dj_replica import models
2226

2327

@@ -109,3 +113,127 @@ def test_apply_query_timeouts(settings, engine, p_count):
109113
assert apply_query_timeouts(models.BasicFieldsModelRef) is None
110114

111115
assert p.call_count == p_count
116+
117+
118+
@pytest.mark.django_db(transaction=True)
119+
def test_bulk_relate_cqrs_serialization_simple_model(mocker):
120+
produce_mock = mocker.patch('dj_cqrs.controller.producer.produce')
121+
122+
@bulk_relate_cqrs_serialization()
123+
def func():
124+
assert cqrs_state.bulk_relate_cm
125+
126+
instance = master_models.SimplestModel(id=1)
127+
instance.save()
128+
129+
assert cqrs_state.bulk_relate_cm is None
130+
func()
131+
132+
assert master_models.SimplestModel.objects.count() == 1
133+
assert produce_mock.call_count == 1
134+
assert cqrs_state.bulk_relate_cm is None
135+
136+
137+
@pytest.mark.django_db(transaction=True)
138+
def test_bulk_relate_cqrs_serialization_serialized_model(mocker):
139+
produce_mock = mocker.patch('dj_cqrs.controller.producer.produce')
140+
141+
assert cqrs_state.bulk_relate_cm is None
142+
with bulk_relate_cqrs_serialization(cqrs_id=master_models.Author.CQRS_ID):
143+
bulk_relate_cm = cqrs_state.bulk_relate_cm
144+
145+
with transaction.atomic(savepoint=False):
146+
master_models.Author.objects.create(id=1)
147+
148+
assert bulk_relate_cm
149+
assert bulk_relate_cm._mapping
150+
assert not bulk_relate_cm._cache
151+
152+
assert bulk_relate_cm._cache
153+
154+
assert master_models.Author.objects.count() == 1
155+
assert produce_mock.call_count == 1
156+
assert cqrs_state.bulk_relate_cm is None
157+
158+
159+
def test_bulk_relate_cqrs_serialization_error():
160+
assert cqrs_state.bulk_relate_cm is None
161+
162+
try:
163+
with bulk_relate_cqrs_serialization(cqrs_id=master_models.Author.CQRS_ID):
164+
assert cqrs_state.bulk_relate_cm
165+
raise ValueError
166+
except ValueError:
167+
pass
168+
169+
assert cqrs_state.bulk_relate_cm is None
170+
171+
172+
@pytest.mark.django_db(transaction=True)
173+
def test_bulk_relate_cqrs_serialization_register():
174+
author1 = master_models.Author(id=1)
175+
author2 = master_models.Author(id=2)
176+
177+
with bulk_relate_cqrs_serialization(cqrs_id=master_models.Author.CQRS_ID):
178+
bulk_relate_cm = cqrs_state.bulk_relate_cm
179+
bulk_relate_cm.register(ValueError)
180+
bulk_relate_cm.register(master_models.FilteredSimplestModel())
181+
bulk_relate_cm.register(author1, 'default')
182+
bulk_relate_cm.register(author1, 'default')
183+
bulk_relate_cm.register(author1, 'other')
184+
bulk_relate_cm.register(author2, 'other')
185+
bulk_relate_cm.register(author2)
186+
187+
assert bulk_relate_cm._mapping == {
188+
master_models.Author.CQRS_ID: {
189+
'default': {1},
190+
'other': {1, 2},
191+
None: {2},
192+
},
193+
}
194+
195+
assert cqrs_state.bulk_relate_cm is None
196+
197+
198+
@pytest.mark.django_db(transaction=True)
199+
def test_bulk_relate_cqrs_serialization_get_cached_instance(mocker, django_assert_num_queries):
200+
produce_mock = mocker.patch('dj_cqrs.controller.producer.produce')
201+
202+
simple = master_models.SimplestModel.objects.create(id=1)
203+
204+
with bulk_relate_cqrs_serialization():
205+
bulk_relate_cm = cqrs_state.bulk_relate_cm
206+
207+
with transaction.atomic():
208+
author1 = master_models.Author.objects.create(id=1)
209+
author1.name = 'new'
210+
author1.save()
211+
author2 = master_models.Author.objects.create(id=2)
212+
213+
af = master_models.AutoFieldsModel.objects.using('default').create()
214+
publisher = master_models.Publisher.objects.create(id=3)
215+
216+
assert produce_mock.call_count == 4
217+
assert bulk_relate_cm._cache == {
218+
master_models.Author.CQRS_ID: {
219+
'default': {
220+
1: author1,
221+
2: author2,
222+
},
223+
},
224+
}
225+
226+
assert bulk_relate_cm.get_cached_instance(publisher) is None
227+
assert bulk_relate_cm.get_cached_instance(ValueError, 'test') is None
228+
229+
with django_assert_num_queries(0):
230+
assert bulk_relate_cm.get_cached_instance(simple) is None
231+
assert bulk_relate_cm.get_cached_instance(author1, 'default') == author1
232+
assert bulk_relate_cm.get_cached_instance(author1, 'default') == author1
233+
assert bulk_relate_cm.get_cached_instance(author1, 'other') is None
234+
assert bulk_relate_cm.get_cached_instance(author2, 'default') == author2
235+
assert bulk_relate_cm.get_cached_instance(author2) is None
236+
assert bulk_relate_cm.get_cached_instance(master_models.Author(id=3)) is None
237+
assert bulk_relate_cm.get_cached_instance(af) is None
238+
239+
assert cqrs_state.bulk_relate_cm is None

0 commit comments

Comments
 (0)