hexkit 3.1.0__tar.gz → 3.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. {hexkit-3.1.0/src/hexkit.egg-info → hexkit-3.2.0}/PKG-INFO +1 -1
  2. {hexkit-3.1.0 → hexkit-3.2.0}/pyproject.toml +1 -1
  3. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/protocols/daopub.py +3 -2
  4. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/mongokafka/provider.py +43 -18
  5. {hexkit-3.1.0 → hexkit-3.2.0/src/hexkit.egg-info}/PKG-INFO +1 -1
  6. {hexkit-3.1.0 → hexkit-3.2.0}/LICENSE +0 -0
  7. {hexkit-3.1.0 → hexkit-3.2.0}/MANIFEST.in +0 -0
  8. {hexkit-3.1.0 → hexkit-3.2.0}/README.md +0 -0
  9. {hexkit-3.1.0 → hexkit-3.2.0}/setup.cfg +0 -0
  10. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/__init__.py +0 -0
  11. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/__main__.py +0 -0
  12. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/base.py +0 -0
  13. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/config.py +0 -0
  14. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/correlation.py +0 -0
  15. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/custom_types.py +0 -0
  16. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/log.py +0 -0
  17. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/protocols/__init__.py +0 -0
  18. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/protocols/dao.py +0 -0
  19. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/protocols/daosub.py +0 -0
  20. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/protocols/eventpub.py +0 -0
  21. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/protocols/eventsub.py +0 -0
  22. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/protocols/objstorage.py +0 -0
  23. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/__init__.py +0 -0
  24. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/__init__.py +0 -0
  25. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/config.py +0 -0
  26. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/provider/__init__.py +0 -0
  27. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/provider/daosub.py +0 -0
  28. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/provider/eventpub.py +0 -0
  29. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/provider/eventsub.py +0 -0
  30. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/provider/utils.py +0 -0
  31. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/testcontainer.py +0 -0
  32. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/akafka/testutils.py +0 -0
  33. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/mongodb/__init__.py +0 -0
  34. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/mongodb/provider.py +0 -0
  35. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/mongodb/testutils.py +0 -0
  36. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/mongokafka/__init__.py +0 -0
  37. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/mongokafka/testutils.py +0 -0
  38. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/s3/__init__.py +0 -0
  39. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/s3/provider.py +0 -0
  40. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/s3/test_files/__init__.py +0 -0
  41. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/s3/test_files/test_file1.yaml +0 -0
  42. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/s3/test_files/test_file2.yaml +0 -0
  43. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/s3/test_files/test_file3.yaml +0 -0
  44. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/s3/test_files/test_file4.yaml +0 -0
  45. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/s3/testutils.py +0 -0
  46. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/testing/__init__.py +0 -0
  47. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/providers/testing/eventpub.py +0 -0
  48. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/py.typed +0 -0
  49. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit/utils.py +0 -0
  50. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit.egg-info/SOURCES.txt +0 -0
  51. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit.egg-info/dependency_links.txt +0 -0
  52. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit.egg-info/requires.txt +0 -0
  53. {hexkit-3.1.0 → hexkit-3.2.0}/src/hexkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hexkit
3
- Version: 3.1.0
3
+ Version: 3.2.0
4
4
  Summary: A Toolkit for Building Microservices using the Hexagonal Architecture
5
5
  Author-email: "German Human Genome Phenome Archive (GHGA)" <contact@ghga.de>
6
6
  License: Apache 2.0
@@ -23,7 +23,7 @@ classifiers = [
23
23
  "Intended Audience :: Developers",
24
24
  ]
25
25
  name = "hexkit"
26
- version = "3.1.0"
26
+ version = "3.2.0"
27
27
  description = "A Toolkit for Building Microservices using the Hexagonal Architecture"
28
28
  dependencies = [
29
29
  "pydantic >=2, <3",
@@ -62,7 +62,7 @@ class DaoPublisherFactoryProtocol(DaoFactoryBase, ABC):
62
62
  dto_model: type[Dto],
63
63
  id_field: str,
64
64
  fields_to_index: Optional[Collection[str]] = None,
65
- dto_to_event: Callable[[Dto], JsonObject],
65
+ dto_to_event: Callable[[Dto], Optional[JsonObject]],
66
66
  event_topic: str,
67
67
  autopublish: bool = True,
68
68
  ) -> DaoPublisher[Dto]:
@@ -82,6 +82,7 @@ class DaoPublisherFactoryProtocol(DaoFactoryBase, ABC):
82
82
  `id_field`. Defaults to None.
83
83
  dto_to_event:
84
84
  A function that takes a DTO and returns the payload for an event.
85
+ If the returned payload is None, the event will not be published.
85
86
  event_topic:
86
87
  The topic to which events should be published.
87
88
  autopublish:
@@ -120,7 +121,7 @@ class DaoPublisherFactoryProtocol(DaoFactoryBase, ABC):
120
121
  dto_model: type[Dto],
121
122
  id_field: str,
122
123
  fields_to_index: Optional[Collection[str]],
123
- dto_to_event: Callable[[Dto], JsonObject],
124
+ dto_to_event: Callable[[Dto], Optional[JsonObject]],
124
125
  event_topic: str,
125
126
  autopublish: bool,
126
127
  ) -> DaoPublisher[Dto]:
@@ -28,6 +28,7 @@ from aiokafka import AIOKafkaProducer
28
28
  from motor.core import AgnosticCollection
29
29
  from motor.motor_asyncio import AsyncIOMotorClient
30
30
 
31
+ from hexkit.correlation import get_correlation_id, set_correlation_id
31
32
  from hexkit.custom_types import JsonObject
32
33
  from hexkit.protocols.dao import (
33
34
  DaoNaturalId,
@@ -86,7 +87,13 @@ def dto_to_document(
86
87
  """
87
88
  document = json.loads(dto.model_dump_json())
88
89
  document["_id"] = document.pop(id_field)
89
- document["__metadata__"] = {"deleted": False, "published": published}
90
+
91
+ correlation_id = get_correlation_id()
92
+ document["__metadata__"] = {
93
+ "deleted": False,
94
+ "published": published,
95
+ "correlation_id": correlation_id,
96
+ }
90
97
 
91
98
  return document
92
99
 
@@ -94,7 +101,7 @@ def dto_to_document(
94
101
  def get_change_publish_func(
95
102
  id_field: str,
96
103
  event_topic: str,
97
- dto_to_event: Callable[[Dto], JsonObject],
104
+ dto_to_event: Callable[[Dto], Optional[JsonObject]],
98
105
  event_publisher: EventPublisherProtocol,
99
106
  collection: AgnosticCollection,
100
107
  ) -> Callable[[Dto], Awaitable[None]]:
@@ -103,12 +110,13 @@ def get_change_publish_func(
103
110
  async def publish_change(dto: Dto) -> None:
104
111
  """Publishes a change event and marks the change as published."""
105
112
  payload = dto_to_event(dto)
106
- await event_publisher.publish(
107
- payload=payload,
108
- type_=CHANGE_EVENT_TYPE,
109
- key=getattr(dto, id_field),
110
- topic=event_topic,
111
- )
113
+ if payload is not None:
114
+ await event_publisher.publish(
115
+ payload=payload,
116
+ type_=CHANGE_EVENT_TYPE,
117
+ key=getattr(dto, id_field),
118
+ topic=event_topic,
119
+ )
112
120
 
113
121
  document = dto_to_document(dto, id_field=id_field, published=True)
114
122
  await collection.replace_one({"_id": document["_id"]}, document, upsert=True)
@@ -134,7 +142,15 @@ def get_delete_publish_func(
134
142
  topic=event_topic,
135
143
  )
136
144
 
137
- document = {"_id": id_, "__metadata__": {"deleted": True, "published": True}}
145
+ correlation_id = get_correlation_id() # Get active correlation first
146
+ document = {
147
+ "_id": id_,
148
+ "__metadata__": {
149
+ "deleted": True,
150
+ "published": True,
151
+ "correlation_id": correlation_id,
152
+ },
153
+ }
138
154
  await collection.replace_one({"_id": document["_id"]}, document)
139
155
 
140
156
  return publish_deletion
@@ -233,7 +249,9 @@ class MongoKafkaDaoPublisher(Generic[Dto]):
233
249
  ResourceNotFoundError:
234
250
  when resource with the id specified in the dto was not found
235
251
  """
252
+ correlation_id = get_correlation_id()
236
253
  document = self._dao._dto_to_document(dto)
254
+ document["__metadata__.correlation_id"] = correlation_id
237
255
  result = await self._collection.replace_one(
238
256
  {"_id": document["_id"], "__metadata__.deleted": False}, document
239
257
  )
@@ -252,9 +270,14 @@ class MongoKafkaDaoPublisher(Generic[Dto]):
252
270
  Raises:
253
271
  ResourceNotFoundError: when resource with the specified id_ was not found
254
272
  """
273
+ correlation_id = get_correlation_id()
255
274
  document = {
256
275
  "_id": id_,
257
- "__metadata__": {"deleted": True, "published": False},
276
+ "__metadata__": {
277
+ "deleted": True,
278
+ "published": False,
279
+ "correlation_id": correlation_id,
280
+ },
258
281
  }
259
282
  result = await self._collection.replace_one(
260
283
  {"_id": document["_id"], "__metadata__.deleted": False}, document
@@ -343,13 +366,15 @@ class MongoKafkaDaoPublisher(Generic[Dto]):
343
366
 
344
367
  async def publish_document(self, document: dict[str, Any]) -> None:
345
368
  """Publishes a document"""
346
- if document.get("__metadata__", {}).get("deleted", False):
347
- await self._publish_delete(document["_id"])
348
- else:
349
- dto = document_to_dto(
350
- document, id_field=self._id_field, dto_model=self._dto_model
351
- )
352
- await self._publish_change(dto)
369
+ correlation_id = document.get("__metadata__", {}).get("correlation_id", "")
370
+ async with set_correlation_id(correlation_id=correlation_id):
371
+ if document.get("__metadata__", {}).get("deleted", False):
372
+ await self._publish_delete(document["_id"])
373
+ else:
374
+ dto = document_to_dto(
375
+ document, id_field=self._id_field, dto_model=self._dto_model
376
+ )
377
+ await self._publish_change(dto)
353
378
 
354
379
  async def publish_pending(self) -> None:
355
380
  """Publishes all non-published changes."""
@@ -422,7 +447,7 @@ class MongoKafkaDaoPublisherFactory(DaoPublisherFactoryProtocol):
422
447
  dto_model: type[Dto],
423
448
  id_field: str,
424
449
  fields_to_index: Optional[Collection[str]],
425
- dto_to_event: Callable[[Dto], JsonObject],
450
+ dto_to_event: Callable[[Dto], Optional[JsonObject]],
426
451
  event_topic: str,
427
452
  autopublish: bool,
428
453
  ) -> DaoPublisher[Dto]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: hexkit
3
- Version: 3.1.0
3
+ Version: 3.2.0
4
4
  Summary: A Toolkit for Building Microservices using the Hexagonal Architecture
5
5
  Author-email: "German Human Genome Phenome Archive (GHGA)" <contact@ghga.de>
6
6
  License: Apache 2.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes