piphi-runtime-kit-python 0.4.2__py3-none-any.whl → 0.4.3__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.
- piphi_runtime_kit_python/__init__.py +19 -1
- piphi_runtime_kit_python/runtime/config_sync.py +74 -0
- piphi_runtime_kit_python/runtime/health.py +1 -0
- piphi_runtime_kit_python/schemas.py +22 -0
- {piphi_runtime_kit_python-0.4.2.dist-info → piphi_runtime_kit_python-0.4.3.dist-info}/METADATA +1 -1
- {piphi_runtime_kit_python-0.4.2.dist-info → piphi_runtime_kit_python-0.4.3.dist-info}/RECORD +9 -9
- {piphi_runtime_kit_python-0.4.2.dist-info → piphi_runtime_kit_python-0.4.3.dist-info}/WHEEL +0 -0
- {piphi_runtime_kit_python-0.4.2.dist-info → piphi_runtime_kit_python-0.4.3.dist-info}/entry_points.txt +0 -0
- {piphi_runtime_kit_python-0.4.2.dist-info → piphi_runtime_kit_python-0.4.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -8,7 +8,18 @@ from .runtime.auth import (
|
|
|
8
8
|
format_runtime_auth_sync_log,
|
|
9
9
|
mask_token,
|
|
10
10
|
)
|
|
11
|
-
from .runtime.config_sync import
|
|
11
|
+
from .runtime.config_sync import (
|
|
12
|
+
CORE_BASE_URL_ENV_NAME,
|
|
13
|
+
DEFAULT_RUNTIME_CONFIG_SNAPSHOT_FILENAME,
|
|
14
|
+
DEFAULT_RUNTIME_VOLUME_DIR,
|
|
15
|
+
RUNTIME_CONFIG_SNAPSHOT_PATH_ENV_NAME,
|
|
16
|
+
ConfigSyncCoordinator,
|
|
17
|
+
build_sync_response,
|
|
18
|
+
load_runtime_config_snapshot,
|
|
19
|
+
reconcile_config_ids,
|
|
20
|
+
resolve_core_base_url,
|
|
21
|
+
resolve_runtime_config_snapshot_path,
|
|
22
|
+
)
|
|
12
23
|
from .runtime.configuration import (
|
|
13
24
|
build_config_apply_response,
|
|
14
25
|
build_config_remove_response,
|
|
@@ -109,6 +120,10 @@ __all__ = [
|
|
|
109
120
|
"CoreUnavailableError",
|
|
110
121
|
"CoreUnexpectedResponseError",
|
|
111
122
|
"DEFAULT_CORE_CLIENT_TIMEOUT_SECONDS",
|
|
123
|
+
"CORE_BASE_URL_ENV_NAME",
|
|
124
|
+
"DEFAULT_RUNTIME_CONFIG_SNAPSHOT_FILENAME",
|
|
125
|
+
"DEFAULT_RUNTIME_VOLUME_DIR",
|
|
126
|
+
"RUNTIME_CONFIG_SNAPSHOT_PATH_ENV_NAME",
|
|
112
127
|
"DEFAULT_RUNTIME_CONTAINER_ID_ENV_NAME",
|
|
113
128
|
"DEFAULT_RUNTIME_INTERNAL_TOKEN_ENV_NAME",
|
|
114
129
|
"RUNTIME_CONTAINER_ID_HEADER_NAME",
|
|
@@ -169,6 +184,7 @@ __all__ = [
|
|
|
169
184
|
"format_discovery_attempt_log",
|
|
170
185
|
"format_event_log",
|
|
171
186
|
"format_runtime_auth_sync_log",
|
|
187
|
+
"load_runtime_config_snapshot",
|
|
172
188
|
"mask_token",
|
|
173
189
|
"MqttBrokerConfig",
|
|
174
190
|
"MqttJsonClient",
|
|
@@ -176,6 +192,8 @@ __all__ = [
|
|
|
176
192
|
"normalize_event_payload",
|
|
177
193
|
"redact_config_secrets",
|
|
178
194
|
"reconcile_config_ids",
|
|
195
|
+
"resolve_core_base_url",
|
|
196
|
+
"resolve_runtime_config_snapshot_path",
|
|
179
197
|
"runtime_lifespan",
|
|
180
198
|
"schedule_event_delivery",
|
|
181
199
|
"schedule_telemetry_delivery",
|
|
@@ -3,6 +3,9 @@ from __future__ import annotations
|
|
|
3
3
|
"""Helpers for basic config-sync orchestration and generation tracking."""
|
|
4
4
|
|
|
5
5
|
from dataclasses import dataclass
|
|
6
|
+
import json
|
|
7
|
+
import os
|
|
8
|
+
from pathlib import Path
|
|
6
9
|
from typing import Awaitable, Callable, TypeVar
|
|
7
10
|
|
|
8
11
|
from ..schemas import RuntimeConfig, RuntimeConfigSnapshot, RuntimeConfigSyncResponse
|
|
@@ -10,6 +13,77 @@ from .state import RuntimeProcessState
|
|
|
10
13
|
|
|
11
14
|
TConfig = TypeVar("TConfig", bound=RuntimeConfig)
|
|
12
15
|
|
|
16
|
+
CORE_BASE_URL_ENV_NAME = "PIPHI_CORE_BASE_URL"
|
|
17
|
+
RUNTIME_CONTAINER_ID_ENV_NAME = "PIPHI_CONTAINER_ID"
|
|
18
|
+
RUNTIME_CONFIG_SNAPSHOT_PATH_ENV_NAME = "PIPHI_CONFIG_SNAPSHOT_PATH"
|
|
19
|
+
DEFAULT_RUNTIME_VOLUME_DIR = "/.piphinetwork"
|
|
20
|
+
DEFAULT_RUNTIME_CONFIG_SNAPSHOT_FILENAME = "configs.json"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def resolve_core_base_url(default: str | None = None) -> str | None:
|
|
24
|
+
"""Resolve Core's base URL from the managed-runtime environment."""
|
|
25
|
+
value = (os.getenv(CORE_BASE_URL_ENV_NAME) or "").strip().rstrip("/")
|
|
26
|
+
if value:
|
|
27
|
+
return value
|
|
28
|
+
return default.rstrip("/") if isinstance(default, str) and default.strip() else default
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def resolve_runtime_config_snapshot_path(
|
|
32
|
+
*,
|
|
33
|
+
container_id: str | None = None,
|
|
34
|
+
volume_dir: str | Path = DEFAULT_RUNTIME_VOLUME_DIR,
|
|
35
|
+
) -> Path:
|
|
36
|
+
"""Resolve the local config snapshot path mounted by PiPhi Core."""
|
|
37
|
+
explicit_path = (os.getenv(RUNTIME_CONFIG_SNAPSHOT_PATH_ENV_NAME) or "").strip()
|
|
38
|
+
if explicit_path:
|
|
39
|
+
return Path(explicit_path)
|
|
40
|
+
|
|
41
|
+
resolved_container_id = (
|
|
42
|
+
str(container_id or "").strip()
|
|
43
|
+
or (os.getenv(RUNTIME_CONTAINER_ID_ENV_NAME) or "").strip()
|
|
44
|
+
)
|
|
45
|
+
if resolved_container_id:
|
|
46
|
+
return Path(volume_dir).joinpath(f"{resolved_container_id}.json")
|
|
47
|
+
return Path(volume_dir).joinpath(DEFAULT_RUNTIME_CONFIG_SNAPSHOT_FILENAME)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def load_runtime_config_snapshot(
|
|
51
|
+
*,
|
|
52
|
+
path: str | Path | None = None,
|
|
53
|
+
container_id: str | None = None,
|
|
54
|
+
volume_dir: str | Path = DEFAULT_RUNTIME_VOLUME_DIR,
|
|
55
|
+
) -> RuntimeConfigSnapshot | None:
|
|
56
|
+
"""Load Core's last known config snapshot from the mounted runtime volume.
|
|
57
|
+
|
|
58
|
+
Missing, unreadable, or invalid snapshots return ``None`` so integrations can
|
|
59
|
+
treat snapshot rehydration as a safe startup fallback rather than a crash
|
|
60
|
+
trigger.
|
|
61
|
+
"""
|
|
62
|
+
snapshot_path = (
|
|
63
|
+
Path(path)
|
|
64
|
+
if path is not None
|
|
65
|
+
else resolve_runtime_config_snapshot_path(
|
|
66
|
+
container_id=container_id,
|
|
67
|
+
volume_dir=volume_dir,
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
try:
|
|
71
|
+
raw_payload = snapshot_path.read_text(encoding="utf-8")
|
|
72
|
+
except (FileNotFoundError, OSError):
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
payload = json.loads(raw_payload)
|
|
77
|
+
except json.JSONDecodeError:
|
|
78
|
+
return None
|
|
79
|
+
if not isinstance(payload, dict):
|
|
80
|
+
return None
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
return RuntimeConfigSnapshot.model_validate(payload)
|
|
84
|
+
except ValueError:
|
|
85
|
+
return None
|
|
86
|
+
|
|
13
87
|
|
|
14
88
|
def reconcile_config_ids(
|
|
15
89
|
*,
|
|
@@ -15,6 +15,7 @@ def _build_runtime_snapshot(runtime_context: RuntimeContext) -> dict[str, Any]:
|
|
|
15
15
|
"core_auth_present": bool(runtime_context.auth.internal_token),
|
|
16
16
|
"core_http_client_bound": process_state.core_http_client is not None,
|
|
17
17
|
"current_generation": process_state.current_generation,
|
|
18
|
+
"config_generation": process_state.current_generation,
|
|
18
19
|
"pending_task_count": len(
|
|
19
20
|
[task for task in process_state.background_tasks if not task.done()]
|
|
20
21
|
),
|
|
@@ -35,12 +35,34 @@ class RuntimeConfig(BaseModel):
|
|
|
35
35
|
|
|
36
36
|
class RuntimeConfigSnapshot(BaseModel):
|
|
37
37
|
"""Snapshot payload sent from PiPhi Core to an integration runtime."""
|
|
38
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
39
|
+
|
|
40
|
+
schema_version: int | None = Field(
|
|
41
|
+
default=None,
|
|
42
|
+
validation_alias=AliasChoices("schema_version", "schemaVersion"),
|
|
43
|
+
)
|
|
38
44
|
container_id: str
|
|
39
45
|
integration_id: str | None = None
|
|
40
46
|
driver_pid: int | None = None
|
|
41
47
|
reason: str | None = None
|
|
42
48
|
generation: int | None = None
|
|
49
|
+
updated_at: str | None = Field(
|
|
50
|
+
default=None,
|
|
51
|
+
validation_alias=AliasChoices("updated_at", "updatedAt"),
|
|
52
|
+
)
|
|
43
53
|
configs: list[RuntimeConfig] = Field(default_factory=list)
|
|
54
|
+
deleted_config_ids: list[str] = Field(
|
|
55
|
+
default_factory=list,
|
|
56
|
+
validation_alias=AliasChoices("deleted_config_ids", "deletedConfigIds"),
|
|
57
|
+
)
|
|
58
|
+
config_hash: str | None = Field(
|
|
59
|
+
default=None,
|
|
60
|
+
validation_alias=AliasChoices("config_hash", "configHash"),
|
|
61
|
+
)
|
|
62
|
+
internal_token: str | None = Field(
|
|
63
|
+
default=None,
|
|
64
|
+
validation_alias=AliasChoices("internal_token", "internalToken"),
|
|
65
|
+
)
|
|
44
66
|
|
|
45
67
|
|
|
46
68
|
class RuntimeConfigSyncResponse(BaseModel):
|
{piphi_runtime_kit_python-0.4.2.dist-info → piphi_runtime_kit_python-0.4.3.dist-info}/RECORD
RENAMED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
piphi_runtime_kit_python-0.4.
|
|
2
|
-
piphi_runtime_kit_python-0.4.
|
|
3
|
-
piphi_runtime_kit_python-0.4.
|
|
4
|
-
piphi_runtime_kit_python-0.4.
|
|
5
|
-
piphi_runtime_kit_python/__init__.py,sha256=
|
|
1
|
+
piphi_runtime_kit_python-0.4.3.dist-info/METADATA,sha256=E79yjhZ5noVak87XO3vqqmXAPPcpwnnHCQ6ARARjN_U,30849
|
|
2
|
+
piphi_runtime_kit_python-0.4.3.dist-info/WHEEL,sha256=Z36eTX6lG3PITRleSd5hAZHCcz52yg3c0JQVxKBbLW0,90
|
|
3
|
+
piphi_runtime_kit_python-0.4.3.dist-info/entry_points.txt,sha256=6OYgBcLyFCUgeqLgnvMyOJxPCWzgy7se4rLPKtNonMs,34
|
|
4
|
+
piphi_runtime_kit_python-0.4.3.dist-info/licenses/LICENSE,sha256=pS6szQI4X7qAin1ODdoDp-XwZvsFy6ZZ28-JAwGHgzo,1070
|
|
5
|
+
piphi_runtime_kit_python/__init__.py,sha256=PYHFtcA1h8JY3HaOAoPfTX4u9jgiYrXV25NStwQaVKk,6548
|
|
6
6
|
piphi_runtime_kit_python/adapters/__init__.py,sha256=3jBhPZSBN3Qo7MKHlxAol2jPU3cK23BXHR2oTlircsw,361
|
|
7
7
|
piphi_runtime_kit_python/adapters/fastapi.py,sha256=1QcOBYprg6AmQVrkI8g61NIelBB_7BTbdvNaMvG2-s8,2098
|
|
8
8
|
piphi_runtime_kit_python/fastapi.py,sha256=OZ-ds2-g32kB4YkF90D5bM4vVVjpOWPtrNC-WdhDNyo,361
|
|
9
9
|
piphi_runtime_kit_python/runtime/__init__.py,sha256=0WxNbgGodqba-uiJILOAuU3EwZhBtXeDyw6sYhduWzg,3717
|
|
10
10
|
piphi_runtime_kit_python/runtime/auth.py,sha256=hL90c3K5pJgEpPdNGJ7ds6mqeN4tmjC3I8igfNam_L4,4648
|
|
11
|
-
piphi_runtime_kit_python/runtime/config_sync.py,sha256=
|
|
11
|
+
piphi_runtime_kit_python/runtime/config_sync.py,sha256=ellgkNQmEGLVFH81VdvxpleQdG_bEmmRdpBkmykdbA4,8078
|
|
12
12
|
piphi_runtime_kit_python/runtime/configuration.py,sha256=4kkoJeENOhJHeNvC9QDu81ejDJUQJG7S5GmQG1sv3YQ,3631
|
|
13
13
|
piphi_runtime_kit_python/runtime/context.py,sha256=CwXgrivciBd7eTREn0u0zjqkDPy6VthASW-gsoZqCTg,1109
|
|
14
14
|
piphi_runtime_kit_python/runtime/discovery.py,sha256=uH6rJ4BnLVukTCxu2QwvN8yJhsI_fcT29VEat62oBcY,2274
|
|
15
15
|
piphi_runtime_kit_python/runtime/dispatch.py,sha256=QcbA9B5izyyg0znlKHq94dbr-oqHVxKW2LCjrQKYfkY,7341
|
|
16
16
|
piphi_runtime_kit_python/runtime/errors.py,sha256=_mjqmJLsdM5NfrTwb6YFkhheqPfn6Df-QtAKgl9U6QU,4120
|
|
17
17
|
piphi_runtime_kit_python/runtime/events.py,sha256=JcvrTZlJ-vgY237jTDVOAVTbSxbcuh9u2QCdOGyuduA,6543
|
|
18
|
-
piphi_runtime_kit_python/runtime/health.py,sha256=
|
|
18
|
+
piphi_runtime_kit_python/runtime/health.py,sha256=3pds8SYSUql2w2ijegbszwm0HK69VzfIrwz42bN97yk,1943
|
|
19
19
|
piphi_runtime_kit_python/runtime/identity.py,sha256=cth0_QHR9R5LTdp-6DPD1IhM8cYJT5HB1OUQYW7kLGs,2762
|
|
20
20
|
piphi_runtime_kit_python/runtime/lifespan.py,sha256=mVSdZZAS66xlcnlzAwkztFjzw_l2pyLrJqULJsb0Ezk,2850
|
|
21
21
|
piphi_runtime_kit_python/runtime/mqtt.py,sha256=JKMN5zxg1BcOidu7TaYnuRD3HuoAJ_WcvXMTTSlAteo,6069
|
|
@@ -24,5 +24,5 @@ piphi_runtime_kit_python/runtime/starter.py,sha256=j5C4GOOcRHNLJ-HYu8fmf3bE00baD
|
|
|
24
24
|
piphi_runtime_kit_python/runtime/state.py,sha256=4xvQGTT59DF9rXHAtM3kDyV_UGg2a9tLPvGiCp_PFMc,674
|
|
25
25
|
piphi_runtime_kit_python/runtime/tasks.py,sha256=gMd-2K96jMU8tCPvI12xdWxuyNt5gsLDss2QWOoM94k,1241
|
|
26
26
|
piphi_runtime_kit_python/runtime/telemetry.py,sha256=RN6SFrhmAZ7aJLyioQMBzJEFsxQgOjjA1pV5qNeaR4E,4279
|
|
27
|
-
piphi_runtime_kit_python/schemas.py,sha256=
|
|
28
|
-
piphi_runtime_kit_python-0.4.
|
|
27
|
+
piphi_runtime_kit_python/schemas.py,sha256=9jlsfmvz-O2YeoB0SVopXY7NhFlb1zgynez0NXEZkVE,9849
|
|
28
|
+
piphi_runtime_kit_python-0.4.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|