feat: add server store role overrides

This commit is contained in:
lda
2026-06-06 18:21:58 +07:00 Verified
parent 6b61fac5f6
commit 5df1e27928
18 changed files with 454 additions and 25 deletions
+2
View File
@@ -10,6 +10,7 @@ from .models import (
RpcHttpTargetConfig,
RpcHttpTransportConfig,
ServerConfig,
ServerStoresConfig,
SourceConfigOwnership,
SourceTransportConfig,
StdioSourceTransportConfig,
@@ -27,6 +28,7 @@ __all__ = [
"RpcHttpTargetConfig",
"RpcHttpTransportConfig",
"ServerConfig",
"ServerStoresConfig",
"SourceConfigOwnership",
"SourceTransportConfig",
"StdioSourceTransportConfig",
+47 -14
View File
@@ -3,7 +3,12 @@ from __future__ import annotations
import json
from pathlib import Path
from .models import FilesystemStoreConfig, WorkflowConfigFile
from .models import (
FilesystemStoreConfig,
ServerStoresConfig,
StoreConfig,
WorkflowConfigFile,
)
def load_workflow_config(path: str | Path) -> WorkflowConfigFile:
@@ -11,22 +16,50 @@ def load_workflow_config(path: str | Path) -> WorkflowConfigFile:
Relative filesystem store roots are config-file relative so `wf --config`
behaves the same regardless of the caller's current working directory.
Role-specific store overrides follow the same rule.
"""
config_path = Path(path)
data = json.loads(config_path.read_text(encoding="utf-8"))
config = WorkflowConfigFile.model_validate(data)
store = config.server.store
return _resolve_store_paths(config, base_dir=config_path.parent)
def _resolve_store_paths(
config: WorkflowConfigFile,
*,
base_dir: Path,
) -> WorkflowConfigFile:
server = config.server
resolved_stores = ServerStoresConfig(
workflow=_resolve_store(server.stores.workflow, base_dir=base_dir),
auth=_resolve_store(server.stores.auth, base_dir=base_dir),
source_registry=_resolve_store(
server.stores.source_registry,
base_dir=base_dir,
),
catalog_cache=_resolve_store(
server.stores.catalog_cache,
base_dir=base_dir,
),
)
return config.model_copy(
update={
"server": server.model_copy(
update={
"store": _resolve_store(server.store, base_dir=base_dir),
"stores": resolved_stores,
}
)
}
)
def _resolve_store(
store: StoreConfig | None,
*,
base_dir: Path,
) -> StoreConfig | None:
if isinstance(store, FilesystemStoreConfig) and not store.root.is_absolute():
config = config.model_copy(
update={
"server": config.server.model_copy(
update={
"store": store.model_copy(
update={"root": (config_path.parent / store.root).resolve()}
)
}
)
}
)
return config
return store.model_copy(update={"root": (base_dir / store.root).resolve()})
return store
+31
View File
@@ -139,8 +139,23 @@ SourceConfig = Annotated[
]
class ServerStoresConfig(WorkflowConfigModel):
"""Optional role-specific store overrides.
Missing roles fall back to `ServerConfig.store`. Keep this config role-based
so future backends can split workflow records, auth, desired sources, and
cache storage independently.
"""
workflow: StoreConfig | None = None
auth: StoreConfig | None = None
source_registry: StoreConfig | None = None
catalog_cache: StoreConfig | None = None
class ServerConfig(WorkflowConfigModel):
store: StoreConfig = Field(default_factory=FilesystemStoreConfig)
stores: ServerStoresConfig = Field(default_factory=ServerStoresConfig)
transports: list[ServerTransportConfig] = Field(default_factory=list)
sources: list[SourceConfig] = Field(default_factory=list)
@@ -153,6 +168,22 @@ class ServerConfig(WorkflowConfigModel):
seen.add(source.id)
return self
@property
def workflow_store(self) -> StoreConfig:
return self.stores.workflow or self.store
@property
def auth_store(self) -> StoreConfig:
return self.stores.auth or self.store
@property
def source_registry_store(self) -> StoreConfig:
return self.stores.source_registry or self.store
@property
def catalog_cache_store(self) -> StoreConfig:
return self.stores.catalog_cache or self.store
class WorkflowConfigFile(WorkflowConfigModel):
version: Literal[1] = 1