tigrbl-runtime 0.4.5.dev1__py3-none-any.whl → 0.4.5.dev6__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.
- tigrbl_runtime/channel/_asgi_jsonrpc.py +11 -0
- tigrbl_runtime/channel/_asgi_send.py +79 -5
- tigrbl_runtime/channel/_asgi_webtransport.py +31 -4
- tigrbl_runtime/executors/ctx/context.py +1 -5
- tigrbl_runtime/executors/ctx/hot_namespace_values.py +200 -0
- tigrbl_runtime/executors/ctx/hot_namespaces.py +6 -187
- tigrbl_runtime/executors/packed/__init__.py +4 -0
- tigrbl_runtime/executors/packed/_shared.py +168 -0
- tigrbl_runtime/executors/packed/batch.py +337 -0
- tigrbl_runtime/executors/packed/error_edges.py +303 -0
- tigrbl_runtime/executors/packed/execute.py +368 -0
- tigrbl_runtime/executors/packed/executor.py +86 -0
- tigrbl_runtime/executors/packed/hot_access.py +222 -0
- tigrbl_runtime/executors/packed/hot_context.py +301 -0
- tigrbl_runtime/executors/packed/input_compile.py +336 -0
- tigrbl_runtime/executors/packed/input_extract.py +310 -0
- tigrbl_runtime/executors/packed/request_select.py +209 -0
- tigrbl_runtime/executors/packed/route_select.py +397 -0
- tigrbl_runtime/executors/packed/route_select_websocket.py +34 -0
- tigrbl_runtime/executors/packed/runner_resolve.py +379 -0
- tigrbl_runtime/executors/packed/segments.py +337 -0
- tigrbl_runtime/lowering_services.py +22 -0
- {tigrbl_runtime-0.4.5.dev1.dist-info → tigrbl_runtime-0.4.5.dev6.dist-info}/METADATA +21 -16
- {tigrbl_runtime-0.4.5.dev1.dist-info → tigrbl_runtime-0.4.5.dev6.dist-info}/RECORD +27 -11
- {tigrbl_runtime-0.4.5.dev1.dist-info → tigrbl_runtime-0.4.5.dev6.dist-info}/WHEEL +1 -1
- tigrbl_runtime/executors/packed.py +0 -3591
- {tigrbl_runtime-0.4.5.dev1.dist-info → tigrbl_runtime-0.4.5.dev6.dist-info}/licenses/LICENSE +0 -0
- {tigrbl_runtime-0.4.5.dev1.dist-info → tigrbl_runtime-0.4.5.dev6.dist-info}/licenses/NOTICE +0 -0
|
@@ -36,3 +36,14 @@ def _resolve_jsonrpc_endpoint(ctx: Any, channel: OpChannel) -> str | None:
|
|
|
36
36
|
if path == _normalize_path(mapped_path):
|
|
37
37
|
return endpoint
|
|
38
38
|
return None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
_NO_ERROR_DATA = object()
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _jsonrpc_error_payload(code: int, message: str, request_id: Any, *, data: Any = _NO_ERROR_DATA) -> dict[str, Any]:
|
|
45
|
+
"""Construct the existing compatibility error envelope without choosing policy."""
|
|
46
|
+
error: dict[str, Any] = {"code": code, "message": message}
|
|
47
|
+
if data is not _NO_ERROR_DATA:
|
|
48
|
+
error["data"] = data
|
|
49
|
+
return {"jsonrpc": "2.0", "error": error, "id": request_id}
|
|
@@ -19,6 +19,52 @@ from ._asgi_webtransport import (
|
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def _webtransport_event_projection(ctx: Any) -> Mapping[str, Any]:
|
|
23
|
+
projection = ctx.get("channel_event_projection")
|
|
24
|
+
if isinstance(projection, Mapping):
|
|
25
|
+
return projection
|
|
26
|
+
channel = ctx.get("channel")
|
|
27
|
+
state = getattr(channel, "state", None) if channel is not None else None
|
|
28
|
+
if isinstance(state, dict):
|
|
29
|
+
projection = state.get("event_projection")
|
|
30
|
+
if isinstance(projection, Mapping):
|
|
31
|
+
return projection
|
|
32
|
+
return {}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _is_receive_only_webtransport_stream(ctx: Any) -> bool:
|
|
36
|
+
projection = _webtransport_event_projection(ctx)
|
|
37
|
+
if (
|
|
38
|
+
projection.get("lane") == "unidi_client_stream"
|
|
39
|
+
or projection.get("exchange") == "client_stream"
|
|
40
|
+
):
|
|
41
|
+
return True
|
|
42
|
+
message = ctx.get("channel_message")
|
|
43
|
+
return bool(
|
|
44
|
+
isinstance(message, Mapping)
|
|
45
|
+
and message.get("type") == "webtransport.stream.receive"
|
|
46
|
+
and message.get("stream_direction") == "client_to_server"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _validate_receive_only_webtransport_output(payload: Any) -> None:
|
|
51
|
+
if payload is None:
|
|
52
|
+
return
|
|
53
|
+
if not isinstance(payload, Mapping) or not any(
|
|
54
|
+
key in payload
|
|
55
|
+
for key in ("bidirectional_streams", "unidirectional_streams", "datagrams")
|
|
56
|
+
):
|
|
57
|
+
raise ValueError(
|
|
58
|
+
"cannot automatically reply on a client_to_server WebTransport stream; "
|
|
59
|
+
"return None or emit an explicit server_to_client stream or datagram"
|
|
60
|
+
)
|
|
61
|
+
if payload.get("bidirectional_streams"):
|
|
62
|
+
raise ValueError(
|
|
63
|
+
"bidirectional_streams output is invalid for a client_to_server "
|
|
64
|
+
"WebTransport stream; use unidirectional_streams or datagrams"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
22
68
|
async def _send_session_payload(
|
|
23
69
|
env: Any,
|
|
24
70
|
payload: Any,
|
|
@@ -87,11 +133,15 @@ async def _send_webtransport_payload(env: Any, ctx: Any, payload: Any) -> None:
|
|
|
87
133
|
for key in ("bidirectional_streams", "unidirectional_streams", "datagrams")
|
|
88
134
|
)
|
|
89
135
|
if structured_payload:
|
|
90
|
-
if
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
136
|
+
if (
|
|
137
|
+
message_type
|
|
138
|
+
in {
|
|
139
|
+
"webtransport.stream.receive",
|
|
140
|
+
"webtransport.datagram.receive",
|
|
141
|
+
}
|
|
142
|
+
and message not in queue
|
|
143
|
+
):
|
|
144
|
+
queue.append(message)
|
|
95
145
|
if not queue:
|
|
96
146
|
raise ValueError(
|
|
97
147
|
"structured WebTransport payloads require inbound stream.receive or datagram.receive events"
|
|
@@ -125,6 +175,12 @@ async def _send_webtransport_payload(env: Any, ctx: Any, payload: Any) -> None:
|
|
|
125
175
|
)
|
|
126
176
|
if payload is not None:
|
|
127
177
|
base = {**message, "session_id": session_id}
|
|
178
|
+
temp = getattr(ctx, "temp", None)
|
|
179
|
+
dispatch = temp.get("dispatch") if isinstance(temp, Mapping) else None
|
|
180
|
+
if isinstance(dispatch, Mapping):
|
|
181
|
+
request = dispatch.get("rpc") or dispatch.get("rpc_envelope")
|
|
182
|
+
if isinstance(request, Mapping) and request.get("id") is not None:
|
|
183
|
+
base["jsonrpc_request_id"] = request.get("id")
|
|
128
184
|
if structured_payload:
|
|
129
185
|
for event in _webtransport_structured_payload_events(
|
|
130
186
|
session_id=session_id,
|
|
@@ -151,6 +207,14 @@ async def _send_webtransport_payload(env: Any, ctx: Any, payload: Any) -> None:
|
|
|
151
207
|
)
|
|
152
208
|
await _run_webtransport_hooks(env, ctx, direction="send", message=event)
|
|
153
209
|
await send(event)
|
|
210
|
+
if isinstance(state, dict):
|
|
211
|
+
raw_queue = state.get("receive_queue")
|
|
212
|
+
consumed = min(len(queue), len(raw_queue or ()))
|
|
213
|
+
if isinstance(raw_queue, deque):
|
|
214
|
+
for _ in range(consumed):
|
|
215
|
+
raw_queue.popleft()
|
|
216
|
+
elif isinstance(raw_queue, list):
|
|
217
|
+
del raw_queue[:consumed]
|
|
154
218
|
else:
|
|
155
219
|
event = _webtransport_payload_event(base=base, payload=payload)
|
|
156
220
|
if isinstance(session, WebTransportSessionState):
|
|
@@ -222,6 +286,16 @@ async def send_transport_via_channel(env: Any, ctx: Any) -> None:
|
|
|
222
286
|
if payload is None:
|
|
223
287
|
payload = getattr(ctx, "result", None)
|
|
224
288
|
if scope_type == "webtransport":
|
|
289
|
+
if _is_receive_only_webtransport_stream(ctx):
|
|
290
|
+
_validate_receive_only_webtransport_output(payload)
|
|
291
|
+
if payload is None:
|
|
292
|
+
if isinstance(state, dict):
|
|
293
|
+
state["egress_disposition"] = "suppressed_receive_only"
|
|
294
|
+
state["emitted"] = False
|
|
295
|
+
if isinstance(egress, dict):
|
|
296
|
+
egress["response_suppressed"] = True
|
|
297
|
+
egress["suppression_reason"] = "receive_only_stream"
|
|
298
|
+
return
|
|
225
299
|
await _send_webtransport_payload(env, ctx, payload)
|
|
226
300
|
else:
|
|
227
301
|
await _send_session_payload(
|
|
@@ -15,9 +15,12 @@ from tigrbl_kernel.channel_taxonomy import (
|
|
|
15
15
|
webtransport_event_metadata as _webtransport_event_metadata,
|
|
16
16
|
)
|
|
17
17
|
from tigrbl_kernel.webtransport_events import validate_webtransport_event_payload
|
|
18
|
+
from tigrbl_kernel.webtransport_session_plan import WebTransportSessionPlan
|
|
18
19
|
from tigrbl_atoms.runtime_channel import WebTransportSessionState
|
|
19
20
|
from tigrbl_typing.channel import OpChannel
|
|
20
21
|
|
|
22
|
+
MAX_EAGER_DRAIN_EVENTS = 16
|
|
23
|
+
|
|
21
24
|
|
|
22
25
|
def _webtransport_scope_state(env: Any) -> dict[str, Any]:
|
|
23
26
|
scope = getattr(env, "scope", {}) or {}
|
|
@@ -242,6 +245,20 @@ async def _receive_webtransport_session_messages(
|
|
|
242
245
|
queue: deque[Mapping[str, Any]] = deque()
|
|
243
246
|
session: WebTransportSessionState | None = None
|
|
244
247
|
|
|
248
|
+
session_plan = shared_state.get("session_plan")
|
|
249
|
+
if not isinstance(session_plan, WebTransportSessionPlan):
|
|
250
|
+
session_plan = WebTransportSessionPlan()
|
|
251
|
+
shared_state["session_plan"] = session_plan
|
|
252
|
+
|
|
253
|
+
async def _receive_record_or_event() -> Mapping[str, Any]:
|
|
254
|
+
if session_plan.has_pending():
|
|
255
|
+
return session_plan.pop_pending()
|
|
256
|
+
while True:
|
|
257
|
+
raw = _enrich_webtransport_message(env, await receive())
|
|
258
|
+
session_plan.project_receive(raw)
|
|
259
|
+
if session_plan.has_pending():
|
|
260
|
+
return session_plan.pop_pending()
|
|
261
|
+
|
|
245
262
|
def _ensure_session(message: Mapping[str, Any]) -> WebTransportSessionState | None:
|
|
246
263
|
nonlocal session
|
|
247
264
|
session_id = message.get("session_id") or _webtransport_scope_session_id(env)
|
|
@@ -292,6 +309,8 @@ async def _receive_webtransport_session_messages(
|
|
|
292
309
|
channel="receive",
|
|
293
310
|
payload={**message, "session_id": state.get("session_id")},
|
|
294
311
|
)
|
|
312
|
+
state["event_projection"] = dict(projection)
|
|
313
|
+
ctx["channel_event_projection"] = dict(projection)
|
|
295
314
|
if current_session is not None:
|
|
296
315
|
current_session.apply_event(
|
|
297
316
|
event=message_type,
|
|
@@ -334,18 +353,26 @@ async def _receive_webtransport_session_messages(
|
|
|
334
353
|
return
|
|
335
354
|
ctx["channel_message"] = message
|
|
336
355
|
|
|
337
|
-
message = await
|
|
356
|
+
message = await _receive_record_or_event()
|
|
338
357
|
await _record_payload_message(message)
|
|
339
358
|
if message.get("type") == "webtransport.connect":
|
|
340
359
|
if "channel_message" not in ctx:
|
|
341
|
-
message = await
|
|
360
|
+
message = await _receive_record_or_event()
|
|
342
361
|
await _record_payload_message(message)
|
|
343
362
|
|
|
344
|
-
|
|
363
|
+
drained_events = 0
|
|
364
|
+
while (
|
|
365
|
+
shared_state.get("eager_drain") is True
|
|
366
|
+
and not state.get("disconnected")
|
|
367
|
+
and drained_events < MAX_EAGER_DRAIN_EVENTS
|
|
368
|
+
):
|
|
345
369
|
try:
|
|
346
|
-
message = await asyncio.wait_for(
|
|
370
|
+
message = await asyncio.wait_for(
|
|
371
|
+
_receive_record_or_event(), timeout=0.001
|
|
372
|
+
)
|
|
347
373
|
except TimeoutError:
|
|
348
374
|
break
|
|
349
375
|
await _record_payload_message(message)
|
|
376
|
+
drained_events += 1
|
|
350
377
|
|
|
351
378
|
state["receive_queue"] = queue
|
|
@@ -16,11 +16,7 @@ from typing import (
|
|
|
16
16
|
runtime_checkable,
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
from sqlalchemy.ext.asyncio import AsyncSession
|
|
21
|
-
from sqlalchemy.orm import Session
|
|
22
|
-
except Exception: # pragma: no cover - optional ORM dependency for runtime typing
|
|
23
|
-
AsyncSession = Session = Any # type: ignore[assignment]
|
|
19
|
+
AsyncSession = Session = Any # type: ignore[assignment]
|
|
24
20
|
|
|
25
21
|
from tigrbl_atoms.types import BaseCtx
|
|
26
22
|
from tigrbl_base._base import AttrDict
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Mapping as ABCMapping
|
|
4
|
+
from typing import Any, Mapping
|
|
5
|
+
|
|
6
|
+
from .hot_state import (
|
|
7
|
+
HotCtx,
|
|
8
|
+
_ensure_hot_assembled_values_view,
|
|
9
|
+
_ensure_hot_in_values_view,
|
|
10
|
+
_ensure_hot_virtual_in_view,
|
|
11
|
+
_LAZY_MISSING,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _coerce_optional_dict(value: Any) -> dict[str, Any] | None:
|
|
16
|
+
if isinstance(value, dict):
|
|
17
|
+
return value
|
|
18
|
+
if isinstance(value, ABCMapping):
|
|
19
|
+
return dict(value)
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _namespace_lazy_value(kind: str, hot: HotCtx, key: str) -> Any:
|
|
24
|
+
if kind == "route":
|
|
25
|
+
if key == "selector":
|
|
26
|
+
value = hot.route_selector
|
|
27
|
+
return value if value else _LAZY_MISSING
|
|
28
|
+
if key == "protocol":
|
|
29
|
+
value = hot.route_protocol
|
|
30
|
+
return value if value else _LAZY_MISSING
|
|
31
|
+
if key == "program_id":
|
|
32
|
+
value = (
|
|
33
|
+
hot.route_program_id if hot.route_program_id >= 0 else hot.program_id
|
|
34
|
+
)
|
|
35
|
+
return value if value >= 0 else _LAZY_MISSING
|
|
36
|
+
if key == "opmeta_index":
|
|
37
|
+
value = (
|
|
38
|
+
hot.route_opmeta_index
|
|
39
|
+
if hot.route_opmeta_index >= 0
|
|
40
|
+
else hot.route_program_id
|
|
41
|
+
)
|
|
42
|
+
return value if value >= 0 else _LAZY_MISSING
|
|
43
|
+
if key == "method_not_allowed":
|
|
44
|
+
return True if hot.route_method_not_allowed else _LAZY_MISSING
|
|
45
|
+
if key == "short_circuit":
|
|
46
|
+
return True if hot.route_short_circuit else _LAZY_MISSING
|
|
47
|
+
if key == "payload":
|
|
48
|
+
if hot.route_payload is not None:
|
|
49
|
+
return hot.route_payload
|
|
50
|
+
value = _ensure_hot_in_values_view(hot)
|
|
51
|
+
return value if value is not None else _LAZY_MISSING
|
|
52
|
+
if key == "path_params":
|
|
53
|
+
value = hot.route_path_params or hot.path_params
|
|
54
|
+
return value if value is not None else _LAZY_MISSING
|
|
55
|
+
if key == "rpc_envelope":
|
|
56
|
+
value = hot.route_rpc_envelope or hot.dispatch_rpc_envelope
|
|
57
|
+
return value if value is not None else _LAZY_MISSING
|
|
58
|
+
return _LAZY_MISSING
|
|
59
|
+
if kind == "dispatch":
|
|
60
|
+
if key == "binding_protocol":
|
|
61
|
+
value = hot.dispatch_binding_protocol
|
|
62
|
+
return value if value else _LAZY_MISSING
|
|
63
|
+
if key == "binding_selector":
|
|
64
|
+
value = hot.dispatch_binding_selector
|
|
65
|
+
return value if value else _LAZY_MISSING
|
|
66
|
+
if key == "channel_protocol":
|
|
67
|
+
value = hot.dispatch_channel_protocol
|
|
68
|
+
return value if value else _LAZY_MISSING
|
|
69
|
+
if key == "channel_selector":
|
|
70
|
+
value = hot.dispatch_channel_selector
|
|
71
|
+
return value if value else _LAZY_MISSING
|
|
72
|
+
if key in {"normalized_input", "parsed_payload"}:
|
|
73
|
+
value = _ensure_hot_in_values_view(hot)
|
|
74
|
+
return value if value is not None else _LAZY_MISSING
|
|
75
|
+
if key == "rpc":
|
|
76
|
+
value = hot.dispatch_rpc_envelope or hot.route_rpc_envelope
|
|
77
|
+
return value if value is not None else _LAZY_MISSING
|
|
78
|
+
if key == "rpc_method":
|
|
79
|
+
value = hot.dispatch_rpc_method
|
|
80
|
+
return value if value is not None else _LAZY_MISSING
|
|
81
|
+
return _LAZY_MISSING
|
|
82
|
+
if kind == "egress":
|
|
83
|
+
if key == "transport_response":
|
|
84
|
+
value = hot.egress_transport_response
|
|
85
|
+
return value if value is not None else _LAZY_MISSING
|
|
86
|
+
if key == "sent":
|
|
87
|
+
return True if hot.egress_sent else _LAZY_MISSING
|
|
88
|
+
return _LAZY_MISSING
|
|
89
|
+
return _LAZY_MISSING
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _sync_hot_namespace_value(kind: str, hot: HotCtx, key: str, value: Any) -> None:
|
|
93
|
+
if kind == "route":
|
|
94
|
+
if key == "selector" and isinstance(value, str):
|
|
95
|
+
hot.route_selector = value
|
|
96
|
+
elif key == "protocol" and isinstance(value, str):
|
|
97
|
+
hot.route_protocol = value
|
|
98
|
+
elif key == "program_id" and isinstance(value, int):
|
|
99
|
+
hot.route_program_id = value
|
|
100
|
+
hot.program_id = value
|
|
101
|
+
elif key == "opmeta_index" and isinstance(value, int):
|
|
102
|
+
hot.route_opmeta_index = value
|
|
103
|
+
if hot.route_program_id < 0:
|
|
104
|
+
hot.route_program_id = value
|
|
105
|
+
if hot.program_id < 0:
|
|
106
|
+
hot.program_id = value
|
|
107
|
+
elif key == "method_not_allowed":
|
|
108
|
+
hot.route_method_not_allowed = bool(value)
|
|
109
|
+
elif key == "short_circuit":
|
|
110
|
+
hot.route_short_circuit = bool(value)
|
|
111
|
+
elif key == "payload":
|
|
112
|
+
hot.route_payload = _coerce_optional_dict(value)
|
|
113
|
+
elif key == "path_params":
|
|
114
|
+
path_params = _coerce_optional_dict(value)
|
|
115
|
+
hot.route_path_params = path_params
|
|
116
|
+
hot.path_params = path_params
|
|
117
|
+
elif key == "rpc_envelope":
|
|
118
|
+
envelope = _coerce_optional_dict(value)
|
|
119
|
+
hot.route_rpc_envelope = envelope
|
|
120
|
+
if envelope is not None:
|
|
121
|
+
hot.dispatch_jsonrpc_request_id = envelope.get("id")
|
|
122
|
+
method = envelope.get("method")
|
|
123
|
+
hot.dispatch_rpc_method = method if isinstance(method, str) else None
|
|
124
|
+
elif kind == "dispatch":
|
|
125
|
+
if key == "binding_protocol" and isinstance(value, str):
|
|
126
|
+
hot.dispatch_binding_protocol = value
|
|
127
|
+
elif key == "binding_selector" and isinstance(value, str):
|
|
128
|
+
hot.dispatch_binding_selector = value
|
|
129
|
+
elif key == "channel_protocol" and isinstance(value, str):
|
|
130
|
+
hot.dispatch_channel_protocol = value
|
|
131
|
+
elif key == "channel_selector" and isinstance(value, str):
|
|
132
|
+
hot.dispatch_channel_selector = value
|
|
133
|
+
elif key == "rpc":
|
|
134
|
+
envelope = _coerce_optional_dict(value)
|
|
135
|
+
hot.dispatch_rpc_envelope = envelope
|
|
136
|
+
if envelope is not None:
|
|
137
|
+
hot.dispatch_jsonrpc_request_id = envelope.get("id")
|
|
138
|
+
method = envelope.get("method")
|
|
139
|
+
hot.dispatch_rpc_method = method if isinstance(method, str) else None
|
|
140
|
+
elif key == "rpc_method":
|
|
141
|
+
hot.dispatch_rpc_method = value if isinstance(value, str) else None
|
|
142
|
+
elif key in {"normalized_input", "parsed_payload"}:
|
|
143
|
+
route_payload = _coerce_optional_dict(value)
|
|
144
|
+
if route_payload is not None:
|
|
145
|
+
hot.route_payload = route_payload
|
|
146
|
+
elif key == "jsonrpc_request_id":
|
|
147
|
+
hot.dispatch_jsonrpc_request_id = value
|
|
148
|
+
elif kind == "egress":
|
|
149
|
+
if key == "transport_response":
|
|
150
|
+
hot.egress_transport_response = _coerce_optional_dict(value)
|
|
151
|
+
elif key == "sent":
|
|
152
|
+
hot.egress_sent = bool(value)
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
def _clear_hot_namespace_value(kind: str, hot: HotCtx, key: str) -> None:
|
|
156
|
+
if kind == "route":
|
|
157
|
+
if key == "selector":
|
|
158
|
+
hot.route_selector = ""
|
|
159
|
+
elif key == "protocol":
|
|
160
|
+
hot.route_protocol = ""
|
|
161
|
+
elif key == "program_id":
|
|
162
|
+
hot.route_program_id = -1
|
|
163
|
+
elif key == "opmeta_index":
|
|
164
|
+
hot.route_opmeta_index = -1
|
|
165
|
+
elif key == "method_not_allowed":
|
|
166
|
+
hot.route_method_not_allowed = False
|
|
167
|
+
elif key == "short_circuit":
|
|
168
|
+
hot.route_short_circuit = False
|
|
169
|
+
elif key == "payload":
|
|
170
|
+
hot.route_payload = None
|
|
171
|
+
elif key == "path_params":
|
|
172
|
+
hot.route_path_params = None
|
|
173
|
+
hot.path_params = None
|
|
174
|
+
elif key == "rpc_envelope":
|
|
175
|
+
hot.route_rpc_envelope = None
|
|
176
|
+
hot.dispatch_jsonrpc_request_id = None
|
|
177
|
+
hot.dispatch_rpc_method = None
|
|
178
|
+
elif kind == "dispatch":
|
|
179
|
+
if key == "binding_protocol":
|
|
180
|
+
hot.dispatch_binding_protocol = ""
|
|
181
|
+
elif key == "binding_selector":
|
|
182
|
+
hot.dispatch_binding_selector = ""
|
|
183
|
+
elif key == "channel_protocol":
|
|
184
|
+
hot.dispatch_channel_protocol = ""
|
|
185
|
+
elif key == "channel_selector":
|
|
186
|
+
hot.dispatch_channel_selector = ""
|
|
187
|
+
elif key == "rpc":
|
|
188
|
+
hot.dispatch_rpc_envelope = None
|
|
189
|
+
hot.dispatch_jsonrpc_request_id = None
|
|
190
|
+
hot.dispatch_rpc_method = None
|
|
191
|
+
elif key == "rpc_method":
|
|
192
|
+
hot.dispatch_rpc_method = None
|
|
193
|
+
elif key == "jsonrpc_request_id":
|
|
194
|
+
hot.dispatch_jsonrpc_request_id = None
|
|
195
|
+
elif kind == "egress":
|
|
196
|
+
if key == "transport_response":
|
|
197
|
+
hot.egress_transport_response = None
|
|
198
|
+
elif key == "sent":
|
|
199
|
+
hot.egress_sent = False
|
|
200
|
+
|
|
@@ -10,193 +10,12 @@ from .hot_state import (
|
|
|
10
10
|
_ensure_hot_virtual_in_view,
|
|
11
11
|
_LAZY_MISSING,
|
|
12
12
|
)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return dict(value)
|
|
20
|
-
return None
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _namespace_lazy_value(kind: str, hot: HotCtx, key: str) -> Any:
|
|
24
|
-
if kind == "route":
|
|
25
|
-
if key == "selector":
|
|
26
|
-
value = hot.route_selector
|
|
27
|
-
return value if value else _LAZY_MISSING
|
|
28
|
-
if key == "protocol":
|
|
29
|
-
value = hot.route_protocol
|
|
30
|
-
return value if value else _LAZY_MISSING
|
|
31
|
-
if key == "program_id":
|
|
32
|
-
value = (
|
|
33
|
-
hot.route_program_id if hot.route_program_id >= 0 else hot.program_id
|
|
34
|
-
)
|
|
35
|
-
return value if value >= 0 else _LAZY_MISSING
|
|
36
|
-
if key == "opmeta_index":
|
|
37
|
-
value = (
|
|
38
|
-
hot.route_opmeta_index
|
|
39
|
-
if hot.route_opmeta_index >= 0
|
|
40
|
-
else hot.route_program_id
|
|
41
|
-
)
|
|
42
|
-
return value if value >= 0 else _LAZY_MISSING
|
|
43
|
-
if key == "method_not_allowed":
|
|
44
|
-
return True if hot.route_method_not_allowed else _LAZY_MISSING
|
|
45
|
-
if key == "short_circuit":
|
|
46
|
-
return True if hot.route_short_circuit else _LAZY_MISSING
|
|
47
|
-
if key == "payload":
|
|
48
|
-
if hot.route_payload is not None:
|
|
49
|
-
return hot.route_payload
|
|
50
|
-
value = _ensure_hot_in_values_view(hot)
|
|
51
|
-
return value if value is not None else _LAZY_MISSING
|
|
52
|
-
if key == "path_params":
|
|
53
|
-
value = hot.route_path_params or hot.path_params
|
|
54
|
-
return value if value is not None else _LAZY_MISSING
|
|
55
|
-
if key == "rpc_envelope":
|
|
56
|
-
value = hot.route_rpc_envelope or hot.dispatch_rpc_envelope
|
|
57
|
-
return value if value is not None else _LAZY_MISSING
|
|
58
|
-
return _LAZY_MISSING
|
|
59
|
-
if kind == "dispatch":
|
|
60
|
-
if key == "binding_protocol":
|
|
61
|
-
value = hot.dispatch_binding_protocol
|
|
62
|
-
return value if value else _LAZY_MISSING
|
|
63
|
-
if key == "binding_selector":
|
|
64
|
-
value = hot.dispatch_binding_selector
|
|
65
|
-
return value if value else _LAZY_MISSING
|
|
66
|
-
if key == "channel_protocol":
|
|
67
|
-
value = hot.dispatch_channel_protocol
|
|
68
|
-
return value if value else _LAZY_MISSING
|
|
69
|
-
if key == "channel_selector":
|
|
70
|
-
value = hot.dispatch_channel_selector
|
|
71
|
-
return value if value else _LAZY_MISSING
|
|
72
|
-
if key in {"normalized_input", "parsed_payload"}:
|
|
73
|
-
value = _ensure_hot_in_values_view(hot)
|
|
74
|
-
return value if value is not None else _LAZY_MISSING
|
|
75
|
-
if key == "rpc":
|
|
76
|
-
value = hot.dispatch_rpc_envelope or hot.route_rpc_envelope
|
|
77
|
-
return value if value is not None else _LAZY_MISSING
|
|
78
|
-
if key == "rpc_method":
|
|
79
|
-
value = hot.dispatch_rpc_method
|
|
80
|
-
return value if value is not None else _LAZY_MISSING
|
|
81
|
-
return _LAZY_MISSING
|
|
82
|
-
if kind == "egress":
|
|
83
|
-
if key == "transport_response":
|
|
84
|
-
value = hot.egress_transport_response
|
|
85
|
-
return value if value is not None else _LAZY_MISSING
|
|
86
|
-
if key == "sent":
|
|
87
|
-
return True if hot.egress_sent else _LAZY_MISSING
|
|
88
|
-
return _LAZY_MISSING
|
|
89
|
-
return _LAZY_MISSING
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def _sync_hot_namespace_value(kind: str, hot: HotCtx, key: str, value: Any) -> None:
|
|
93
|
-
if kind == "route":
|
|
94
|
-
if key == "selector" and isinstance(value, str):
|
|
95
|
-
hot.route_selector = value
|
|
96
|
-
elif key == "protocol" and isinstance(value, str):
|
|
97
|
-
hot.route_protocol = value
|
|
98
|
-
elif key == "program_id" and isinstance(value, int):
|
|
99
|
-
hot.route_program_id = value
|
|
100
|
-
hot.program_id = value
|
|
101
|
-
elif key == "opmeta_index" and isinstance(value, int):
|
|
102
|
-
hot.route_opmeta_index = value
|
|
103
|
-
if hot.route_program_id < 0:
|
|
104
|
-
hot.route_program_id = value
|
|
105
|
-
if hot.program_id < 0:
|
|
106
|
-
hot.program_id = value
|
|
107
|
-
elif key == "method_not_allowed":
|
|
108
|
-
hot.route_method_not_allowed = bool(value)
|
|
109
|
-
elif key == "short_circuit":
|
|
110
|
-
hot.route_short_circuit = bool(value)
|
|
111
|
-
elif key == "payload":
|
|
112
|
-
hot.route_payload = _coerce_optional_dict(value)
|
|
113
|
-
elif key == "path_params":
|
|
114
|
-
path_params = _coerce_optional_dict(value)
|
|
115
|
-
hot.route_path_params = path_params
|
|
116
|
-
hot.path_params = path_params
|
|
117
|
-
elif key == "rpc_envelope":
|
|
118
|
-
envelope = _coerce_optional_dict(value)
|
|
119
|
-
hot.route_rpc_envelope = envelope
|
|
120
|
-
if envelope is not None:
|
|
121
|
-
hot.dispatch_jsonrpc_request_id = envelope.get("id")
|
|
122
|
-
method = envelope.get("method")
|
|
123
|
-
hot.dispatch_rpc_method = method if isinstance(method, str) else None
|
|
124
|
-
elif kind == "dispatch":
|
|
125
|
-
if key == "binding_protocol" and isinstance(value, str):
|
|
126
|
-
hot.dispatch_binding_protocol = value
|
|
127
|
-
elif key == "binding_selector" and isinstance(value, str):
|
|
128
|
-
hot.dispatch_binding_selector = value
|
|
129
|
-
elif key == "channel_protocol" and isinstance(value, str):
|
|
130
|
-
hot.dispatch_channel_protocol = value
|
|
131
|
-
elif key == "channel_selector" and isinstance(value, str):
|
|
132
|
-
hot.dispatch_channel_selector = value
|
|
133
|
-
elif key == "rpc":
|
|
134
|
-
envelope = _coerce_optional_dict(value)
|
|
135
|
-
hot.dispatch_rpc_envelope = envelope
|
|
136
|
-
if envelope is not None:
|
|
137
|
-
hot.dispatch_jsonrpc_request_id = envelope.get("id")
|
|
138
|
-
method = envelope.get("method")
|
|
139
|
-
hot.dispatch_rpc_method = method if isinstance(method, str) else None
|
|
140
|
-
elif key == "rpc_method":
|
|
141
|
-
hot.dispatch_rpc_method = value if isinstance(value, str) else None
|
|
142
|
-
elif key in {"normalized_input", "parsed_payload"}:
|
|
143
|
-
route_payload = _coerce_optional_dict(value)
|
|
144
|
-
if route_payload is not None:
|
|
145
|
-
hot.route_payload = route_payload
|
|
146
|
-
elif key == "jsonrpc_request_id":
|
|
147
|
-
hot.dispatch_jsonrpc_request_id = value
|
|
148
|
-
elif kind == "egress":
|
|
149
|
-
if key == "transport_response":
|
|
150
|
-
hot.egress_transport_response = _coerce_optional_dict(value)
|
|
151
|
-
elif key == "sent":
|
|
152
|
-
hot.egress_sent = bool(value)
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
def _clear_hot_namespace_value(kind: str, hot: HotCtx, key: str) -> None:
|
|
156
|
-
if kind == "route":
|
|
157
|
-
if key == "selector":
|
|
158
|
-
hot.route_selector = ""
|
|
159
|
-
elif key == "protocol":
|
|
160
|
-
hot.route_protocol = ""
|
|
161
|
-
elif key == "program_id":
|
|
162
|
-
hot.route_program_id = -1
|
|
163
|
-
elif key == "opmeta_index":
|
|
164
|
-
hot.route_opmeta_index = -1
|
|
165
|
-
elif key == "method_not_allowed":
|
|
166
|
-
hot.route_method_not_allowed = False
|
|
167
|
-
elif key == "short_circuit":
|
|
168
|
-
hot.route_short_circuit = False
|
|
169
|
-
elif key == "payload":
|
|
170
|
-
hot.route_payload = None
|
|
171
|
-
elif key == "path_params":
|
|
172
|
-
hot.route_path_params = None
|
|
173
|
-
hot.path_params = None
|
|
174
|
-
elif key == "rpc_envelope":
|
|
175
|
-
hot.route_rpc_envelope = None
|
|
176
|
-
hot.dispatch_jsonrpc_request_id = None
|
|
177
|
-
hot.dispatch_rpc_method = None
|
|
178
|
-
elif kind == "dispatch":
|
|
179
|
-
if key == "binding_protocol":
|
|
180
|
-
hot.dispatch_binding_protocol = ""
|
|
181
|
-
elif key == "binding_selector":
|
|
182
|
-
hot.dispatch_binding_selector = ""
|
|
183
|
-
elif key == "channel_protocol":
|
|
184
|
-
hot.dispatch_channel_protocol = ""
|
|
185
|
-
elif key == "channel_selector":
|
|
186
|
-
hot.dispatch_channel_selector = ""
|
|
187
|
-
elif key == "rpc":
|
|
188
|
-
hot.dispatch_rpc_envelope = None
|
|
189
|
-
hot.dispatch_jsonrpc_request_id = None
|
|
190
|
-
hot.dispatch_rpc_method = None
|
|
191
|
-
elif key == "rpc_method":
|
|
192
|
-
hot.dispatch_rpc_method = None
|
|
193
|
-
elif key == "jsonrpc_request_id":
|
|
194
|
-
hot.dispatch_jsonrpc_request_id = None
|
|
195
|
-
elif kind == "egress":
|
|
196
|
-
if key == "transport_response":
|
|
197
|
-
hot.egress_transport_response = None
|
|
198
|
-
elif key == "sent":
|
|
199
|
-
hot.egress_sent = False
|
|
13
|
+
from .hot_namespace_values import (
|
|
14
|
+
_clear_hot_namespace_value,
|
|
15
|
+
_coerce_optional_dict,
|
|
16
|
+
_namespace_lazy_value,
|
|
17
|
+
_sync_hot_namespace_value,
|
|
18
|
+
)
|
|
200
19
|
|
|
201
20
|
|
|
202
21
|
class _HotNamespaceDict(dict[str, Any]):
|