jararaca 0.2.37a12__py3-none-any.whl → 0.4.0a5__py3-none-any.whl

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 (91) hide show
  1. README.md +121 -0
  2. jararaca/__init__.py +267 -15
  3. jararaca/__main__.py +4 -0
  4. jararaca/broker_backend/__init__.py +106 -0
  5. jararaca/broker_backend/mapper.py +25 -0
  6. jararaca/broker_backend/redis_broker_backend.py +168 -0
  7. jararaca/cli.py +840 -103
  8. jararaca/common/__init__.py +3 -0
  9. jararaca/core/__init__.py +3 -0
  10. jararaca/core/providers.py +4 -0
  11. jararaca/core/uow.py +55 -16
  12. jararaca/di.py +4 -0
  13. jararaca/files/entity.py.mako +4 -0
  14. jararaca/lifecycle.py +6 -2
  15. jararaca/messagebus/__init__.py +5 -1
  16. jararaca/messagebus/bus_message_controller.py +4 -0
  17. jararaca/messagebus/consumers/__init__.py +3 -0
  18. jararaca/messagebus/decorators.py +90 -85
  19. jararaca/messagebus/implicit_headers.py +49 -0
  20. jararaca/messagebus/interceptors/__init__.py +3 -0
  21. jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +95 -37
  22. jararaca/messagebus/interceptors/publisher_interceptor.py +42 -0
  23. jararaca/messagebus/message.py +31 -0
  24. jararaca/messagebus/publisher.py +47 -4
  25. jararaca/messagebus/worker.py +1615 -135
  26. jararaca/microservice.py +248 -36
  27. jararaca/observability/constants.py +7 -0
  28. jararaca/observability/decorators.py +177 -16
  29. jararaca/observability/fastapi_exception_handler.py +37 -0
  30. jararaca/observability/hooks.py +109 -0
  31. jararaca/observability/interceptor.py +8 -2
  32. jararaca/observability/providers/__init__.py +3 -0
  33. jararaca/observability/providers/otel.py +213 -18
  34. jararaca/persistence/base.py +40 -3
  35. jararaca/persistence/exports.py +4 -0
  36. jararaca/persistence/interceptors/__init__.py +3 -0
  37. jararaca/persistence/interceptors/aiosqa_interceptor.py +187 -23
  38. jararaca/persistence/interceptors/constants.py +5 -0
  39. jararaca/persistence/interceptors/decorators.py +50 -0
  40. jararaca/persistence/session.py +3 -0
  41. jararaca/persistence/sort_filter.py +4 -0
  42. jararaca/persistence/utilities.py +74 -32
  43. jararaca/presentation/__init__.py +3 -0
  44. jararaca/presentation/decorators.py +170 -82
  45. jararaca/presentation/exceptions.py +23 -0
  46. jararaca/presentation/hooks.py +4 -0
  47. jararaca/presentation/http_microservice.py +4 -0
  48. jararaca/presentation/server.py +120 -41
  49. jararaca/presentation/websocket/__init__.py +3 -0
  50. jararaca/presentation/websocket/base_types.py +4 -0
  51. jararaca/presentation/websocket/context.py +34 -4
  52. jararaca/presentation/websocket/decorators.py +8 -41
  53. jararaca/presentation/websocket/redis.py +280 -53
  54. jararaca/presentation/websocket/types.py +6 -2
  55. jararaca/presentation/websocket/websocket_interceptor.py +74 -23
  56. jararaca/reflect/__init__.py +3 -0
  57. jararaca/reflect/controller_inspect.py +81 -0
  58. jararaca/reflect/decorators.py +238 -0
  59. jararaca/reflect/metadata.py +76 -0
  60. jararaca/rpc/__init__.py +3 -0
  61. jararaca/rpc/http/__init__.py +101 -0
  62. jararaca/rpc/http/backends/__init__.py +14 -0
  63. jararaca/rpc/http/backends/httpx.py +43 -9
  64. jararaca/rpc/http/backends/otel.py +4 -0
  65. jararaca/rpc/http/decorators.py +378 -113
  66. jararaca/rpc/http/httpx.py +3 -0
  67. jararaca/scheduler/__init__.py +3 -0
  68. jararaca/scheduler/beat_worker.py +758 -0
  69. jararaca/scheduler/decorators.py +89 -28
  70. jararaca/scheduler/types.py +11 -0
  71. jararaca/tools/app_config/__init__.py +3 -0
  72. jararaca/tools/app_config/decorators.py +7 -19
  73. jararaca/tools/app_config/interceptor.py +10 -4
  74. jararaca/tools/typescript/__init__.py +3 -0
  75. jararaca/tools/typescript/decorators.py +120 -0
  76. jararaca/tools/typescript/interface_parser.py +1126 -189
  77. jararaca/utils/__init__.py +3 -0
  78. jararaca/utils/rabbitmq_utils.py +372 -0
  79. jararaca/utils/retry.py +148 -0
  80. jararaca-0.4.0a5.dist-info/LICENSE +674 -0
  81. jararaca-0.4.0a5.dist-info/LICENSES/GPL-3.0-or-later.txt +232 -0
  82. {jararaca-0.2.37a12.dist-info → jararaca-0.4.0a5.dist-info}/METADATA +14 -7
  83. jararaca-0.4.0a5.dist-info/RECORD +88 -0
  84. {jararaca-0.2.37a12.dist-info → jararaca-0.4.0a5.dist-info}/WHEEL +1 -1
  85. pyproject.toml +131 -0
  86. jararaca/messagebus/types.py +0 -30
  87. jararaca/scheduler/scheduler.py +0 -154
  88. jararaca/tools/metadata.py +0 -47
  89. jararaca-0.2.37a12.dist-info/RECORD +0 -63
  90. /jararaca-0.2.37a12.dist-info/LICENSE → /LICENSE +0 -0
  91. {jararaca-0.2.37a12.dist-info → jararaca-0.4.0a5.dist-info}/entry_points.txt +0 -0
@@ -1,154 +0,0 @@
1
- import asyncio
2
- import logging
3
- from contextlib import asynccontextmanager
4
- from dataclasses import dataclass
5
- from datetime import UTC, datetime
6
- from typing import Any, AsyncContextManager, AsyncGenerator, Callable
7
-
8
- import uvloop
9
- from croniter import croniter
10
-
11
- from jararaca.core.uow import UnitOfWorkContextProvider
12
- from jararaca.di import Container
13
- from jararaca.lifecycle import AppLifecycle
14
- from jararaca.microservice import Microservice, SchedulerAppContext
15
- from jararaca.scheduler.decorators import ScheduledAction
16
-
17
- logger = logging.getLogger(__name__)
18
-
19
-
20
- @dataclass
21
- class SchedulerConfig:
22
- interval: int
23
-
24
-
25
- class SchedulerBackend: ...
26
-
27
-
28
- def extract_scheduled_actions(
29
- app: Microservice, container: Container
30
- ) -> list[tuple[Callable[..., Any], "ScheduledAction"]]:
31
- scheduled_actions: list[tuple[Callable[..., Any], "ScheduledAction"]] = []
32
- for controllers in app.controllers:
33
-
34
- controller_instance: Any = container.get_by_type(controllers)
35
-
36
- controller_scheduled_actions = ScheduledAction.get_type_scheduled_actions(
37
- controller_instance
38
- )
39
- scheduled_actions.extend(controller_scheduled_actions)
40
-
41
- return scheduled_actions
42
-
43
-
44
- # TODO: Implement Backend for Distributed Lock
45
- # TODO: Improve error handling
46
- # TODO: Implement logging
47
- # TODO: Implement tests
48
- # TODO: Implement graceful shutdown
49
- # TODO: Implement ScheduletAction parameters configuration
50
- class Scheduler:
51
-
52
- def __init__(
53
- self,
54
- app: Microservice,
55
- backend: SchedulerBackend,
56
- config: SchedulerConfig,
57
- ) -> None:
58
- self.app = app
59
- self.backend = backend
60
- self.config = config
61
- self.container = Container(self.app)
62
- self.uow_provider = UnitOfWorkContextProvider(app, self.container)
63
-
64
- self.tasks: set[asyncio.Task[Any]] = set()
65
- self.lock = asyncio.Lock()
66
- self.shutdown_event = asyncio.Event()
67
-
68
- self.last_checks: dict[Callable[..., Any], datetime] = {}
69
-
70
- self.lifceycle = AppLifecycle(app, self.container)
71
-
72
- async def process_task(
73
- self, func: Callable[..., Any], scheduled_action: ScheduledAction
74
- ) -> None:
75
-
76
- async with self.lock:
77
- task = asyncio.create_task(self.handle_task(func, scheduled_action))
78
- self.tasks.add(task)
79
- task.add_done_callback(self.tasks.discard)
80
-
81
- async def handle_task(
82
- self, func: Callable[..., Any], scheduled_action: ScheduledAction
83
- ) -> None:
84
-
85
- last_check = self.last_checks.setdefault(func, datetime.now(UTC))
86
-
87
- cron = croniter(scheduled_action.cron, last_check)
88
- next_run: datetime = cron.get_next(datetime)
89
- if next_run > datetime.now(UTC):
90
- logger.info(
91
- f"Skipping {func.__module__}.{func.__qualname__} until {next_run}"
92
- )
93
- return
94
-
95
- logger.info(f"Running {func.__module__}.{func.__qualname__}")
96
-
97
- action_specs = ScheduledAction.get_scheduled_action(func)
98
-
99
- assert action_specs is not None
100
-
101
- ctx: AsyncContextManager[Any]
102
- if action_specs.timeout:
103
- ctx = asyncio.timeout(action_specs.timeout)
104
- else:
105
- ctx = none_context()
106
-
107
- try:
108
- async with self.uow_provider(
109
- SchedulerAppContext(
110
- action=func,
111
- scheduled_to=next_run,
112
- cron_expression=scheduled_action.cron,
113
- triggered_at=datetime.now(UTC),
114
- )
115
- ):
116
- try:
117
- async with ctx:
118
- await func()
119
- except BaseException as e:
120
- if action_specs.exception_handler:
121
- action_specs.exception_handler(e)
122
- else:
123
- logging.exception(
124
- f"Error in scheduled action {scheduled_action}: {e}"
125
- )
126
-
127
- except Exception as e:
128
- logging.exception(f"Error in scheduled action {scheduled_action}: {e}")
129
-
130
- self.last_checks[func] = datetime.now(UTC)
131
-
132
- def run(self) -> None:
133
-
134
- async def run_scheduled_actions() -> None:
135
-
136
- async with self.lifceycle():
137
- scheduled_actions = extract_scheduled_actions(self.app, self.container)
138
-
139
- while True:
140
- for func, scheduled_action in scheduled_actions:
141
- if self.shutdown_event.is_set():
142
- break
143
-
144
- await self.process_task(func, scheduled_action)
145
-
146
- await asyncio.sleep(self.config.interval)
147
-
148
- with asyncio.Runner(loop_factory=uvloop.new_event_loop) as runner:
149
- runner.run(run_scheduled_actions())
150
-
151
-
152
- @asynccontextmanager
153
- async def none_context() -> AsyncGenerator[None, None]:
154
- yield
@@ -1,47 +0,0 @@
1
- from contextlib import contextmanager, suppress
2
- from contextvars import ContextVar
3
- from typing import Any, Awaitable, Callable, TypeVar, Union, cast
4
-
5
- DECORATED = TypeVar("DECORATED", bound=Union[Callable[..., Awaitable[Any]], type])
6
-
7
-
8
- metadata_context: ContextVar[dict[str, Any]] = ContextVar("metadata_context")
9
-
10
-
11
- def get_metadata(key: str) -> Any | None:
12
- return metadata_context.get({}).get(key)
13
-
14
-
15
- @contextmanager
16
- def provide_metadata(metadata: dict[str, Any]) -> Any:
17
-
18
- current_metadata = metadata_context.get({})
19
-
20
- token = metadata_context.set({**current_metadata, **metadata})
21
- try:
22
- yield
23
- finally:
24
- with suppress(ValueError):
25
- metadata_context.reset(token)
26
-
27
-
28
- class SetMetadata:
29
- def __init__(self, key: str, value: Any) -> None:
30
- self.key = key
31
- self.value = value
32
-
33
- METATADA_LIST = "__metadata_list__"
34
-
35
- @staticmethod
36
- def register_metadata(cls: DECORATED, value: "SetMetadata") -> None:
37
- metadata_list = getattr(cls, SetMetadata.METATADA_LIST, [])
38
- metadata_list.append(value)
39
- setattr(cls, SetMetadata.METATADA_LIST, metadata_list)
40
-
41
- @staticmethod
42
- def get(cls: type) -> "list[SetMetadata]":
43
- return cast(list[SetMetadata], getattr(cls, SetMetadata.METATADA_LIST, []))
44
-
45
- def __call__(self, cls: DECORATED) -> DECORATED:
46
- SetMetadata.register_metadata(cls, self)
47
- return cls
@@ -1,63 +0,0 @@
1
- jararaca/__init__.py,sha256=VBrN25GHJ3gDG95CcJWe3dmGcA-X2agzOCIBbjzc1Iw,15312
2
- jararaca/__main__.py,sha256=-O3vsB5lHdqNFjUtoELDF81IYFtR-DSiiFMzRaiSsv4,67
3
- jararaca/cli.py,sha256=K6df8fqEc4Qj-yGz5hmO3pSgFWxcLP4iciOP4LHida4,7979
4
- jararaca/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- jararaca/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- jararaca/core/providers.py,sha256=wktH84FK7c1s2wNq-fudf1uMfi3CQBR0neU2czJ_L0U,434
7
- jararaca/core/uow.py,sha256=WrA50VWzfJIyZHeUhSs8IOpSA4T-D8VV6YPLlFTF5V4,2026
8
- jararaca/di.py,sha256=h3IsXdYZjJj8PJfnEDn0ZAwdd4EBfh8jU-wWO8ko_t4,76
9
- jararaca/files/entity.py.mako,sha256=tjQ-1udAMvVqgRokhsrR4uy3P_OVnbk3XZ8X69ixWhE,3098
10
- jararaca/lifecycle.py,sha256=qKlzLQQioS8QkxNJ_FC_5WbmT77cNbc_S7OcQeOoHkI,1895
11
- jararaca/messagebus/__init__.py,sha256=Zdl74HcS9K0FW6XUt7bVvaHEyxL8pWsqqakeRENIn0w,54
12
- jararaca/messagebus/bus_message_controller.py,sha256=Xd_qwnX5jUvgBTCarHR36fvtol9lPTsYp2IIGKyQQaE,1487
13
- jararaca/messagebus/decorators.py,sha256=GHlaXRuHtrz6R0HgcG2gJybpGYtdts9meDVSRPwN74I,4245
14
- jararaca/messagebus/interceptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py,sha256=BPH5wOlj_CyHtJ7W4NWF2h0gYMwzOPNzFhGADk618N4,4373
16
- jararaca/messagebus/publisher.py,sha256=5ay9Znwybqt981OOykdWkFisSvGiTeTpPXDFLMnaiqg,1109
17
- jararaca/messagebus/types.py,sha256=iYLyLxWqOHkDadxyMqQPWy3itLNQfvD6oQe8jcq9nzo,887
18
- jararaca/messagebus/worker.py,sha256=_X2Ctj7bI9XjCMvQMy8jM3dEE3CGnqgrU_B3lTGfmmQ,13605
19
- jararaca/microservice.py,sha256=1TvDKVMMREH27Ly8eTEheMmSfro4_Az_JKM_NdDvrgc,6636
20
- jararaca/observability/decorators.py,sha256=XffBinFXdiNkY6eo8_1nkr_GapM0RUGBg0aicBIelag,2220
21
- jararaca/observability/interceptor.py,sha256=GHkuGKFWftN7MDjvYeGFGEPnuJETNhtxRK6yuPrCrpU,1462
22
- jararaca/observability/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- jararaca/observability/providers/otel.py,sha256=LgfoITdoQTCxKebfLcEfwMiG992wlWY_0AUTd2fo8hY,6065
24
- jararaca/persistence/base.py,sha256=Xfnpvj3yeLdpVBifH5W6AwPCLwL2ot0dpLzbPg1zwkQ,966
25
- jararaca/persistence/exports.py,sha256=Ghx4yoFaB4QVTb9WxrFYgmcSATXMNvrOvT8ybPNKXCA,62
26
- jararaca/persistence/interceptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
- jararaca/persistence/interceptors/aiosqa_interceptor.py,sha256=H6ZjOdosYGCZUzKjugiXQwJkAbnsL4HnkZLOEQhULEc,1986
28
- jararaca/persistence/session.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
- jararaca/persistence/sort_filter.py,sha256=agggpN0YvNjUr6wJjy69NkaqxoDDW13ys9B3r85OujA,9226
30
- jararaca/persistence/utilities.py,sha256=0v1YrK-toTCgtw8aROtrDMNfjo3qWWNAb5qQcCOdSUU,13681
31
- jararaca/presentation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
- jararaca/presentation/decorators.py,sha256=EErRZtLZDoZZj1ZVlDkGQbvqpoQkBaoU70KAUwWIufs,9146
33
- jararaca/presentation/hooks.py,sha256=WBbU5DG3-MAm2Ro2YraQyYG_HENfizYfyShL2ktHi6k,1980
34
- jararaca/presentation/http_microservice.py,sha256=g771JosV6jTY3hQtG-HkLOo-T0e-r3b3rp1ddt99Qf0,533
35
- jararaca/presentation/server.py,sha256=JuEatLFhD_NFnszwXDSgtcCXNOwvQYyxoxxQ33hnAEc,3731
36
- jararaca/presentation/websocket/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- jararaca/presentation/websocket/base_types.py,sha256=AvUeeZ1TFhSiRMcYqZU1HaQNqSrcgTkC5R0ArP5dGmA,146
38
- jararaca/presentation/websocket/context.py,sha256=090vJmO4bWt0Hr7MI-ZtRlVHTD2JW5JvZRJTFI9XGKs,1180
39
- jararaca/presentation/websocket/decorators.py,sha256=ZNd5aoA9UkyfHOt1C8D2Ffy2gQUNDEsusVnQuTgExgs,2157
40
- jararaca/presentation/websocket/redis.py,sha256=6wD4zGHftJXNDW3VfS65WJt2cnOgTI0zmQOfjZ_CEXE,4726
41
- jararaca/presentation/websocket/types.py,sha256=Crz88c1670YLtIhDvbeuyBV1SN-z9RtEGZxaonGvapY,294
42
- jararaca/presentation/websocket/websocket_interceptor.py,sha256=R_DfIMhi1ngFfCGy33b6yv_6LxCM-Dipkr12z6evfyk,8297
43
- jararaca/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
44
- jararaca/rpc/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
- jararaca/rpc/http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
- jararaca/rpc/http/backends/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- jararaca/rpc/http/backends/httpx.py,sha256=2inHnHYF5f7HiidkwlPOK7ZFpc1jBklKxvVRla9knCE,1141
48
- jararaca/rpc/http/backends/otel.py,sha256=Uc6CjHSCZ5hvnK1fNFv3ota5xzUFnvIl1JOpG380siA,807
49
- jararaca/rpc/http/decorators.py,sha256=oUSzgMGI8w6SoKiz3GltDbd3BWAuyY60F23cdRRNeiw,11897
50
- jararaca/rpc/http/httpx.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
- jararaca/scheduler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
52
- jararaca/scheduler/decorators.py,sha256=V6VtLA44HPEbevEcEGiHDHM3HZvka1P5kpvIm9nCMkc,2268
53
- jararaca/scheduler/scheduler.py,sha256=r1_OPTOsL9WkxTLBaxLiq1csujUqepvPg-8I4m28amU,4845
54
- jararaca/tools/app_config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
- jararaca/tools/app_config/decorators.py,sha256=-ckkMZ1dswOmECdo1rFrZ15UAku--txaNXMp8fd1Ndk,941
56
- jararaca/tools/app_config/interceptor.py,sha256=nfFZiS80hrbnL7-XEYrwmp2rwaVYBqxvqu3Y-6o_ov4,2575
57
- jararaca/tools/metadata.py,sha256=7nlCDYgItNybentPSSCc2MLqN7IpBd0VyQzfjfQycVI,1402
58
- jararaca/tools/typescript/interface_parser.py,sha256=4SHt094P-QawMFHSyMCiujQf8Niw7xACIO1RHBM8-w4,29192
59
- jararaca-0.2.37a12.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
60
- jararaca-0.2.37a12.dist-info/METADATA,sha256=W8aHUpqo5Q5iGBwX0BE4CS9MfEEMN97vM-YRuCJ2URM,4873
61
- jararaca-0.2.37a12.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
62
- jararaca-0.2.37a12.dist-info/entry_points.txt,sha256=WIh3aIvz8LwUJZIDfs4EeH3VoFyCGEk7cWJurW38q0I,45
63
- jararaca-0.2.37a12.dist-info/RECORD,,
File without changes