Skip to content

Commit

Permalink
Merge pull request #81 from cloudblue/LITE-24012-documentation
Browse files Browse the repository at this point in the history
Added metadata documentation
  • Loading branch information
maxipavlovic authored Jun 23, 2022
2 parents 5df6c13 + 2c2d8f0 commit d23f947
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 18 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,11 @@ class AuthorRef(ReplicaMixin, models.Model):
CQRS_CUSTOM_SERIALIZATION = True

@classmethod
def cqrs_create(cls, sync, **mapped_data):
def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
# Override here
pass

def cqrs_update(self, sync, **mapped_data):
def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
# Override here
pass
```
Expand Down
6 changes: 3 additions & 3 deletions docs/custom_serialization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@ yourself deserialization for the replica model.
class MyReplicaModel(ReplicaMixin):
CQRS_ID = 'my_model'
CQRS_CUSTOM_SERIALIZATION = True # bypass default deserialization.
@classmethod
def cqrs_create(cls, sync, mapped_data, previous_data=None):
def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
# Custom deserialization logic here
pass
def cqrs_update(self, sync, mapped_data, previous_data=None):
def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
# Custom deserialization logic here
pass
Expand Down
66 changes: 65 additions & 1 deletion docs/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ to the model, you must create a new migration for it:
Run your django application
---------------------------


.. code-block:: shell
$ ./manage.py runserver
Expand Down Expand Up @@ -181,3 +180,68 @@ And that's all!

Now every time you modify your master model, changes are replicated to
all services that have a replica model with the same CQRS_ID.

Use of customized meta data
===========================

The library allow us to send customized metadata from the Master models to the Replica ones.

Configuring the metadata for Master model
-----------------------------------------

There are two ways to specify what we want to include in this metadata, overriding the master function or setting a default generic function that will be executed for all masters.


Override master function
^^^^^^^^^^^^^^^^^^^^^^^^

Inside the Master model class you have to add the **get_cqrs_meta** function that will replace the default one (that returns an empty dict). For instance if you want to return the access of a given model instance inside the metadata you could do the following:

.. code-block:: python
def get_cqrs_meta(self, **kwargs):
meta = super().get_cqrs_meta(**kwargs)
if self.is_owner():
meta['access']['owner'] = True
meta['access']['others'] = False
else:
meta['access']['owner'] = False
meta['access']['others'] = True
return meta
Setting a default generic function
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

In the django settings you could configure a function that will be executed everytime an event is emitted in any Master:

.. code-block:: python
from ... import get_cqrs_meta
CQRS = {
...
'master': {
...
'meta_function': get_cqrs_meta,
},
}
Retrieving the metadata from the Replica model
----------------------------------------------

From the replica model you will now receive an additional parameter called **meta** that will contain all metadata set in the Master model. These data will be present in the following class functions:
* cqrs_update
* cqrs_create
* cqrs_delete

For instance replacing the **cqrs_update** we could do something like:

.. code-block:: python
def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
if meta and not meta['access']['owner']:
# Call asynchronously external system to update some resource.
else:
# Call asynchronously internal system to update some resource.
return super().cqrs_update(sync, mapped_data, previous_data, meta)
4 changes: 2 additions & 2 deletions docs/lifecycle.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ Message assumed as failed when a consumer raises an exception or returns negativ
...
@classmethod
def cqrs_create(cls, sync, mapped_data, previous_data=None):
def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
raise Exception("Some issue during create") # exception could be caught at should_retry_cqrs() method
def cqrs_update(self, sync, mapped_data, previous_data=None):
def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
return None # returning negative boolean for retrying
Retrying
Expand Down
8 changes: 4 additions & 4 deletions examples/demo_project/replica_service/app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def _handle_product_type(mapped_data):
return product_type

@classmethod
def cqrs_create(cls, sync, mapped_data, previous_data=None):
def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
product_type = cls._handle_product_type(mapped_data['product_type'])
return Product.objects.create(
id=mapped_data['id'],
Expand All @@ -46,7 +46,7 @@ def cqrs_create(cls, sync, mapped_data, previous_data=None):
cqrs_updated=mapped_data['cqrs_updated'],
)

def cqrs_update(self, sync, mapped_data, previous_data=None):
def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
product_type = self._handle_product_type(mapped_data['product_type'])
self.name = mapped_data['name']
self.product_type_id = product_type.id
Expand All @@ -68,11 +68,11 @@ class Meta:
abstract = True

@classmethod
def cqrs_save(cls, master_data, previous_data=None, sync=False):
def cqrs_save(cls, master_data, previous_data=None, sync=False, meta=None):
cache.set('purchase_' + str(master_data['id']), master_data)
return True

@classmethod
def cqrs_delete(cls, master_data):
def cqrs_delete(cls, master_data, meta=None):
cache.delete('purchase_' + str(master_data['id']))
return True
3 changes: 2 additions & 1 deletion requirements/docs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ Sphinx==3.1.2
sphinx-rtd-theme==0.4.3
sphinx-copybutton==0.2.11
setuptools-scm==3.5.0
docutils==0.17.1
docutils==0.17.1
Jinja2<3.1
10 changes: 5 additions & 5 deletions tests/dj_replica/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ class AuthorRef(ReplicaMixin, models.Model):
publisher = models.ForeignKey(Publisher, null=True, on_delete=models.CASCADE)

@classmethod
def cqrs_create(cls, sync, mapped_data, previous_data=None):
def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
publisher_data, publisher = mapped_data.pop('publisher', None), None
if publisher_data:
publisher, _ = Publisher.objects.get_or_create(**publisher_data)
Expand All @@ -101,7 +101,7 @@ def cqrs_create(cls, sync, mapped_data, previous_data=None):
Book.objects.bulk_create(Book(author=author, **book_data) for book_data in books_data)
return author

def cqrs_update(self, sync, mapped_data, previous_data=None):
def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
# It's just an example, that doesn't make sense in real cases
publisher_data, publisher = mapped_data.pop('publisher', None), None
if publisher_data:
Expand Down Expand Up @@ -131,7 +131,7 @@ class Article(ReplicaMixin):
author = models.ForeignKey(AuthorRef, on_delete=models.CASCADE)

@classmethod
def cqrs_create(cls, sync, mapped_data, previous_data=None):
def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
data = {
'id': mapped_data['id'],
'author_id': mapped_data['author']['id'],
Expand All @@ -156,8 +156,8 @@ class CQRSMetaModel(ReplicaMixin):
id = models.IntegerField(primary_key=True)

@classmethod
def cqrs_create(cls, sync, mapped_data, **kwargs):
return kwargs['meta']
def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
return meta

def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
return sync, mapped_data, previous_data, meta
Expand Down

0 comments on commit d23f947

Please sign in to comment.