jararaca 0.2.37a9__tar.gz → 0.2.37a11__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.
Potentially problematic release.
This version of jararaca might be problematic. Click here for more details.
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/PKG-INFO +1 -1
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/pyproject.toml +1 -1
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/__init__.py +7 -0
- jararaca-0.2.37a11/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +131 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/decorators.py +53 -13
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/tools/typescript/interface_parser.py +15 -0
- jararaca-0.2.37a9/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -76
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/LICENSE +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/README.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/Message Bus/Decorators.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/Message Bus/Interceptors.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/Observability/Decorators.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/Observability/Interceptors.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/Presentation/Decorators.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/RPC/RestClients/Decorators.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/RPC/RestClients/Middlewared.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/Schedule/Decorators.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/Websocket/Decorators.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Architecture/Websocket/Interceptors.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Concept/Adapters.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Concept/Hexagonal Architecture.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/Concept/Ports.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/assets/tracing_example.png +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/index.md +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/__main__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/cli.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/common/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/core/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/core/providers.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/core/uow.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/di.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/files/entity.py.mako +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/lifecycle.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/messagebus/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/messagebus/bus_message_controller.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/messagebus/decorators.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/messagebus/publisher.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/messagebus/types.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/messagebus/worker.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/microservice.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/observability/decorators.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/observability/interceptor.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/observability/providers/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/observability/providers/otel.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/persistence/base.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/persistence/exports.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/persistence/interceptors/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/persistence/session.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/persistence/sort_filter.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/persistence/utilities.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/hooks.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/http_microservice.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/server.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/websocket/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/websocket/base_types.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/websocket/context.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/websocket/decorators.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/websocket/redis.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/websocket/types.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/py.typed +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/rpc/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/rpc/http/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/rpc/http/backends/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/rpc/http/backends/httpx.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/rpc/http/backends/otel.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/rpc/http/decorators.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/rpc/http/httpx.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/scheduler/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/scheduler/decorators.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/scheduler/scheduler.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/tools/app_config/__init__.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/tools/app_config/decorators.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/tools/app_config/interceptor.py +0 -0
- {jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/tools/metadata.py +0 -0
|
@@ -59,6 +59,7 @@ if TYPE_CHECKING:
|
|
|
59
59
|
from .messagebus.decorators import MessageBusController, MessageHandler
|
|
60
60
|
from .messagebus.interceptors.aiopika_publisher_interceptor import (
|
|
61
61
|
AIOPikaConnectionFactory,
|
|
62
|
+
GenericPoolConfig,
|
|
62
63
|
MessageBusPublisherInterceptor,
|
|
63
64
|
)
|
|
64
65
|
from .messagebus.publisher import use_publisher
|
|
@@ -192,6 +193,7 @@ if TYPE_CHECKING:
|
|
|
192
193
|
"Put",
|
|
193
194
|
"Delete",
|
|
194
195
|
"use_publisher",
|
|
196
|
+
"GenericPoolConfig",
|
|
195
197
|
"AIOPikaConnectionFactory",
|
|
196
198
|
"MessageBusPublisherInterceptor",
|
|
197
199
|
"RedisWebSocketConnectionBackend",
|
|
@@ -221,6 +223,11 @@ _dynamic_imports: "dict[str, tuple[str, str, str | None]]" = {
|
|
|
221
223
|
"messagebus.bus_message_controller",
|
|
222
224
|
None,
|
|
223
225
|
),
|
|
226
|
+
"GenericPoolConfig": (
|
|
227
|
+
__SPEC_PARENT__,
|
|
228
|
+
"messagebus.interceptors.aiopika_publisher_interceptor",
|
|
229
|
+
None,
|
|
230
|
+
),
|
|
224
231
|
"ack": (__SPEC_PARENT__, "messagebus.bus_message_controller", None),
|
|
225
232
|
"nack": (__SPEC_PARENT__, "messagebus.bus_message_controller", None),
|
|
226
233
|
"reject": (__SPEC_PARENT__, "messagebus.bus_message_controller", None),
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
from contextlib import asynccontextmanager
|
|
2
|
+
from typing import Any, AsyncContextManager, AsyncGenerator, Protocol
|
|
3
|
+
|
|
4
|
+
import aio_pika
|
|
5
|
+
from aio_pika.abc import AbstractConnection
|
|
6
|
+
from pydantic import BaseModel
|
|
7
|
+
|
|
8
|
+
from jararaca.messagebus.publisher import MessagePublisher, provide_message_publisher
|
|
9
|
+
from jararaca.microservice import AppContext, AppInterceptor
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MessageBusConnectionFactory(Protocol):
|
|
13
|
+
|
|
14
|
+
def provide_connection(self) -> AsyncContextManager[MessagePublisher]: ...
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MessageBusPublisherInterceptor(AppInterceptor):
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
connection_factory: MessageBusConnectionFactory,
|
|
22
|
+
connection_name: str = "default",
|
|
23
|
+
):
|
|
24
|
+
self.connection_factory = connection_factory
|
|
25
|
+
self.connection_name = connection_name
|
|
26
|
+
|
|
27
|
+
@asynccontextmanager
|
|
28
|
+
async def intercept(self, app_context: AppContext) -> AsyncGenerator[None, None]:
|
|
29
|
+
if app_context.context_type == "websocket":
|
|
30
|
+
yield
|
|
31
|
+
return
|
|
32
|
+
|
|
33
|
+
async with self.connection_factory.provide_connection() as connection:
|
|
34
|
+
with provide_message_publisher(self.connection_name, connection):
|
|
35
|
+
yield
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AIOPikaMessagePublisher(MessagePublisher):
|
|
39
|
+
|
|
40
|
+
def __init__(self, channel: aio_pika.abc.AbstractChannel, exchange_name: str):
|
|
41
|
+
self.channel = channel
|
|
42
|
+
self.exchange_name = exchange_name
|
|
43
|
+
|
|
44
|
+
async def publish(self, message: BaseModel, topic: str) -> None:
|
|
45
|
+
exchange = await self.channel.declare_exchange(
|
|
46
|
+
self.exchange_name,
|
|
47
|
+
type=aio_pika.ExchangeType.TOPIC,
|
|
48
|
+
)
|
|
49
|
+
routing_key = f"{self.exchange_name}.{topic}."
|
|
50
|
+
await exchange.publish(
|
|
51
|
+
aio_pika.Message(body=message.model_dump_json().encode()),
|
|
52
|
+
routing_key=routing_key,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class GenericPoolConfig(BaseModel):
|
|
57
|
+
max_size: int
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class AIOPikaConnectionFactory(MessageBusConnectionFactory):
|
|
61
|
+
|
|
62
|
+
def __init__(
|
|
63
|
+
self,
|
|
64
|
+
url: str,
|
|
65
|
+
exchange: str,
|
|
66
|
+
connection_pool_config: GenericPoolConfig | None = None,
|
|
67
|
+
channel_pool_config: GenericPoolConfig | None = None,
|
|
68
|
+
):
|
|
69
|
+
self.url = url
|
|
70
|
+
self.exchange = exchange
|
|
71
|
+
|
|
72
|
+
self.connection_pool: aio_pika.pool.Pool[AbstractConnection] | None = None
|
|
73
|
+
self.channel_pool: aio_pika.pool.Pool[aio_pika.abc.AbstractChannel] | None = (
|
|
74
|
+
None
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
if connection_pool_config:
|
|
78
|
+
|
|
79
|
+
async def get_connection() -> AbstractConnection:
|
|
80
|
+
return await aio_pika.connect_robust(self.url)
|
|
81
|
+
|
|
82
|
+
self.connection_pool = aio_pika.pool.Pool[AbstractConnection](
|
|
83
|
+
get_connection,
|
|
84
|
+
max_size=connection_pool_config.max_size,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if channel_pool_config:
|
|
88
|
+
|
|
89
|
+
async def get_channel() -> aio_pika.abc.AbstractChannel:
|
|
90
|
+
async with self.acquire_connection() as connection:
|
|
91
|
+
return await connection.channel(publisher_confirms=False)
|
|
92
|
+
|
|
93
|
+
self.channel_pool = aio_pika.pool.Pool[aio_pika.abc.AbstractChannel](
|
|
94
|
+
get_channel, max_size=channel_pool_config.max_size
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
@asynccontextmanager
|
|
98
|
+
async def acquire_connection(self) -> AsyncGenerator[AbstractConnection, Any]:
|
|
99
|
+
if not self.connection_pool:
|
|
100
|
+
async with await aio_pika.connect_robust(self.url) as connection:
|
|
101
|
+
yield connection
|
|
102
|
+
else:
|
|
103
|
+
|
|
104
|
+
async with self.connection_pool.acquire() as connection:
|
|
105
|
+
yield connection
|
|
106
|
+
|
|
107
|
+
@asynccontextmanager
|
|
108
|
+
async def acquire_channel(
|
|
109
|
+
self,
|
|
110
|
+
) -> AsyncGenerator[aio_pika.abc.AbstractChannel, Any]:
|
|
111
|
+
if not self.channel_pool:
|
|
112
|
+
async with self.acquire_connection() as connection:
|
|
113
|
+
yield await connection.channel(publisher_confirms=False)
|
|
114
|
+
else:
|
|
115
|
+
async with self.channel_pool.acquire() as channel:
|
|
116
|
+
yield channel
|
|
117
|
+
|
|
118
|
+
@asynccontextmanager
|
|
119
|
+
async def provide_connection(self) -> AsyncGenerator[AIOPikaMessagePublisher, Any]:
|
|
120
|
+
|
|
121
|
+
async with self.acquire_channel() as channel:
|
|
122
|
+
tx = channel.transaction()
|
|
123
|
+
|
|
124
|
+
await tx.select()
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
yield AIOPikaMessagePublisher(channel, exchange_name=self.exchange)
|
|
128
|
+
await tx.commit()
|
|
129
|
+
except Exception as e:
|
|
130
|
+
await tx.rollback()
|
|
131
|
+
raise e
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import inspect
|
|
2
|
-
from typing import Any, Callable, Protocol, TypeVar, cast
|
|
2
|
+
from typing import Any, Callable, Literal, Protocol, TypeVar, cast
|
|
3
3
|
|
|
4
4
|
from fastapi import APIRouter
|
|
5
5
|
from fastapi import Depends as DependsF
|
|
@@ -147,6 +147,16 @@ class RestController:
|
|
|
147
147
|
|
|
148
148
|
Options = dict[str, Any]
|
|
149
149
|
|
|
150
|
+
ResponseType = Literal[
|
|
151
|
+
"arraybuffer",
|
|
152
|
+
"blob",
|
|
153
|
+
"document",
|
|
154
|
+
"json",
|
|
155
|
+
"text",
|
|
156
|
+
"stream",
|
|
157
|
+
"formdata",
|
|
158
|
+
]
|
|
159
|
+
|
|
150
160
|
|
|
151
161
|
class HttpMapping:
|
|
152
162
|
|
|
@@ -154,11 +164,16 @@ class HttpMapping:
|
|
|
154
164
|
ORDER_COUNTER = 0
|
|
155
165
|
|
|
156
166
|
def __init__(
|
|
157
|
-
self,
|
|
167
|
+
self,
|
|
168
|
+
method: str,
|
|
169
|
+
path: str = "/",
|
|
170
|
+
adapter_options: Options | None = None,
|
|
171
|
+
response_type: ResponseType | None = None,
|
|
158
172
|
) -> None:
|
|
159
173
|
self.method = method
|
|
160
174
|
self.path = path
|
|
161
|
-
self.options =
|
|
175
|
+
self.options = adapter_options
|
|
176
|
+
self.response_type = response_type
|
|
162
177
|
|
|
163
178
|
HttpMapping.ORDER_COUNTER += 1
|
|
164
179
|
self.order = HttpMapping.ORDER_COUNTER
|
|
@@ -185,32 +200,57 @@ class HttpMapping:
|
|
|
185
200
|
|
|
186
201
|
class Post(HttpMapping):
|
|
187
202
|
|
|
188
|
-
def __init__(
|
|
189
|
-
|
|
203
|
+
def __init__(
|
|
204
|
+
self,
|
|
205
|
+
path: str = "/",
|
|
206
|
+
options: Options | None = None,
|
|
207
|
+
response_type: ResponseType | None = None,
|
|
208
|
+
) -> None:
|
|
209
|
+
super().__init__("POST", path, options, response_type)
|
|
190
210
|
|
|
191
211
|
|
|
192
212
|
class Get(HttpMapping):
|
|
193
213
|
|
|
194
|
-
def __init__(
|
|
195
|
-
|
|
214
|
+
def __init__(
|
|
215
|
+
self,
|
|
216
|
+
path: str = "/",
|
|
217
|
+
options: Options | None = None,
|
|
218
|
+
response_type: ResponseType | None = None,
|
|
219
|
+
) -> None:
|
|
220
|
+
super().__init__("GET", path, options, response_type)
|
|
196
221
|
|
|
197
222
|
|
|
198
223
|
class Put(HttpMapping):
|
|
199
224
|
|
|
200
|
-
def __init__(
|
|
201
|
-
|
|
225
|
+
def __init__(
|
|
226
|
+
self,
|
|
227
|
+
path: str = "/",
|
|
228
|
+
options: Options | None = None,
|
|
229
|
+
response_type: ResponseType | None = None,
|
|
230
|
+
) -> None:
|
|
231
|
+
super().__init__("PUT", path, options, response_type)
|
|
202
232
|
|
|
203
233
|
|
|
204
234
|
class Delete(HttpMapping):
|
|
205
235
|
|
|
206
|
-
def __init__(
|
|
207
|
-
|
|
236
|
+
def __init__(
|
|
237
|
+
self,
|
|
238
|
+
path: str = "/",
|
|
239
|
+
options: Options | None = None,
|
|
240
|
+
response_type: ResponseType | None = None,
|
|
241
|
+
) -> None:
|
|
242
|
+
super().__init__("DELETE", path, options, response_type)
|
|
208
243
|
|
|
209
244
|
|
|
210
245
|
class Patch(HttpMapping):
|
|
211
246
|
|
|
212
|
-
def __init__(
|
|
213
|
-
|
|
247
|
+
def __init__(
|
|
248
|
+
self,
|
|
249
|
+
path: str = "/",
|
|
250
|
+
options: Options | None = None,
|
|
251
|
+
response_type: ResponseType | None = None,
|
|
252
|
+
) -> None:
|
|
253
|
+
super().__init__("PATCH", path, options, response_type)
|
|
214
254
|
|
|
215
255
|
|
|
216
256
|
class UseMiddleware:
|
|
@@ -85,6 +85,8 @@ def parse_literal_value(value: Any) -> str:
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
def get_field_type_for_ts(field_type: Any) -> Any:
|
|
88
|
+
if field_type is Response:
|
|
89
|
+
return "unknown"
|
|
88
90
|
if field_type is Any:
|
|
89
91
|
return "any"
|
|
90
92
|
if field_type == UploadFile:
|
|
@@ -367,12 +369,23 @@ export type WebSocketMessageMap = {
|
|
|
367
369
|
|
|
368
370
|
final_buffer.write(
|
|
369
371
|
"""
|
|
372
|
+
export type ResponseType =
|
|
373
|
+
| "arraybuffer"
|
|
374
|
+
| "blob"
|
|
375
|
+
| "document"
|
|
376
|
+
| "json"
|
|
377
|
+
| "text"
|
|
378
|
+
| "stream"
|
|
379
|
+
| "formdata";
|
|
380
|
+
|
|
381
|
+
|
|
370
382
|
export interface HttpBackendRequest {
|
|
371
383
|
method: string;
|
|
372
384
|
path: string;
|
|
373
385
|
headers: { [key: string]: string };
|
|
374
386
|
query: { [key: string]: unknown };
|
|
375
387
|
body: unknown;
|
|
388
|
+
responseType?: ResponseType;
|
|
376
389
|
}
|
|
377
390
|
|
|
378
391
|
export interface HttpBackend {
|
|
@@ -491,6 +504,8 @@ def write_rest_controller_to_typescript_interface(
|
|
|
491
504
|
"const response = await this.httpBackend.request<%s>({ \n"
|
|
492
505
|
% return_value_repr
|
|
493
506
|
)
|
|
507
|
+
if mapping.response_type is not None:
|
|
508
|
+
class_buffer.write(f'\t\t\tresponseType: "{mapping.response_type}",\n')
|
|
494
509
|
class_buffer.write(f'\t\t\tmethod: "{mapping.method}",\n')
|
|
495
510
|
|
|
496
511
|
endpoint_path = parse_path_with_params(mapping.path, arg_params_spec)
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
from contextlib import asynccontextmanager
|
|
2
|
-
from typing import Any, AsyncContextManager, AsyncGenerator, Protocol
|
|
3
|
-
|
|
4
|
-
import aio_pika
|
|
5
|
-
from pydantic import BaseModel
|
|
6
|
-
|
|
7
|
-
from jararaca.messagebus.publisher import MessagePublisher, provide_message_publisher
|
|
8
|
-
from jararaca.microservice import AppContext, AppInterceptor
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class MessageBusConnectionFactory(Protocol):
|
|
12
|
-
|
|
13
|
-
def provide_connection(self) -> AsyncContextManager[MessagePublisher]: ...
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class MessageBusPublisherInterceptor(AppInterceptor):
|
|
17
|
-
|
|
18
|
-
def __init__(
|
|
19
|
-
self,
|
|
20
|
-
connection_factory: MessageBusConnectionFactory,
|
|
21
|
-
connection_name: str = "default",
|
|
22
|
-
):
|
|
23
|
-
self.connection_factory = connection_factory
|
|
24
|
-
self.connection_name = connection_name
|
|
25
|
-
|
|
26
|
-
@asynccontextmanager
|
|
27
|
-
async def intercept(self, app_context: AppContext) -> AsyncGenerator[None, None]:
|
|
28
|
-
async with self.connection_factory.provide_connection() as connection:
|
|
29
|
-
with provide_message_publisher(self.connection_name, connection):
|
|
30
|
-
yield
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class AIOPikaMessagePublisher(MessagePublisher):
|
|
34
|
-
|
|
35
|
-
def __init__(self, channel: aio_pika.abc.AbstractChannel, exchange_name: str):
|
|
36
|
-
self.channel = channel
|
|
37
|
-
self.exchange_name = exchange_name
|
|
38
|
-
|
|
39
|
-
async def publish(self, message: BaseModel, topic: str) -> None:
|
|
40
|
-
exchange = await self.channel.declare_exchange(
|
|
41
|
-
self.exchange_name,
|
|
42
|
-
type=aio_pika.ExchangeType.TOPIC,
|
|
43
|
-
)
|
|
44
|
-
routing_key = f"{self.exchange_name}.{topic}."
|
|
45
|
-
await exchange.publish(
|
|
46
|
-
aio_pika.Message(body=message.model_dump_json().encode()),
|
|
47
|
-
routing_key=routing_key,
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
class AIOPikaConnectionFactory(MessageBusConnectionFactory):
|
|
52
|
-
|
|
53
|
-
def __init__(
|
|
54
|
-
self,
|
|
55
|
-
url: str,
|
|
56
|
-
exchange: str,
|
|
57
|
-
):
|
|
58
|
-
self.url = url
|
|
59
|
-
self.exchange = exchange
|
|
60
|
-
|
|
61
|
-
@asynccontextmanager
|
|
62
|
-
async def provide_connection(self) -> AsyncGenerator[AIOPikaMessagePublisher, Any]:
|
|
63
|
-
connection = await aio_pika.connect_robust(self.url)
|
|
64
|
-
async with connection:
|
|
65
|
-
async with connection.channel(publisher_confirms=False) as channel:
|
|
66
|
-
|
|
67
|
-
tx = channel.transaction()
|
|
68
|
-
|
|
69
|
-
await tx.select()
|
|
70
|
-
|
|
71
|
-
try:
|
|
72
|
-
yield AIOPikaMessagePublisher(channel, exchange_name=self.exchange)
|
|
73
|
-
await tx.commit()
|
|
74
|
-
except Exception as e:
|
|
75
|
-
await tx.rollback()
|
|
76
|
-
raise e
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg
RENAMED
|
File without changes
|
{jararaca-0.2.37a9 → jararaca-0.2.37a11}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{jararaca-0.2.37a9 → jararaca-0.2.37a11}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py
RENAMED
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|