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
@@ -0,0 +1,42 @@
1
+ # SPDX-FileCopyrightText: 2025 Lucas S
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ from contextlib import asynccontextmanager
6
+ from typing import AsyncContextManager, AsyncGenerator, Protocol
7
+
8
+ from jararaca.broker_backend import MessageBrokerBackend
9
+ from jararaca.messagebus.publisher import MessagePublisher, provide_message_publisher
10
+ from jararaca.microservice import AppInterceptor, AppTransactionContext
11
+
12
+
13
+ class MessageBusConnectionFactory(Protocol):
14
+
15
+ def provide_connection(self) -> AsyncContextManager[MessagePublisher]: ...
16
+
17
+
18
+ class MessageBusPublisherInterceptor(AppInterceptor):
19
+
20
+ def __init__(
21
+ self,
22
+ connection_factory: MessageBusConnectionFactory,
23
+ connection_name: str = "default",
24
+ message_scheduler: MessageBrokerBackend | None = None,
25
+ ):
26
+ self.connection_factory = connection_factory
27
+ self.connection_name = connection_name
28
+ self.message_scheduler = message_scheduler
29
+
30
+ @asynccontextmanager
31
+ async def intercept(
32
+ self, app_context: AppTransactionContext
33
+ ) -> AsyncGenerator[None, None]:
34
+ if app_context.transaction_data.context_type == "websocket":
35
+ yield
36
+ return
37
+
38
+ async with self.connection_factory.provide_connection() as connection:
39
+ with provide_message_publisher(self.connection_name, connection):
40
+ yield
41
+
42
+ await connection.flush()
@@ -0,0 +1,31 @@
1
+ # SPDX-FileCopyrightText: 2025 Lucas S
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ from datetime import datetime, tzinfo
6
+ from typing import Generic, Protocol, TypeVar
7
+
8
+ from jararaca.messagebus.publisher import IMessage, use_publisher
9
+
10
+
11
+ class Message(IMessage):
12
+
13
+ async def publish(self) -> None:
14
+ task_publisher = use_publisher()
15
+ await task_publisher.publish(self, self.MESSAGE_TOPIC)
16
+
17
+ async def delay(self, seconds: int) -> None:
18
+ task_publisher = use_publisher()
19
+ await task_publisher.delay(self, seconds)
20
+
21
+ async def schedule(self, when: datetime, tz: tzinfo) -> None:
22
+ task_publisher = use_publisher()
23
+ await task_publisher.schedule(self, when, tz)
24
+
25
+
26
+ INHERITS_MESSAGE_CO = TypeVar("INHERITS_MESSAGE_CO", bound=Message, covariant=True)
27
+
28
+
29
+ class MessageOf(Protocol, Generic[INHERITS_MESSAGE_CO]):
30
+
31
+ def payload(self) -> INHERITS_MESSAGE_CO: ...
@@ -1,13 +1,56 @@
1
+ # SPDX-FileCopyrightText: 2025 Lucas S
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ from abc import ABC, abstractmethod
1
6
  from contextlib import contextmanager, suppress
2
7
  from contextvars import ContextVar
3
- from typing import Any, Generator, Protocol
8
+ from datetime import datetime, tzinfo
9
+ from typing import Any, ClassVar, Generator, Literal
4
10
 
5
11
  from pydantic import BaseModel
6
12
 
7
13
 
8
- class MessagePublisher(Protocol):
9
- async def publish(self, message: BaseModel, topic: str) -> None:
10
- raise NotImplementedError()
14
+ class IMessage(BaseModel):
15
+ """
16
+ Base class for messages representing tasks.
17
+ A Task is a message that represents a unit of work to be done.
18
+ It is published to a TaskPublisher and consumed by a TaskHandler, wrapped in TaskData.
19
+ Note: A Task is not an Event.
20
+ """
21
+
22
+ MESSAGE_TOPIC: ClassVar[str] = "__unset__"
23
+
24
+ MESSAGE_TYPE: ClassVar[Literal["task", "event"]] = "task"
25
+
26
+ MESSAGE_CATEGORY: ClassVar[str] = "uncategorized"
27
+
28
+
29
+ class MessagePublisher(ABC):
30
+ @abstractmethod
31
+ async def publish(self, message: IMessage, topic: str) -> None:
32
+ pass
33
+
34
+ @abstractmethod
35
+ async def delay(self, message: IMessage, seconds: int) -> None:
36
+ """
37
+ Delay the message for a given number of seconds.
38
+ """
39
+
40
+ @abstractmethod
41
+ async def schedule(
42
+ self, message: IMessage, when: datetime, timezone: tzinfo
43
+ ) -> None:
44
+ """
45
+ Schedule the message for a given datetime.
46
+ """
47
+
48
+ @abstractmethod
49
+ async def flush(self) -> None:
50
+ """
51
+ Publish all messages that have been delayed or scheduled.
52
+ This is typically called at the end of a request or task processing.
53
+ """
11
54
 
12
55
 
13
56
  message_publishers_ctx = ContextVar[dict[str, MessagePublisher]](