models.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. # Copyright © 2023 Ingram Micro Inc. All rights reserved.
  2. from django.db import DatabaseError, models
  3. from dj_cqrs.metas import ReplicaMeta
  4. from dj_cqrs.mixins import RawReplicaMixin, ReplicaMixin
  5. class BasicFieldsModelRef(ReplicaMixin, models.Model):
  6. CQRS_ID = 'basic'
  7. int_field = models.IntegerField(primary_key=True)
  8. char_field = models.CharField(max_length=200)
  9. bool_field = models.BooleanField(null=True)
  10. date_field = models.DateField(null=True)
  11. datetime_field = models.DateTimeField(null=True)
  12. float_field = models.FloatField(null=True)
  13. url_field = models.URLField(null=True)
  14. uuid_field = models.UUIDField(null=True)
  15. class BadTypeModelRef(ReplicaMixin, models.Model):
  16. CQRS_ID = 'basic_1'
  17. int_field = models.IntegerField(primary_key=True)
  18. datetime_field = models.BooleanField(null=True)
  19. class MappedFieldsModelRef(ReplicaMixin, models.Model):
  20. CQRS_ID = 'basic_2'
  21. CQRS_MAPPING = {
  22. 'int_field': 'id',
  23. 'char_field': 'name',
  24. }
  25. id = models.IntegerField(primary_key=True)
  26. name = models.CharField(max_length=200)
  27. class BadMappingModelRef(ReplicaMixin, models.Model):
  28. CQRS_ID = 'basic_3'
  29. CQRS_MAPPING = {
  30. 'int_field': 'id',
  31. 'invalid_field': 'name',
  32. }
  33. id = models.IntegerField(primary_key=True)
  34. name = models.CharField(max_length=200)
  35. class LockModelRef(ReplicaMixin, models.Model):
  36. CQRS_ID = 'lock'
  37. CQRS_SELECT_FOR_UPDATE = True
  38. CQRS_META = True
  39. id = models.IntegerField(primary_key=True)
  40. class NoDBModelRef(ReplicaMixin):
  41. CQRS_ID = 'no_db'
  42. CQRS_NO_DB_OPERATIONS = True
  43. id = models.IntegerField(primary_key=True)
  44. class Meta:
  45. abstract = True
  46. class Event(models.Model):
  47. pid = models.IntegerField()
  48. cqrs_id = models.CharField(max_length=20)
  49. cqrs_revision = models.IntegerField()
  50. time = models.DateTimeField(auto_now_add=True)
  51. class Publisher(models.Model):
  52. id = models.IntegerField(primary_key=True)
  53. name = models.CharField(max_length=20)
  54. class AuthorRef(ReplicaMixin, models.Model):
  55. CQRS_ID = 'author'
  56. CQRS_CUSTOM_SERIALIZATION = True
  57. id = models.IntegerField(primary_key=True)
  58. name = models.CharField(max_length=20)
  59. publisher = models.ForeignKey(Publisher, null=True, on_delete=models.CASCADE)
  60. @classmethod
  61. def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
  62. publisher_data, publisher = mapped_data.pop('publisher', None), None
  63. if publisher_data:
  64. publisher, _ = Publisher.objects.get_or_create(**publisher_data)
  65. books_data = mapped_data.pop('books', [])
  66. author = cls.objects.create(publisher=publisher, **mapped_data)
  67. Book.objects.bulk_create(Book(author=author, **book_data) for book_data in books_data)
  68. return author
  69. def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
  70. # It's just an example, that doesn't make sense in real cases
  71. publisher_data, publisher = mapped_data.pop('publisher', None), None
  72. if publisher_data:
  73. publisher, _ = Publisher.objects.get_or_create(**publisher_data)
  74. self.publisher = publisher
  75. self.name = mapped_data.get('name', self.name)
  76. self.cqrs_revision = mapped_data['cqrs_revision']
  77. self.cqrs_updated = mapped_data['cqrs_updated']
  78. self.save()
  79. return self
  80. class Book(models.Model):
  81. id = models.IntegerField(primary_key=True)
  82. name = models.CharField(max_length=20)
  83. author = models.ForeignKey(AuthorRef, on_delete=models.CASCADE)
  84. class Article(ReplicaMixin):
  85. CQRS_ID = 'article'
  86. id = models.IntegerField(primary_key=True)
  87. author = models.ForeignKey(AuthorRef, on_delete=models.CASCADE)
  88. @classmethod
  89. def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
  90. data = {
  91. 'id': mapped_data['id'],
  92. 'author_id': mapped_data['author']['id'],
  93. 'cqrs_revision': mapped_data['cqrs_revision'],
  94. 'cqrs_updated': mapped_data['cqrs_updated'],
  95. }
  96. return super().cqrs_create(sync, data, previous_data)
  97. class FailModel(ReplicaMixin):
  98. CQRS_ID = 'fail'
  99. @classmethod
  100. def cqrs_save(cls, *args, **kwargs):
  101. raise Exception('Test fail Exception')
  102. class OnlyDirectSyncModel(ReplicaMixin):
  103. CQRS_ID = 'only_direct_sync'
  104. CQRS_ONLY_DIRECT_SYNCS = True
  105. class AbstractModel(ReplicaMixin):
  106. CQRS_ID = 'abstract'
  107. class Meta:
  108. abstract = True
  109. @classmethod
  110. def cqrs_save(
  111. cls,
  112. master_data: dict,
  113. previous_data: dict = None,
  114. sync: bool = False,
  115. meta: dict = None,
  116. ):
  117. raise DatabaseError
  118. class CQRSMetaModel(ReplicaMixin):
  119. CQRS_ID = 'meta'
  120. CQRS_META = True
  121. id = models.IntegerField(primary_key=True)
  122. @classmethod
  123. def cqrs_create(cls, sync, mapped_data, previous_data=None, meta=None):
  124. return meta
  125. def cqrs_update(self, sync, mapped_data, previous_data=None, meta=None):
  126. return sync, mapped_data, previous_data, meta
  127. @classmethod
  128. def cqrs_delete(cls, master_data, meta=None):
  129. super().cqrs_delete(master_data, meta)
  130. return meta
  131. for cqrs_id in ('document1', 'document2'):
  132. class DocCls(RawReplicaMixin):
  133. CQRS_ID = cqrs_id
  134. CQRS_META = True
  135. @classmethod
  136. def cqrs_save(cls, master_data, **kwargs):
  137. return cls.CQRS_ID, master_data, kwargs
  138. @classmethod
  139. def cqrs_delete(cls, master_data, **kwargs):
  140. return cls.CQRS_ID, master_data, kwargs
  141. ReplicaMeta.register(DocCls)