mersal 0.1.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 (286) hide show
  1. mersal-0.1.0/.gitignore +196 -0
  2. mersal-0.1.0/.pre-commit-config.yaml +53 -0
  3. mersal-0.1.0/.python-version +1 -0
  4. mersal-0.1.0/CONTRIBUTING.rst +0 -0
  5. mersal-0.1.0/Makefile +254 -0
  6. mersal-0.1.0/PKG-INFO +13 -0
  7. mersal-0.1.0/README.rst +4 -0
  8. mersal-0.1.0/core/README.md +3 -0
  9. mersal-0.1.0/core/src/mersal/__init__.py +1 -0
  10. mersal-0.1.0/core/src/mersal/_activation/builtin_handler_activator.py +102 -0
  11. mersal-0.1.0/core/src/mersal/_activation/handler_activator.py +78 -0
  12. mersal-0.1.0/core/src/mersal/activation/__init__.py +14 -0
  13. mersal-0.1.0/core/src/mersal/app.py +338 -0
  14. mersal-0.1.0/core/src/mersal/configuration/__init__.py +3 -0
  15. mersal-0.1.0/core/src/mersal/configuration/default_plugin.py +161 -0
  16. mersal-0.1.0/core/src/mersal/configuration/dependency_resolver.py +55 -0
  17. mersal-0.1.0/core/src/mersal/configuration/standard_configurator.py +67 -0
  18. mersal-0.1.0/core/src/mersal/exceptions/__init__.py +11 -0
  19. mersal-0.1.0/core/src/mersal/exceptions/base_exceptions.py +49 -0
  20. mersal-0.1.0/core/src/mersal/handlers/__init__.py +3 -0
  21. mersal-0.1.0/core/src/mersal/handlers/message_handler.py +6 -0
  22. mersal-0.1.0/core/src/mersal/idempotency/__init__.py +11 -0
  23. mersal-0.1.0/core/src/mersal/idempotency/config.py +25 -0
  24. mersal-0.1.0/core/src/mersal/idempotency/const.py +4 -0
  25. mersal-0.1.0/core/src/mersal/idempotency/idempotency_checker_step.py +38 -0
  26. mersal-0.1.0/core/src/mersal/idempotency/message_tracker.py +17 -0
  27. mersal-0.1.0/core/src/mersal/idempotency/plugin.py +35 -0
  28. mersal-0.1.0/core/src/mersal/lifespan/__init__.py +4 -0
  29. mersal-0.1.0/core/src/mersal/lifespan/autosubscribe/__init__.py +3 -0
  30. mersal-0.1.0/core/src/mersal/lifespan/autosubscribe/autosubscribe_plugin.py +54 -0
  31. mersal-0.1.0/core/src/mersal/lifespan/default_lifespan_handler.py +15 -0
  32. mersal-0.1.0/core/src/mersal/lifespan/lifespan_handler.py +15 -0
  33. mersal-0.1.0/core/src/mersal/lifespan/lifespan_hooks_registration_plugin.py +48 -0
  34. mersal-0.1.0/core/src/mersal/messages/__init__.py +7 -0
  35. mersal-0.1.0/core/src/mersal/messages/batch_message.py +8 -0
  36. mersal-0.1.0/core/src/mersal/messages/logical_message.py +18 -0
  37. mersal-0.1.0/core/src/mersal/messages/message_completed_event.py +9 -0
  38. mersal-0.1.0/core/src/mersal/messages/message_completed_event_publisher.py +31 -0
  39. mersal-0.1.0/core/src/mersal/messages/message_headers.py +27 -0
  40. mersal-0.1.0/core/src/mersal/messages/transport_message.py +18 -0
  41. mersal-0.1.0/core/src/mersal/outbox/__init__.py +12 -0
  42. mersal-0.1.0/core/src/mersal/outbox/config.py +13 -0
  43. mersal-0.1.0/core/src/mersal/outbox/in_memory/__init__.py +5 -0
  44. mersal-0.1.0/core/src/mersal/outbox/in_memory/in_memory_outbox_storage.py +44 -0
  45. mersal-0.1.0/core/src/mersal/outbox/outbox_forwarder.py +86 -0
  46. mersal-0.1.0/core/src/mersal/outbox/outbox_incoming_step.py +20 -0
  47. mersal-0.1.0/core/src/mersal/outbox/outbox_message.py +32 -0
  48. mersal-0.1.0/core/src/mersal/outbox/outbox_message_batch.py +33 -0
  49. mersal-0.1.0/core/src/mersal/outbox/outbox_storage.py +44 -0
  50. mersal-0.1.0/core/src/mersal/outbox/outbox_transport_decorator.py +54 -0
  51. mersal-0.1.0/core/src/mersal/outbox/plugin.py +77 -0
  52. mersal-0.1.0/core/src/mersal/persistence/in_memory/__init__.py +15 -0
  53. mersal-0.1.0/core/src/mersal/persistence/in_memory/in_memory_message_tracker.py +19 -0
  54. mersal-0.1.0/core/src/mersal/persistence/in_memory/in_memory_saga_storage.py +98 -0
  55. mersal-0.1.0/core/src/mersal/persistence/in_memory/in_memory_subscription_storage.py +58 -0
  56. mersal-0.1.0/core/src/mersal/persistence/not_implemented/__init__.py +3 -0
  57. mersal-0.1.0/core/src/mersal/persistence/not_implemented/not_implemented_subscription_storage.py +21 -0
  58. mersal-0.1.0/core/src/mersal/pipeline/__init__.py +42 -0
  59. mersal-0.1.0/core/src/mersal/pipeline/default_pipeline.py +41 -0
  60. mersal-0.1.0/core/src/mersal/pipeline/incoming_step.py +11 -0
  61. mersal-0.1.0/core/src/mersal/pipeline/incoming_step_context.py +20 -0
  62. mersal-0.1.0/core/src/mersal/pipeline/iterative_pipeline_invoker.py +44 -0
  63. mersal-0.1.0/core/src/mersal/pipeline/message_context.py +48 -0
  64. mersal-0.1.0/core/src/mersal/pipeline/outgoing_step.py +11 -0
  65. mersal-0.1.0/core/src/mersal/pipeline/outgoing_step_context.py +20 -0
  66. mersal-0.1.0/core/src/mersal/pipeline/pipeline.py +23 -0
  67. mersal-0.1.0/core/src/mersal/pipeline/pipeline_injector.py +68 -0
  68. mersal-0.1.0/core/src/mersal/pipeline/pipeline_invoker.py +10 -0
  69. mersal-0.1.0/core/src/mersal/pipeline/receive/activate_handlers_step.py +70 -0
  70. mersal-0.1.0/core/src/mersal/pipeline/receive/deserialize_incoming_message_step.py +21 -0
  71. mersal-0.1.0/core/src/mersal/pipeline/receive/dispatch_incoming_message_step.py +19 -0
  72. mersal-0.1.0/core/src/mersal/pipeline/receive/handler_invoker.py +32 -0
  73. mersal-0.1.0/core/src/mersal/pipeline/receive/handler_invokers.py +24 -0
  74. mersal-0.1.0/core/src/mersal/pipeline/receive/saga_handler_invoker.py +26 -0
  75. mersal-0.1.0/core/src/mersal/pipeline/recursive_pipeline_invoker.py +38 -0
  76. mersal-0.1.0/core/src/mersal/pipeline/send/destination_addresses.py +12 -0
  77. mersal-0.1.0/core/src/mersal/pipeline/send/flow_correlation_step.py +59 -0
  78. mersal-0.1.0/core/src/mersal/pipeline/send/send_outgoing_message_step.py +23 -0
  79. mersal-0.1.0/core/src/mersal/pipeline/send/serialize_outgoing_message_step.py +19 -0
  80. mersal-0.1.0/core/src/mersal/pipeline/send/set_default_headers_step.py +33 -0
  81. mersal-0.1.0/core/src/mersal/pipeline/step_context.py +27 -0
  82. mersal-0.1.0/core/src/mersal/plugins/__init__.py +7 -0
  83. mersal-0.1.0/core/src/mersal/plugins/generic_registration_plugin.py +13 -0
  84. mersal-0.1.0/core/src/mersal/plugins/plugin.py +9 -0
  85. mersal-0.1.0/core/src/mersal/py.typed +0 -0
  86. mersal-0.1.0/core/src/mersal/retry/__init__.py +27 -0
  87. mersal-0.1.0/core/src/mersal/retry/default_retry_step.py +91 -0
  88. mersal-0.1.0/core/src/mersal/retry/default_retry_strategy.py +29 -0
  89. mersal-0.1.0/core/src/mersal/retry/error_handling/deadletter_queue_error_handler.py +29 -0
  90. mersal-0.1.0/core/src/mersal/retry/error_handling/error_handler.py +15 -0
  91. mersal-0.1.0/core/src/mersal/retry/error_tracking/error_tracker.py +16 -0
  92. mersal-0.1.0/core/src/mersal/retry/error_tracking/in_memory_error_tracker.py +29 -0
  93. mersal-0.1.0/core/src/mersal/retry/fail_fast/default_fail_fast_checker.py +23 -0
  94. mersal-0.1.0/core/src/mersal/retry/fail_fast/fail_fast_checker.py +8 -0
  95. mersal-0.1.0/core/src/mersal/retry/retry_step.py +8 -0
  96. mersal-0.1.0/core/src/mersal/retry/retry_strategy.py +9 -0
  97. mersal-0.1.0/core/src/mersal/retry/retry_strategy_settings.py +9 -0
  98. mersal-0.1.0/core/src/mersal/routing/__init__.py +7 -0
  99. mersal-0.1.0/core/src/mersal/routing/default/__init__.py +9 -0
  100. mersal-0.1.0/core/src/mersal/routing/default/config.py +15 -0
  101. mersal-0.1.0/core/src/mersal/routing/default/default_router.py +32 -0
  102. mersal-0.1.0/core/src/mersal/routing/default/plugin.py +29 -0
  103. mersal-0.1.0/core/src/mersal/routing/router.py +9 -0
  104. mersal-0.1.0/core/src/mersal/sagas/__init__.py +13 -0
  105. mersal-0.1.0/core/src/mersal/sagas/config.py +17 -0
  106. mersal-0.1.0/core/src/mersal/sagas/correlation_error_handler.py +21 -0
  107. mersal-0.1.0/core/src/mersal/sagas/correlation_property.py +15 -0
  108. mersal-0.1.0/core/src/mersal/sagas/correlator.py +32 -0
  109. mersal-0.1.0/core/src/mersal/sagas/default_correlation_error_handler.py +29 -0
  110. mersal-0.1.0/core/src/mersal/sagas/load_saga_data_step.py +134 -0
  111. mersal-0.1.0/core/src/mersal/sagas/plugin.py +55 -0
  112. mersal-0.1.0/core/src/mersal/sagas/saga.py +61 -0
  113. mersal-0.1.0/core/src/mersal/sagas/saga_data.py +15 -0
  114. mersal-0.1.0/core/src/mersal/sagas/saga_storage.py +41 -0
  115. mersal-0.1.0/core/src/mersal/serialization/__init__.py +9 -0
  116. mersal-0.1.0/core/src/mersal/serialization/identity_serializer/__init__.py +3 -0
  117. mersal-0.1.0/core/src/mersal/serialization/identity_serializer/identity_object_serializer.py +13 -0
  118. mersal-0.1.0/core/src/mersal/serialization/message_serializer.py +17 -0
  119. mersal-0.1.0/core/src/mersal/serialization/serializers.py +13 -0
  120. mersal-0.1.0/core/src/mersal/subscription/__init__.py +3 -0
  121. mersal-0.1.0/core/src/mersal/subscription/subscription_storage.py +14 -0
  122. mersal-0.1.0/core/src/mersal/threading/__init__.py +13 -0
  123. mersal-0.1.0/core/src/mersal/threading/anyio/anyio_periodic_async_task.py +49 -0
  124. mersal-0.1.0/core/src/mersal/threading/anyio/anyio_periodic_async_task_factory.py +22 -0
  125. mersal-0.1.0/core/src/mersal/threading/periodic_async_task.py +9 -0
  126. mersal-0.1.0/core/src/mersal/threading/periodic_async_task_factory.py +11 -0
  127. mersal-0.1.0/core/src/mersal/topic/__init__.py +4 -0
  128. mersal-0.1.0/core/src/mersal/topic/default_topic_name_convention.py +6 -0
  129. mersal-0.1.0/core/src/mersal/topic/topic_name_convention.py +7 -0
  130. mersal-0.1.0/core/src/mersal/transport/__init__.py +19 -0
  131. mersal-0.1.0/core/src/mersal/transport/ambient_context.py +20 -0
  132. mersal-0.1.0/core/src/mersal/transport/base_transport.py +40 -0
  133. mersal-0.1.0/core/src/mersal/transport/default_transaction_context.py +158 -0
  134. mersal-0.1.0/core/src/mersal/transport/default_transaction_context_with_app.py +16 -0
  135. mersal-0.1.0/core/src/mersal/transport/in_memory/__init__.py +10 -0
  136. mersal-0.1.0/core/src/mersal/transport/in_memory/in_memory_network.py +32 -0
  137. mersal-0.1.0/core/src/mersal/transport/in_memory/in_memory_transport.py +60 -0
  138. mersal-0.1.0/core/src/mersal/transport/in_memory/in_memory_transport_plugin.py +49 -0
  139. mersal-0.1.0/core/src/mersal/transport/outgoing_message.py +15 -0
  140. mersal-0.1.0/core/src/mersal/transport/transaction_context.py +32 -0
  141. mersal-0.1.0/core/src/mersal/transport/transaction_scope.py +46 -0
  142. mersal-0.1.0/core/src/mersal/transport/transport.py +21 -0
  143. mersal-0.1.0/core/src/mersal/transport/transport_bridge.py +46 -0
  144. mersal-0.1.0/core/src/mersal/transport/transport_decorator_plugin.py +23 -0
  145. mersal-0.1.0/core/src/mersal/types/__init__.py +22 -0
  146. mersal-0.1.0/core/src/mersal/types/callable_types.py +13 -0
  147. mersal-0.1.0/core/src/mersal/types/helper_types.py +6 -0
  148. mersal-0.1.0/core/src/mersal/unit_of_work/__init__.py +17 -0
  149. mersal-0.1.0/core/src/mersal/unit_of_work/config.py +49 -0
  150. mersal-0.1.0/core/src/mersal/unit_of_work/plugin.py +37 -0
  151. mersal-0.1.0/core/src/mersal/unit_of_work/unit_of_work_step.py +86 -0
  152. mersal-0.1.0/core/src/mersal/utils/__init__.py +9 -0
  153. mersal-0.1.0/core/src/mersal/utils/predicates.py +28 -0
  154. mersal-0.1.0/core/src/mersal/utils/retrier.py +24 -0
  155. mersal-0.1.0/core/src/mersal/utils/singleton.py +17 -0
  156. mersal-0.1.0/core/src/mersal/utils/sync.py +73 -0
  157. mersal-0.1.0/core/src/mersal/workers/__init__.py +3 -0
  158. mersal-0.1.0/core/src/mersal/workers/anyio/__init__.py +4 -0
  159. mersal-0.1.0/core/src/mersal/workers/anyio/anyio_worker.py +117 -0
  160. mersal-0.1.0/core/src/mersal/workers/anyio/anyio_worker_factory.py +34 -0
  161. mersal-0.1.0/core/src/mersal/workers/worker.py +23 -0
  162. mersal-0.1.0/core/src/mersal/workers/worker_factory.py +16 -0
  163. mersal-0.1.0/core/testing/mersal_testing/_internal/conftest.py +70 -0
  164. mersal-0.1.0/core/testing/mersal_testing/_internal/docker-compose.yml +17 -0
  165. mersal-0.1.0/core/testing/mersal_testing/app_runner_helper.py +22 -0
  166. mersal-0.1.0/core/testing/mersal_testing/counter.py +41 -0
  167. mersal-0.1.0/core/testing/mersal_testing/message_handlers/__init__.py +9 -0
  168. mersal-0.1.0/core/testing/mersal_testing/message_handlers/message_handler_that_counts.py +14 -0
  169. mersal-0.1.0/core/testing/mersal_testing/message_handlers/message_handler_that_sends_local_messages.py +32 -0
  170. mersal-0.1.0/core/testing/mersal_testing/message_handlers/message_handler_that_stores_the_message.py +15 -0
  171. mersal-0.1.0/core/testing/mersal_testing/message_handlers/message_handler_that_throws.py +13 -0
  172. mersal-0.1.0/core/testing/mersal_testing/message_handlers/null_message_handler.py +10 -0
  173. mersal-0.1.0/core/testing/mersal_testing/messages.py +12 -0
  174. mersal-0.1.0/core/testing/mersal_testing/pipeline/pipeline_invoker_tests.py +137 -0
  175. mersal-0.1.0/core/testing/mersal_testing/py.typed +2 -0
  176. mersal-0.1.0/core/testing/mersal_testing/retry/error_tracker_base_tests.py +89 -0
  177. mersal-0.1.0/core/testing/mersal_testing/test_doubles/__init__.py +31 -0
  178. mersal-0.1.0/core/testing/mersal_testing/test_doubles/messages/__init__.py +0 -0
  179. mersal-0.1.0/core/testing/mersal_testing/test_doubles/messages/logical_message_builder.py +52 -0
  180. mersal-0.1.0/core/testing/mersal_testing/test_doubles/messages/transport_message_builder.py +19 -0
  181. mersal-0.1.0/core/testing/mersal_testing/test_doubles/outbox/outbox_storage_test_double.py +61 -0
  182. mersal-0.1.0/core/testing/mersal_testing/test_doubles/retry/error_handler_spy.py +20 -0
  183. mersal-0.1.0/core/testing/mersal_testing/test_doubles/retry/error_tracker_test_double.py +28 -0
  184. mersal-0.1.0/core/testing/mersal_testing/test_doubles/serialization/serializer_test_double.py +21 -0
  185. mersal-0.1.0/core/testing/mersal_testing/test_doubles/transport/outgoing_message_builder.py +10 -0
  186. mersal-0.1.0/core/testing/mersal_testing/test_doubles/transport/transaction_context_test_double.py +49 -0
  187. mersal-0.1.0/core/testing/mersal_testing/test_doubles/transport/transport_spy.py +26 -0
  188. mersal-0.1.0/core/testing/mersal_testing/test_doubles/transport/transport_test_double.py +25 -0
  189. mersal-0.1.0/core/testing/mersal_testing/test_doubles/unit_of_work/unit_of_work_test_helper.py +24 -0
  190. mersal-0.1.0/core/testing/mersal_testing/testing_utils.py +11 -0
  191. mersal-0.1.0/core/testing/mersal_testing/transport/basic_transport_tests.py +170 -0
  192. mersal-0.1.0/core/testing/mersal_testing/transport/transport_decorator_helper.py +36 -0
  193. mersal-0.1.0/core/tests/__init__.py +0 -0
  194. mersal-0.1.0/core/tests/activation/test_builtin_handler_activator.py +49 -0
  195. mersal-0.1.0/core/tests/conftest.py +30 -0
  196. mersal-0.1.0/core/tests/idempotency/test_idempotency_checker_step.py +208 -0
  197. mersal-0.1.0/core/tests/integration/test_app.py +64 -0
  198. mersal-0.1.0/core/tests/integration/test_basic_receive.py +0 -0
  199. mersal-0.1.0/core/tests/integration/test_basic_send.py +115 -0
  200. mersal-0.1.0/core/tests/integration/test_basic_send_and_receive.py +171 -0
  201. mersal-0.1.0/core/tests/integration/test_idempotency_plugin.py +85 -0
  202. mersal-0.1.0/core/tests/integration/test_lifespan_plugin.py +85 -0
  203. mersal-0.1.0/core/tests/integration/test_pub_sub.py +209 -0
  204. mersal-0.1.0/core/tests/integration/test_receive_with_unit_of_work.py +135 -0
  205. mersal-0.1.0/core/tests/integration/test_with_autosubscribe_plugin.py +140 -0
  206. mersal-0.1.0/core/tests/integration/test_with_outbox.py +80 -0
  207. mersal-0.1.0/core/tests/integration/test_with_saga.py +156 -0
  208. mersal-0.1.0/core/tests/outbox/test_outbox_forwader.py +126 -0
  209. mersal-0.1.0/core/tests/outbox/test_outbox_step.py +41 -0
  210. mersal-0.1.0/core/tests/outbox/test_outbox_transport_decorator.py +118 -0
  211. mersal-0.1.0/core/tests/persistence/test_in_memory_subscription_storage.py +34 -0
  212. mersal-0.1.0/core/tests/pipeline/test_activate_handlers_step.py +120 -0
  213. mersal-0.1.0/core/tests/pipeline/test_deserialize_incoming_message_step.py +38 -0
  214. mersal-0.1.0/core/tests/pipeline/test_dispatch_incoming_message_step.py +78 -0
  215. mersal-0.1.0/core/tests/pipeline/test_flow_correlation_step.py +135 -0
  216. mersal-0.1.0/core/tests/pipeline/test_iterative_pipeline_invoker.py +28 -0
  217. mersal-0.1.0/core/tests/pipeline/test_pipeline_injector.py +112 -0
  218. mersal-0.1.0/core/tests/pipeline/test_recursive_pipeline_invoker.py +31 -0
  219. mersal-0.1.0/core/tests/pipeline/test_send_outgoing_message_step.py +58 -0
  220. mersal-0.1.0/core/tests/pipeline/test_serialize_outgoing_message_step.py +41 -0
  221. mersal-0.1.0/core/tests/pipeline/test_set_default_headers_step.py +72 -0
  222. mersal-0.1.0/core/tests/pipeline/test_stop_invocation.py +46 -0
  223. mersal-0.1.0/core/tests/profile.py +44 -0
  224. mersal-0.1.0/core/tests/profile_results +0 -0
  225. mersal-0.1.0/core/tests/retry/test_deadletter_queue_error_handler.py +37 -0
  226. mersal-0.1.0/core/tests/retry/test_default_fail_fast_checker.py +26 -0
  227. mersal-0.1.0/core/tests/retry/test_default_retry_strategy.py +297 -0
  228. mersal-0.1.0/core/tests/retry/test_in_memory_error_tracker.py +28 -0
  229. mersal-0.1.0/core/tests/routing/test_default_router.py +37 -0
  230. mersal-0.1.0/core/tests/sagas/test_default_correlation_handler.py +34 -0
  231. mersal-0.1.0/core/tests/sagas/test_load_saga_data_step.py +465 -0
  232. mersal-0.1.0/core/tests/test_default_configurator.py +110 -0
  233. mersal-0.1.0/core/tests/test_dependency_resolver.py +121 -0
  234. mersal-0.1.0/core/tests/threading/test_anyio_async_periodic_task_factory.py +27 -0
  235. mersal-0.1.0/core/tests/transport/in_memory/test_in_memory_network.py +31 -0
  236. mersal-0.1.0/core/tests/transport/in_memory/test_in_memory_transport.py +34 -0
  237. mersal-0.1.0/core/tests/transport/test_ambient_context.py +38 -0
  238. mersal-0.1.0/core/tests/transport/test_default_transaction_context.py +320 -0
  239. mersal-0.1.0/core/tests/transport/test_transaction_scope.py +49 -0
  240. mersal-0.1.0/core/tests/transport/test_transport_bridge.py +58 -0
  241. mersal-0.1.0/core/tests/unit_of_work/test_unit_of_work_step.py +126 -0
  242. mersal-0.1.0/core/tests/utils/test_async_retrier.py +67 -0
  243. mersal-0.1.0/core/tests/workers/test_anyio_worker.py +230 -0
  244. mersal-0.1.0/packages/mersal_alchemy/README.md +3 -0
  245. mersal-0.1.0/packages/mersal_alchemy/pyproject.toml +36 -0
  246. mersal-0.1.0/packages/mersal_alchemy/src/mersal_alchemy/__init__.py +24 -0
  247. mersal-0.1.0/packages/mersal_alchemy/src/mersal_alchemy/orm.py +73 -0
  248. mersal-0.1.0/packages/mersal_alchemy/src/mersal_alchemy/py.typed +0 -0
  249. mersal-0.1.0/packages/mersal_alchemy/src/mersal_alchemy/sqlalchemy_outbox_storage.py +128 -0
  250. mersal-0.1.0/packages/mersal_alchemy/src/mersal_alchemy/sqlalchemy_saga_storage.py +155 -0
  251. mersal-0.1.0/packages/mersal_alchemy/src/mersal_alchemy/sqlalchemy_unit_of_work.py +58 -0
  252. mersal-0.1.0/packages/mersal_alchemy/tests/conftest.py +209 -0
  253. mersal-0.1.0/packages/mersal_alchemy/tests/docker-compose.yml +17 -0
  254. mersal-0.1.0/packages/mersal_alchemy/tests/test_sqlalchemy_outbox_storage.py +182 -0
  255. mersal-0.1.0/packages/mersal_alchemy/tests/test_sqlalchemy_saga_storage.py +313 -0
  256. mersal-0.1.0/packages/mersal_litestar/README.md +3 -0
  257. mersal-0.1.0/packages/mersal_litestar/pyproject.toml +33 -0
  258. mersal-0.1.0/packages/mersal_litestar/src/mersal_litestar/__init__.py +8 -0
  259. mersal-0.1.0/packages/mersal_litestar/src/mersal_litestar/litestar_mersal_plugin.py +47 -0
  260. mersal-0.1.0/packages/mersal_litestar/src/mersal_litestar/py.typed +0 -0
  261. mersal-0.1.0/packages/mersal_litestar/tests/conftest.py +3 -0
  262. mersal-0.1.0/packages/mersal_litestar/tests/test_with_litestar_plugin.py +136 -0
  263. mersal-0.1.0/packages/mersal_msgspec/.python-version +1 -0
  264. mersal-0.1.0/packages/mersal_msgspec/README.md +3 -0
  265. mersal-0.1.0/packages/mersal_msgspec/pyproject.toml +33 -0
  266. mersal-0.1.0/packages/mersal_msgspec/src/mersal_msgspec/__init__.py +5 -0
  267. mersal-0.1.0/packages/mersal_msgspec/src/mersal_msgspec/msgspec_serializer.py +47 -0
  268. mersal-0.1.0/packages/mersal_msgspec/src/mersal_msgspec/msgspec_serializer_plugin.py +38 -0
  269. mersal-0.1.0/packages/mersal_msgspec/src/mersal_msgspec/py.typed +0 -0
  270. mersal-0.1.0/packages/mersal_msgspec/tests/conftest.py +3 -0
  271. mersal-0.1.0/packages/mersal_msgspec/tests/test_msgspec_serializer.py +48 -0
  272. mersal-0.1.0/packages/mersal_polling/README.md +3 -0
  273. mersal-0.1.0/packages/mersal_polling/pyproject.toml +33 -0
  274. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/__init__.py +21 -0
  275. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/config.py +65 -0
  276. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/default_poller.py +37 -0
  277. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/error_handler_poller_wrapper.py +21 -0
  278. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/message_completion_handler.py +93 -0
  279. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/plugin.py +245 -0
  280. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/poller.py +23 -0
  281. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/poller_with_timeout.py +28 -0
  282. mersal-0.1.0/packages/mersal_polling/src/mersal_polling/py.typed +0 -0
  283. mersal-0.1.0/packages/mersal_polling/tests/conftest.py +3 -0
  284. mersal-0.1.0/packages/mersal_polling/tests/test_polling_plugin.py +385 -0
  285. mersal-0.1.0/pyproject.toml +235 -0
  286. mersal-0.1.0/uv.lock +2002 -0
@@ -0,0 +1,196 @@
1
+
2
+ # Created by https://www.toptal.com/developers/gitignore/api/python,emacs
3
+ # Edit at https://www.toptal.com/developers/gitignore?templates=python,emacs
4
+
5
+ *.DS_Store
6
+ ### Emacs ###
7
+ # -*- mode: gitignore; -*-
8
+ *~
9
+ \#*\#
10
+ /.emacs.desktop
11
+ /.emacs.desktop.lock
12
+ *.elc
13
+ auto-save-list
14
+ tramp
15
+ .\#*
16
+
17
+ # Org-mode
18
+ .org-id-locations
19
+ *_archive
20
+
21
+ # flymake-mode
22
+ *_flymake.*
23
+
24
+ # eshell files
25
+ /eshell/history
26
+ /eshell/lastdir
27
+
28
+ # elpa packages
29
+ /elpa/
30
+
31
+ # reftex files
32
+ *.rel
33
+
34
+ # AUCTeX auto folder
35
+ /auto/
36
+
37
+ # cask packages
38
+ .cask/
39
+ dist/
40
+
41
+ # Flycheck
42
+ flycheck_*.el
43
+
44
+ # server auth directory
45
+ /server/
46
+
47
+ # projectiles files
48
+ .projectile
49
+
50
+ # directory configuration
51
+ .dir-locals.el
52
+
53
+ # network security
54
+ /network-security.data
55
+
56
+
57
+ ### Python ###
58
+ # Byte-compiled / optimized / DLL files
59
+ __pycache__/
60
+ *.py[cod]
61
+ *$py.class
62
+
63
+ # C extensions
64
+ *.so
65
+
66
+ # Distribution / packaging
67
+ .Python
68
+ build/
69
+ develop-eggs/
70
+ downloads/
71
+ eggs/
72
+ .eggs/
73
+ lib/
74
+ lib64/
75
+ parts/
76
+ sdist/
77
+ var/
78
+ wheels/
79
+ share/python-wheels/
80
+ *.egg-info/
81
+ .installed.cfg
82
+ *.egg
83
+ MANIFEST
84
+
85
+ # PyInstaller
86
+ # Usually these files are written by a python script from a template
87
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
88
+ *.manifest
89
+ *.spec
90
+
91
+ # Installer logs
92
+ pip-log.txt
93
+ pip-delete-this-directory.txt
94
+
95
+ # Unit test / coverage reports
96
+ htmlcov/
97
+ .tox/
98
+ .nox/
99
+ .coverage
100
+ .coverage.*
101
+ .cache
102
+ nosetests.xml
103
+ coverage.xml
104
+ *.cover
105
+ *.py,cover
106
+ .hypothesis/
107
+ .pytest_cache/
108
+ cover/
109
+
110
+ # Translations
111
+ *.mo
112
+ *.pot
113
+
114
+ # Django stuff:
115
+ *.log
116
+ local_settings.py
117
+ db.sqlite3
118
+ db.sqlite3-journal
119
+
120
+ # Flask stuff:
121
+ instance/
122
+ .webassets-cache
123
+
124
+ # Scrapy stuff:
125
+ .scrapy
126
+
127
+ # Sphinx documentation
128
+ docs/_build/
129
+
130
+ # PyBuilder
131
+ .pybuilder/
132
+ target/
133
+
134
+ # Jupyter Notebook
135
+ .ipynb_checkpoints
136
+
137
+ # IPython
138
+ profile_default/
139
+ ipython_config.py
140
+
141
+ # pyenv
142
+ # For a library or package, you might want to ignore these files since the code is
143
+ # intended to run in multiple environments; otherwise, check them in:
144
+ # .python-version
145
+
146
+ # pipenv
147
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
148
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
149
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
150
+ # install all needed dependencies.
151
+ #Pipfile.lock
152
+
153
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
154
+ __pypackages__/
155
+
156
+ # Celery stuff
157
+ celerybeat-schedule
158
+ celerybeat.pid
159
+
160
+ # SageMath parsed files
161
+ *.sage.py
162
+
163
+ # Environments
164
+ .env
165
+ .venv
166
+ env/
167
+ venv/
168
+ ENV/
169
+ env.bak/
170
+ venv.bak/
171
+
172
+ # Spyder project settings
173
+ .spyderproject
174
+ .spyproject
175
+
176
+ # Rope project settings
177
+ .ropeproject
178
+
179
+ # mkdocs documentation
180
+ /site
181
+
182
+ # mypy
183
+ .mypy_cache/
184
+ .dmypy.json
185
+ dmypy.json
186
+
187
+ # Pyre type checker
188
+ .pyre/
189
+
190
+ # pytype static type analyzer
191
+ .pytype/
192
+
193
+ # Cython debug symbols
194
+ cython_debug/
195
+
196
+ # End of https://www.toptal.com/developers/gitignore/api/python,emacs
@@ -0,0 +1,53 @@
1
+ default_language_version:
2
+ python: "3.13"
3
+ repos:
4
+ - repo: https://github.com/compilerla/conventional-pre-commit
5
+ rev: v4.0.0
6
+ hooks:
7
+ - id: conventional-pre-commit
8
+ stages: [commit-msg]
9
+ - repo: https://github.com/pre-commit/pre-commit-hooks
10
+ rev: v5.0.0
11
+ hooks:
12
+ - id: check-ast
13
+ - id: check-case-conflict
14
+ - id: check-toml
15
+ - id: debug-statements
16
+ exclude: ^(core/src/mersal/retry/default_retry_step\.py)$
17
+ - id: end-of-file-fixer
18
+ - id: mixed-line-ending
19
+ - id: trailing-whitespace
20
+ - repo: https://github.com/astral-sh/ruff-pre-commit
21
+ rev: v0.11.0
22
+ hooks:
23
+ - id: ruff
24
+ args: ["--fix", "--config", "pyproject.toml"]
25
+ - id: ruff-format
26
+ args: ["--config", "pyproject.toml"]
27
+ - repo: https://github.com/codespell-project/codespell
28
+ rev: v2.4.1
29
+ hooks:
30
+ - id: codespell
31
+ additional_dependencies:
32
+ - tomli
33
+ - repo: https://github.com/python-formate/flake8-dunder-all
34
+ rev: v0.4.1
35
+ hooks:
36
+ - id: ensure-dunder-all
37
+ args: ["--use-tuple"]
38
+ # - repo: https://github.com/ariebovenberg/slotscheck
39
+ # rev: v0.19.1
40
+ # hooks:
41
+ # - id: slotscheck
42
+ # exclude: "docs|.github"
43
+ - repo: https://github.com/sphinx-contrib/sphinx-lint
44
+ rev: "v1.0.0"
45
+ hooks:
46
+ - id: sphinx-lint
47
+ # - repo: local
48
+ # hooks:
49
+ # - id: pypi-readme
50
+ # name: pypi-readme
51
+ # language: python
52
+ # entry: python tools/pypi_readme.py
53
+ # types: [markdown]
@@ -0,0 +1 @@
1
+ 3.13
File without changes
mersal-0.1.0/Makefile ADDED
@@ -0,0 +1,254 @@
1
+ SHELL := /bin/bash
2
+
3
+ # =============================================================================
4
+ # Configuration and Environment Variables
5
+ # =============================================================================
6
+
7
+ .DEFAULT_GOAL := help
8
+ .ONESHELL:
9
+ .EXPORT_ALL_VARIABLES:
10
+ MAKEFLAGS += --no-print-directory
11
+
12
+ # -----------------------------------------------------------------------------
13
+ # Display Formatting and Colors
14
+ # -----------------------------------------------------------------------------
15
+ BLUE := $(shell printf "\033[1;34m")
16
+ GREEN := $(shell printf "\033[1;32m")
17
+ RED := $(shell printf "\033[1;31m")
18
+ YELLOW := $(shell printf "\033[1;33m")
19
+ NC := $(shell printf "\033[0m")
20
+ INFO := $(shell printf "$(BLUE)ℹ$(NC)")
21
+ OK := $(shell printf "$(GREEN)✓$(NC)")
22
+ WARN := $(shell printf "$(YELLOW)⚠$(NC)")
23
+ ERROR := $(shell printf "$(RED)✖$(NC)")
24
+
25
+ # =============================================================================
26
+ # Help and Documentation
27
+ # =============================================================================
28
+
29
+ .PHONY: help
30
+ help: ## Display this help text for Makefile
31
+ @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
32
+
33
+ # =============================================================================
34
+ # Installation and Environment Setup
35
+ # =============================================================================
36
+
37
+ .PHONY: install-uv
38
+ install-uv: ## Install latest version of uv
39
+ @echo "${INFO} Installing uv..."
40
+ @curl -LsSf https://astral.sh/uv/install.sh | sh >/dev/null 2>&1
41
+ @echo "${OK} UV installed successfully"
42
+
43
+ .PHONY: install
44
+ install: destroy clean ## Install the project, dependencies, and pre-commit
45
+ @echo "${INFO} Starting fresh installation..."
46
+ @uv python pin 3.13 >/dev/null 2>&1
47
+ @uv venv >/dev/null 2>&1
48
+ @uv sync --all-extras --dev --all-packages
49
+ @echo "${OK} Installation complete! 🎉"
50
+
51
+ .PHONY: destroy
52
+ destroy: ## Destroy the virtual environment
53
+ @echo "${INFO} Destroying virtual environment... 🗑️"
54
+ @uv run pre-commit clean >/dev/null 2>&1
55
+ @rm -rf .venv
56
+ @echo "${OK} Virtual environment destroyed 🗑️"
57
+
58
+ # =============================================================================
59
+ # Dependency Management
60
+ # =============================================================================
61
+
62
+ .PHONY: upgrade
63
+ upgrade: ## Upgrade all dependencies to latest stable versions
64
+ @echo "${INFO} Updating all dependencies... 🔄"
65
+ @uv lock --upgrade
66
+ @echo "${OK} Dependencies updated 🔄"
67
+ @uv run pre-commit autoupdate
68
+ @echo "${OK} Updated Pre-commit hooks 🔄"
69
+
70
+ .PHONY: lock
71
+ lock: ## Rebuild lockfiles from scratch
72
+ @echo "${INFO} Rebuilding lockfiles... 🔄"
73
+ @uv lock --upgrade >/dev/null 2>&1
74
+ @echo "${OK} Lockfiles updated"
75
+
76
+ # =============================================================================
77
+ # Build and Release
78
+ # =============================================================================
79
+
80
+ .PHONY: build
81
+ build: ## Build the package
82
+ @echo "${INFO} Building package... 📦"
83
+ @uv build --all-packages >/dev/null 2>&1
84
+ @echo "${OK} Package build complete"
85
+
86
+ .PHONY: release
87
+ release: ## Bump version and create release tag
88
+ @echo "${INFO} Preparing for release... 📦"
89
+ @make docs
90
+ @make clean
91
+ @make build
92
+ @uv lock --upgrade-package litestar-vite >/dev/null 2>&1
93
+ @uv run bump-my-version bump $(bump)
94
+ @echo "${OK} Release complete 🎉"
95
+
96
+ # =============================================================================
97
+ # Cleaning and Maintenance
98
+ # =============================================================================
99
+
100
+ .PHONY: clean
101
+ clean: ## Cleanup temporary build artifacts
102
+ @echo "${INFO} Cleaning working directory... 🧹"
103
+ @rm -rf .pytest_cache .ruff_cache .hypothesis build/ -rf dist/ .eggs/ .coverage coverage.xml coverage.json htmlcov/ .pytest_cache tests/.pytest_cache tests/**/.pytest_cache .mypy_cache .unasyncd_cache/ .auto_pytabs_cache >/dev/null 2>&1
104
+ @find . -name '*.egg-info' -exec rm -rf {} + >/dev/null 2>&1
105
+ @find . -type f -name '*.egg' -exec rm -f {} + >/dev/null 2>&1
106
+ @find . -name '*.pyc' -exec rm -f {} + >/dev/null 2>&1
107
+ @find . -name '*.pyo' -exec rm -f {} + >/dev/null 2>&1
108
+ @find . -name '*~' -exec rm -f {} + >/dev/null 2>&1
109
+ @find . -name '__pycache__' -exec rm -rf {} + >/dev/null 2>&1
110
+ @find . -name '.ipynb_checkpoints' -exec rm -rf {} + >/dev/null 2>&1
111
+ @echo "${OK} Working directory cleaned"
112
+ $(MAKE) docs-clean
113
+
114
+ # =============================================================================
115
+ # Testing and Quality Checks
116
+ # =============================================================================
117
+
118
+ .PHONY: test
119
+ test: ## Run the tests
120
+ @echo "${INFO} Running core test cases... 🧪"
121
+ @uv run pytest core/tests
122
+ @echo "${OK} Core Tests complete ✨"
123
+
124
+ .PHONY: test-litestar
125
+ test-litestar: ## Run the mersal_litestar tests
126
+ @echo "${INFO} Running mersal_litestar test cases... 🧪"
127
+ @uv run --package=mersal_litestar pytest packages/mersal_litestar/tests
128
+ @echo "${OK} Mersal_Litestar Tests complete ✨"
129
+
130
+ .PHONY: test-polling
131
+ test-polling: ## Run the mersal_polling tests
132
+ @echo "${INFO} Running mersal_polling test cases... 🧪"
133
+ @uv run --package=mersal_polling pytest packages/mersal_polling/tests
134
+ @echo "${OK} Mersal_Polling Tests complete ✨"
135
+
136
+ .PHONY: test-sqlalchemy
137
+ test-sqlalchemy: ## Run the mersal_alchemy tests
138
+ @echo "${INFO} Running mersal_alchemy test cases... 🧪"
139
+ @uv run --package=mersal_alchemy pytest packages/mersal_alchemy/tests
140
+ @echo "${OK} Mersal_Alchemy Tests complete ✨"
141
+
142
+ .PHONY: test-msgspec
143
+ test-msgspec: ## Run the mersal_msgspec tests
144
+ @echo "${INFO} Running mersal_msgspec test cases... 🧪"
145
+ @uv run --package=mersal_msgspec pytest packages/mersal_msgspec/tests
146
+ @echo "${OK} Mersal_Msgspec Tests complete ✨"
147
+
148
+ .PHONY: test-examples
149
+ test-examples: ## Run the doc examples tests
150
+ @echo "${INFO} Running doc examples test cases... 🧪"
151
+ @uv run --package=mersal_docs pytest docs/examples/tests
152
+ @echo "${OK} Doc Examples Tests complete ✨"
153
+
154
+ .PHONY: test-all
155
+ test-all: test test-litestar test-polling test-sqlalchemy test-msgspec # test-examples ## Run all tests
156
+ @echo "${INFO} All tests executed successfully ✨"
157
+
158
+ # .PHONY: coverage
159
+ # coverage: ## Run tests with coverage report
160
+ # @echo "${INFO} Running tests with coverage... 📊"
161
+ # @uv run pytest --cov -n auto --quiet
162
+ # @uv run coverage html >/dev/null 2>&1
163
+ # @uv run coverage xml >/dev/null 2>&1
164
+ # @echo "${OK} Coverage report generated ✨"
165
+
166
+ # -----------------------------------------------------------------------------
167
+ # Type Checking
168
+ # -----------------------------------------------------------------------------
169
+
170
+ .PHONY: mypy
171
+ mypy: ## Run mypy
172
+ @echo "${INFO} Running mypy... 🔍"
173
+ @uv run dmypy run
174
+ @echo "${OK} Mypy checks passed ✨"
175
+
176
+ .PHONY: pyright
177
+ pyright: ## Run pyright
178
+ @echo "${INFO} Running basedpyright... 🔍"
179
+ @uv run basedpyright
180
+ @echo "${OK} basedpyright checks passed ✨"
181
+
182
+ .PHONY: type-check
183
+ type-check: mypy pyright ## Run all type checking
184
+
185
+ # -----------------------------------------------------------------------------
186
+ # Linting and Formatting
187
+ # -----------------------------------------------------------------------------
188
+
189
+ .PHONY: pre-commit
190
+ pre-commit: ## Run pre-commit hooks
191
+ @echo "${INFO} Running pre-commit checks... 🔎"
192
+ @uv run pre-commit run --color=always --all-files
193
+ @echo "${OK} Pre-commit checks passed ✨"
194
+
195
+ # .PHONY: slotscheck
196
+ # slotscheck: ## Run slotscheck
197
+ # @echo "${INFO} Running slotscheck... 🔍"
198
+ # @uv run slotscheck core/src
199
+ # @uv run slotscheck packages/mersal_polling/src
200
+ # @uv run slotscheck packages/mersal_alchemy/src
201
+ # @uv run slotscheck packages/mersal_litestar/src
202
+ # @uv run slotscheck packages/mersal_msgspec/src
203
+ # @echo "${OK} Slotscheck complete ✨"
204
+
205
+ .PHONY: fix
206
+ fix: ## Run code formatters
207
+ @echo "${INFO} Running code formatters... 🔧"
208
+ @uv run ruff check --fix --unsafe-fixes
209
+ @uv run ruff format
210
+ @echo "${OK} Code formatting complete ✨"
211
+
212
+ .PHONY: lint
213
+ lint: fix pre-commit type-check # slotscheck ## Run all linting checks
214
+ @echo "${OK} All linting checks passed ✨"
215
+
216
+ .PHONY: check-all
217
+ check-all: lint test-all # coverage ## Run all checks (lint, test, coverage)
218
+ @echo "${OK} All checks passed successfully ✨"
219
+ # =============================================================================
220
+ # Documentation
221
+ # =============================================================================
222
+
223
+ .PHONY: docs-clean
224
+ docs-clean: ## Clean documentation build
225
+ @echo "${INFO} Cleaning documentation build assets... 🧹"
226
+ @rm -rf docs/_build >/dev/null 2>&1
227
+ @echo "${OK} Documentation assets cleaned"
228
+
229
+ .PHONY: docs-serve
230
+ docs-serve: docs-clean ## Serve documentation locally
231
+ @echo "${INFO} Starting documentation server... 📚"
232
+ @uv run sphinx-autobuild docs docs/_build/ -j auto --watch core --watch packages --watch docs --watch CONTRIBUTING.rst --port 8002
233
+
234
+ .PHONY: docs
235
+ docs: docs-clean ## Build documentation
236
+ @echo "${INFO} Building documentation... 📝"
237
+ @uv run sphinx-build -M html docs docs/_build/ -E -a -j auto -W --keep-going >/dev/null 2>&1
238
+ @echo "${OK} Documentation built successfully"
239
+
240
+ .PHONY: docs-linkcheck
241
+ docs-linkcheck: ## Check documentation links
242
+ @echo "${INFO} Checking documentation links... 🔗"
243
+ @uv run sphinx-build -b linkcheck ./docs ./docs/_build -D linkcheck_ignore='http://.*','https://.*'
244
+ @echo "${OK} Link check complete"
245
+
246
+ .PHONY: docs-linkcheck-full
247
+ docs-linkcheck-full: ## Run full documentation link check
248
+ @echo "${INFO} Running full link check... 🔗"
249
+ @uv run sphinx-build -b linkcheck ./docs ./docs/_build -D linkcheck_anchors=0
250
+ @echo "${OK} Full link check complete"
251
+
252
+ # =============================================================================
253
+ # End of Makefile
254
+ # =============================================================================
mersal-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,13 @@
1
+ Metadata-Version: 2.4
2
+ Name: mersal
3
+ Version: 0.1.0
4
+ Summary: A service bus library.
5
+ Author-email: Abdulhaq Emhemmed <abdulhaq.emhemmed@gmail.com>
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: anyio>=4.8.0
8
+ Description-Content-Type: text/x-rst
9
+
10
+ Mersal
11
+ =======
12
+
13
+ **Mersal** is a service bus library for Python.
@@ -0,0 +1,4 @@
1
+ Mersal
2
+ =======
3
+
4
+ **Mersal** is a service bus library for Python.
@@ -0,0 +1,3 @@
1
+ # mersal
2
+
3
+ Describe your project here.
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,102 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import defaultdict
4
+ from typing import TYPE_CHECKING, TypeVar, cast
5
+
6
+ from mersal.pipeline import MessageContext
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Sequence
10
+
11
+ from mersal._activation.handler_activator import HandlerFactory
12
+ from mersal.app import Mersal
13
+ from mersal.handlers import MessageHandler
14
+ from mersal.transport import TransactionContext
15
+
16
+ # Define locally to avoid import cycle with handler_activator.py
17
+ MessageT = TypeVar("MessageT")
18
+
19
+ __all__ = ("BuiltinHandlerActivator",)
20
+
21
+
22
+ class BuiltinHandlerActivator:
23
+ """Default implementation of the handler activator pattern.
24
+
25
+ This class manages the registration and activation of message handlers
26
+ based on message types. It stores handler factories indexed by message type
27
+ and instantiates the appropriate handlers when a message needs to be processed.
28
+ """
29
+
30
+ def __init__(self) -> None:
31
+ """Initialize a new instance of the BuiltinHandlerActivator."""
32
+ self._handler_factories: dict[type, list[HandlerFactory]] = defaultdict(list)
33
+ self._app: Mersal | None = None
34
+
35
+ async def get_handlers(
36
+ self,
37
+ message: MessageT,
38
+ transaction_context: TransactionContext,
39
+ ) -> Sequence[MessageHandler[MessageT]]:
40
+ """Get handlers for the specified message.
41
+
42
+ Args:
43
+ message: The message to get handlers for
44
+ transaction_context: The current transaction context
45
+
46
+ Returns:
47
+ A sequence of message handlers that can process the message
48
+
49
+ Raises:
50
+ Exception: If called outside of a message context
51
+ """
52
+ message_context = MessageContext.current()
53
+ if not message_context:
54
+ raise Exception(
55
+ "BuiltinHandlerActivator get_handlers called outside of a transaction.",
56
+ )
57
+
58
+ return [x(message_context, self.app) for x in self._handler_factories.get(type(message), [])]
59
+
60
+ def register(
61
+ self,
62
+ message_type: type[MessageT],
63
+ factory: HandlerFactory[MessageT],
64
+ ) -> BuiltinHandlerActivator:
65
+ """Register a handler factory for a specific message type.
66
+
67
+ Args:
68
+ message_type: The type of message to register a handler for
69
+ factory: A factory function that creates a message handler
70
+
71
+ Returns:
72
+ The handler activator instance for method chaining
73
+ """
74
+ self._handler_factories[message_type].append(factory)
75
+ return self
76
+
77
+ @property
78
+ def registered_message_types(self) -> set[type]:
79
+ """Get the set of message types that have registered handlers.
80
+
81
+ Returns:
82
+ A set containing all registered message types
83
+ """
84
+ return set(self._handler_factories.keys())
85
+
86
+ @property
87
+ def app(self) -> Mersal:
88
+ """Get the associated application instance.
89
+
90
+ Returns:
91
+ The Mersal application instance
92
+ """
93
+ return cast("Mersal", self._app)
94
+
95
+ @app.setter
96
+ def app(self, value: Mersal) -> None:
97
+ """Set the associated application instance.
98
+
99
+ Args:
100
+ value: The Mersal application instance
101
+ """
102
+ self._app = value