jararaca 0.3.12a22__tar.gz → 0.3.14__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.

Files changed (90) hide show
  1. {jararaca-0.3.12a22 → jararaca-0.3.14}/PKG-INFO +1 -1
  2. {jararaca-0.3.12a22 → jararaca-0.3.14}/pyproject.toml +1 -1
  3. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/__init__.py +8 -1
  4. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/worker.py +54 -50
  5. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/microservice.py +28 -0
  6. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/server.py +18 -36
  7. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/scheduler/beat_worker.py +14 -13
  8. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/tools/typescript/interface_parser.py +21 -1
  9. {jararaca-0.3.12a22 → jararaca-0.3.14}/LICENSE +0 -0
  10. {jararaca-0.3.12a22 → jararaca-0.3.14}/README.md +0 -0
  11. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/CNAME +0 -0
  12. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/architecture.md +0 -0
  13. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
  14. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
  15. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/assets/tracing_example.png +0 -0
  16. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/http-rpc.md +0 -0
  17. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/index.md +0 -0
  18. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/interceptors.md +0 -0
  19. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/messagebus.md +0 -0
  20. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/retry.md +0 -0
  21. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/scheduler.md +0 -0
  22. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/stylesheets/custom.css +0 -0
  23. {jararaca-0.3.12a22 → jararaca-0.3.14}/docs/websocket.md +0 -0
  24. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/__main__.py +0 -0
  25. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/broker_backend/__init__.py +0 -0
  26. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/broker_backend/mapper.py +0 -0
  27. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/broker_backend/redis_broker_backend.py +0 -0
  28. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/cli.py +0 -0
  29. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/common/__init__.py +0 -0
  30. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/core/__init__.py +0 -0
  31. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/core/providers.py +0 -0
  32. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/core/uow.py +0 -0
  33. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/di.py +0 -0
  34. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/files/entity.py.mako +0 -0
  35. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/lifecycle.py +0 -0
  36. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/__init__.py +0 -0
  37. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/bus_message_controller.py +0 -0
  38. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/consumers/__init__.py +0 -0
  39. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/decorators.py +0 -0
  40. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
  41. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -0
  42. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -0
  43. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/message.py +0 -0
  44. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/messagebus/publisher.py +0 -0
  45. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/observability/decorators.py +0 -0
  46. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/observability/interceptor.py +0 -0
  47. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/observability/providers/__init__.py +0 -0
  48. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/observability/providers/otel.py +0 -0
  49. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/base.py +0 -0
  50. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/exports.py +0 -0
  51. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/interceptors/__init__.py +0 -0
  52. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
  53. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/interceptors/constants.py +0 -0
  54. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/interceptors/decorators.py +0 -0
  55. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/session.py +0 -0
  56. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/sort_filter.py +0 -0
  57. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/persistence/utilities.py +0 -0
  58. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/__init__.py +0 -0
  59. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/decorators.py +0 -0
  60. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/hooks.py +0 -0
  61. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/http_microservice.py +0 -0
  62. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/websocket/__init__.py +0 -0
  63. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/websocket/base_types.py +0 -0
  64. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/websocket/context.py +0 -0
  65. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/websocket/decorators.py +0 -0
  66. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/websocket/redis.py +0 -0
  67. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/websocket/types.py +0 -0
  68. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
  69. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/py.typed +0 -0
  70. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/reflect/__init__.py +0 -0
  71. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/reflect/controller_inspect.py +0 -0
  72. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/reflect/metadata.py +0 -0
  73. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/rpc/__init__.py +0 -0
  74. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/rpc/http/__init__.py +0 -0
  75. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/rpc/http/backends/__init__.py +0 -0
  76. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/rpc/http/backends/httpx.py +0 -0
  77. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/rpc/http/backends/otel.py +0 -0
  78. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/rpc/http/decorators.py +0 -0
  79. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/rpc/http/httpx.py +0 -0
  80. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/scheduler/__init__.py +0 -0
  81. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/scheduler/decorators.py +0 -0
  82. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/scheduler/types.py +0 -0
  83. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/tools/app_config/__init__.py +0 -0
  84. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/tools/app_config/decorators.py +0 -0
  85. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/tools/app_config/interceptor.py +0 -0
  86. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/tools/typescript/__init__.py +0 -0
  87. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/tools/typescript/decorators.py +0 -0
  88. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/utils/__init__.py +0 -0
  89. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/utils/rabbitmq_utils.py +0 -0
  90. {jararaca-0.3.12a22 → jararaca-0.3.14}/src/jararaca/utils/retry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jararaca
3
- Version: 0.3.12a22
3
+ Version: 0.3.14
4
4
  Summary: A simple and fast API framework for Python
5
5
  Home-page: https://github.com/LuscasLeo/jararaca
6
6
  Author: Lucas S
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "jararaca"
3
- version = "0.3.12a22"
3
+ version = "0.3.14"
4
4
  description = "A simple and fast API framework for Python"
5
5
  authors = ["Lucas S <me@luscasleo.dev>"]
6
6
  readme = "README.md"
@@ -11,7 +11,12 @@ if TYPE_CHECKING:
11
11
  retry_later,
12
12
  use_bus_message_controller,
13
13
  )
14
- from jararaca.microservice import AppContext, AppInterceptor, AppTransactionContext
14
+ from jararaca.microservice import (
15
+ AppContext,
16
+ AppInterceptor,
17
+ AppTransactionContext,
18
+ use_app_type,
19
+ )
15
20
  from jararaca.observability.interceptor import ObservabilityInterceptor
16
21
  from jararaca.observability.providers.otel import OtelObservabilityProvider
17
22
  from jararaca.persistence.sort_filter import (
@@ -308,6 +313,7 @@ if TYPE_CHECKING:
308
313
  # Exception classes
309
314
  "TimeoutException",
310
315
  "AppTransactionContext",
316
+ "use_app_type",
311
317
  "AppContext",
312
318
  "ControllerMemberReflect",
313
319
  "ControllerReflect",
@@ -544,6 +550,7 @@ _dynamic_imports: "dict[str, tuple[str, str, str | None]]" = {
544
550
  "AppContext": (__SPEC_PARENT__, "microservice", None),
545
551
  "AppInterceptor": (__SPEC_PARENT__, "microservice", None),
546
552
  "AppTransactionContext": (__SPEC_PARENT__, "microservice", None),
553
+ "use_app_type": (__SPEC_PARENT__, "microservice", None),
547
554
  "ControllerMemberReflect": (__SPEC_PARENT__, "reflect.controller_inspect", None),
548
555
  "ControllerReflect": (__SPEC_PARENT__, "reflect.controller_inspect", None),
549
556
  }
@@ -58,6 +58,7 @@ from jararaca.microservice import (
58
58
  SchedulerTransactionData,
59
59
  ShutdownState,
60
60
  provide_shutdown_state,
61
+ providing_app_type,
61
62
  )
62
63
  from jararaca.scheduler.decorators import ScheduledActionData
63
64
  from jararaca.utils.rabbitmq_utils import RabbitmqUtils
@@ -1725,61 +1726,64 @@ class MessageBusWorker:
1725
1726
  async def start_async(self) -> None:
1726
1727
  all_message_handlers_set: MESSAGE_HANDLER_DATA_SET = set()
1727
1728
  all_scheduled_actions_set: SCHEDULED_ACTION_DATA_SET = set()
1728
- async with self.lifecycle():
1729
- for instance_class in self.app.controllers:
1730
- controller = MessageBusController.get_messagebus(instance_class)
1731
-
1732
- if controller is None:
1733
- continue
1734
-
1735
- instance: Any = self.container.get_by_type(instance_class)
1736
-
1737
- factory = controller.get_messagebus_factory()
1738
- handlers, schedulers = factory(instance)
1739
-
1740
- message_handler_data_map: dict[str, MessageHandlerData] = {}
1741
- all_scheduled_actions_set.update(schedulers)
1742
- for handler_data in handlers:
1743
- message_type = handler_data.spec.message_type
1744
- topic = message_type.MESSAGE_TOPIC
1745
-
1746
- # Filter handlers by name if specified
1747
- if (
1748
- self.handler_names is not None
1749
- and handler_data.spec.name is not None
1750
- ):
1751
- if handler_data.spec.name not in self.handler_names:
1752
- continue
1753
- elif (
1754
- self.handler_names is not None
1755
- and handler_data.spec.name is None
1756
- ):
1757
- # Skip handlers without names when filtering is requested
1758
- continue
1729
+ with providing_app_type("worker"):
1730
+ async with self.lifecycle():
1731
+ for instance_class in self.app.controllers:
1732
+ controller = MessageBusController.get_messagebus(instance_class)
1759
1733
 
1760
- if (
1761
- topic in message_handler_data_map
1762
- and message_type.MESSAGE_TYPE == "task"
1763
- ):
1764
- logger.warning(
1765
- "Task handler for topic '%s' already registered. Skipping"
1766
- % topic
1767
- )
1734
+ if controller is None:
1768
1735
  continue
1769
- message_handler_data_map[topic] = handler_data
1770
- all_message_handlers_set.add(handler_data)
1771
1736
 
1772
- broker_backend = get_message_broker_backend_from_url(url=self.backend_url)
1737
+ instance: Any = self.container.get_by_type(instance_class)
1773
1738
 
1774
- consumer = self._consumer = create_message_bus(
1775
- broker_url=self.broker_url,
1776
- broker_backend=broker_backend,
1777
- scheduled_actions=all_scheduled_actions_set,
1778
- message_handler_set=all_message_handlers_set,
1779
- uow_context_provider=self.uow_context_provider,
1780
- )
1739
+ factory = controller.get_messagebus_factory()
1740
+ handlers, schedulers = factory(instance)
1741
+
1742
+ message_handler_data_map: dict[str, MessageHandlerData] = {}
1743
+ all_scheduled_actions_set.update(schedulers)
1744
+ for handler_data in handlers:
1745
+ message_type = handler_data.spec.message_type
1746
+ topic = message_type.MESSAGE_TOPIC
1747
+
1748
+ # Filter handlers by name if specified
1749
+ if (
1750
+ self.handler_names is not None
1751
+ and handler_data.spec.name is not None
1752
+ ):
1753
+ if handler_data.spec.name not in self.handler_names:
1754
+ continue
1755
+ elif (
1756
+ self.handler_names is not None
1757
+ and handler_data.spec.name is None
1758
+ ):
1759
+ # Skip handlers without names when filtering is requested
1760
+ continue
1761
+
1762
+ if (
1763
+ topic in message_handler_data_map
1764
+ and message_type.MESSAGE_TYPE == "task"
1765
+ ):
1766
+ logger.warning(
1767
+ "Task handler for topic '%s' already registered. Skipping"
1768
+ % topic
1769
+ )
1770
+ continue
1771
+ message_handler_data_map[topic] = handler_data
1772
+ all_message_handlers_set.add(handler_data)
1773
+
1774
+ broker_backend = get_message_broker_backend_from_url(
1775
+ url=self.backend_url
1776
+ )
1777
+
1778
+ consumer = self._consumer = create_message_bus(
1779
+ broker_url=self.broker_url,
1780
+ broker_backend=broker_backend,
1781
+ scheduled_actions=all_scheduled_actions_set,
1782
+ message_handler_set=all_message_handlers_set,
1783
+ uow_context_provider=self.uow_context_provider,
1784
+ )
1781
1785
 
1782
- await consumer.consume()
1786
+ await consumer.consume()
1783
1787
 
1784
1788
  def start_sync(self) -> None:
1785
1789
 
@@ -59,6 +59,8 @@ class WebSocketTransactionData:
59
59
  context_type: Literal["websocket"] = "websocket"
60
60
 
61
61
 
62
+ APP_TYPE = Literal["http", "worker", "beat"]
63
+
62
64
  TransactionData = (
63
65
  MessageBusTransactionData
64
66
  | HttpTransactionData
@@ -367,6 +369,32 @@ def provide_shutdown_state(
367
369
  shutdown_state_ctx.reset(token)
368
370
 
369
371
 
372
+ app_type_ctx = ContextVar[APP_TYPE]("app_type")
373
+
374
+
375
+ def use_app_type() -> APP_TYPE:
376
+ """
377
+ Returns the current application type.
378
+ This function is used to access the application type in the context of an application transaction.
379
+ If no context is set, it raises a LookupError.
380
+ """
381
+ return app_type_ctx.get()
382
+
383
+
384
+ @contextmanager
385
+ def providing_app_type(app_type: APP_TYPE) -> Generator[None, None, None]:
386
+ """
387
+ Context manager to provide the application type.
388
+ This is used to set the application type for the current transaction.
389
+ """
390
+ token = app_type_ctx.set(app_type)
391
+ try:
392
+ yield
393
+ finally:
394
+ with suppress(ValueError):
395
+ app_type_ctx.reset(token)
396
+
397
+
370
398
  __all__ = [
371
399
  "AppTransactionContext",
372
400
  "AppInterceptor",
@@ -17,6 +17,7 @@ from jararaca.microservice import (
17
17
  ShutdownState,
18
18
  WebSocketTransactionData,
19
19
  provide_shutdown_state,
20
+ providing_app_type,
20
21
  )
21
22
  from jararaca.presentation.decorators import RestController
22
23
  from jararaca.presentation.http_microservice import HttpMicroservice
@@ -37,49 +38,30 @@ class HttpAppLifecycle:
37
38
 
38
39
  @asynccontextmanager
39
40
  async def __call__(self, api: FastAPI) -> AsyncGenerator[None, None]:
40
- async with self.lifecycle():
41
+ with providing_app_type("http"):
42
+ async with self.lifecycle():
41
43
 
42
- # websocket_interceptors = [
43
- # interceptor
44
- # for interceptor in self.lifecycle.initialized_interceptors
45
- # if isinstance(interceptor, WebSocketInterceptor)
46
- # ]
44
+ for controller_t in self.lifecycle.app.controllers:
45
+ controller = RestController.get_controller(controller_t)
47
46
 
48
- # for interceptor in websocket_interceptors:
49
- # router = interceptor.get_ws_router(
50
- # self.lifecycle.app, self.lifecycle.container, self.uow_provider
51
- # )
47
+ if controller is None:
48
+ continue
52
49
 
53
- # api.include_router(router)
50
+ instance: Any = self.lifecycle.container.get_by_type(controller_t)
54
51
 
55
- for controller_t in self.lifecycle.app.controllers:
56
- controller = RestController.get_controller(controller_t)
52
+ router = controller.get_router_factory()(self.lifecycle, instance)
57
53
 
58
- if controller is None:
59
- continue
54
+ api.include_router(router)
60
55
 
61
- instance: Any = self.lifecycle.container.get_by_type(controller_t)
56
+ for middleware in self.http_app.middlewares:
57
+ middleware_instance = self.lifecycle.container.get_by_type(
58
+ middleware
59
+ )
60
+ api.router.dependencies.append(
61
+ Depends(middleware_instance.intercept)
62
+ )
62
63
 
63
- # dependencies: list[DependsCls] = []
64
- # for middleware in controller.middlewares:
65
- # middleware_instance = self.lifecycle.container.get_by_type(
66
- # middleware
67
- # )
68
- # dependencies.append(Depends(middleware_instance.intercept))
69
-
70
- router = controller.get_router_factory()(self.lifecycle, instance)
71
-
72
- api.include_router(router)
73
-
74
- for middleware in self.http_app.middlewares:
75
- middleware_instance = self.lifecycle.container.get_by_type(
76
- middleware
77
- )
78
- api.router.dependencies.append(
79
- Depends(middleware_instance.intercept)
80
- )
81
-
82
- yield
64
+ yield
83
65
 
84
66
 
85
67
  class HttpShutdownState(ShutdownState):
@@ -31,7 +31,7 @@ from jararaca.broker_backend.mapper import get_message_broker_backend_from_url
31
31
  from jararaca.core.uow import UnitOfWorkContextProvider
32
32
  from jararaca.di import Container
33
33
  from jararaca.lifecycle import AppLifecycle
34
- from jararaca.microservice import Microservice
34
+ from jararaca.microservice import Microservice, providing_app_type
35
35
  from jararaca.scheduler.decorators import (
36
36
  ScheduledAction,
37
37
  ScheduledActionData,
@@ -572,22 +572,23 @@ class BeatWorker:
572
572
  Declares the scheduled actions and starts the scheduler.
573
573
  This is the main entry point for the scheduler.
574
574
  """
575
- async with self.lifecycle():
575
+ with providing_app_type("beat"):
576
+ async with self.lifecycle():
576
577
 
577
- scheduled_actions = _extract_scheduled_actions(
578
- self.app, self.container, self.scheduler_names
579
- )
578
+ scheduled_actions = _extract_scheduled_actions(
579
+ self.app, self.container, self.scheduler_names
580
+ )
580
581
 
581
- # Initialize and wait for connection to be established
582
- logger.info("Initializing broker connection...")
583
- await self.broker.initialize(scheduled_actions)
582
+ # Initialize and wait for connection to be established
583
+ logger.info("Initializing broker connection...")
584
+ await self.broker.initialize(scheduled_actions)
584
585
 
585
- # Wait for connection to be healthy before starting scheduler
586
- logger.info("Waiting for connection to be established...")
587
- await self._wait_for_broker_connection()
586
+ # Wait for connection to be healthy before starting scheduler
587
+ logger.info("Waiting for connection to be established...")
588
+ await self._wait_for_broker_connection()
588
589
 
589
- logger.info("Connection established, starting scheduler...")
590
- await self.run_scheduled_actions(scheduled_actions)
590
+ logger.info("Connection established, starting scheduler...")
591
+ await self.run_scheduled_actions(scheduled_actions)
591
592
 
592
593
  async def run_scheduled_actions(
593
594
  self, scheduled_actions: list[ScheduledActionData]
@@ -26,7 +26,7 @@ from uuid import UUID
26
26
  from fastapi import Request, Response, UploadFile
27
27
  from fastapi.params import Body, Cookie, Depends, Form, Header, Path, Query
28
28
  from fastapi.security.http import HTTPBase
29
- from pydantic import BaseModel, PlainValidator
29
+ from pydantic import BaseModel, PlainValidator, RootModel
30
30
  from pydantic_core import PydanticUndefined
31
31
 
32
32
  from jararaca.microservice import Microservice
@@ -314,6 +314,26 @@ def get_field_type_for_ts(field_type: Any, context_suffix: str = "") -> Any:
314
314
  field_type: The Python type to convert
315
315
  context_suffix: Suffix for split models (e.g., "Input", "Output")
316
316
  """
317
+ # Handle RootModel types - use the wrapped type directly
318
+ if inspect.isclass(field_type) and issubclass(field_type, RootModel):
319
+ # For concrete RootModel subclasses, get the wrapped type from annotations
320
+ if (
321
+ hasattr(field_type, "__annotations__")
322
+ and "root" in field_type.__annotations__
323
+ ):
324
+ wrapped_type = field_type.__annotations__["root"]
325
+ return get_field_type_for_ts(wrapped_type, context_suffix)
326
+
327
+ # For parameterized RootModel[T] types, get the type from pydantic metadata
328
+ if hasattr(field_type, "__pydantic_generic_metadata__"):
329
+ metadata = field_type.__pydantic_generic_metadata__
330
+ if metadata.get("origin") is RootModel and metadata.get("args"):
331
+ # Get the first (and only) type argument
332
+ wrapped_type = metadata["args"][0]
333
+ return get_field_type_for_ts(wrapped_type, context_suffix)
334
+
335
+ return "unknown"
336
+
317
337
  if field_type is Response:
318
338
  return "unknown"
319
339
  if field_type is Any:
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes