digitalkin 0.3.1.dev2__py3-none-any.whl → 0.3.2.dev14__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.
- base_server/server_async_insecure.py +6 -5
- base_server/server_async_secure.py +6 -5
- base_server/server_sync_insecure.py +5 -4
- base_server/server_sync_secure.py +5 -4
- digitalkin/__version__.py +1 -1
- digitalkin/core/job_manager/base_job_manager.py +1 -1
- digitalkin/core/job_manager/single_job_manager.py +28 -9
- digitalkin/core/job_manager/taskiq_broker.py +7 -6
- digitalkin/core/job_manager/taskiq_job_manager.py +1 -1
- digitalkin/core/task_manager/surrealdb_repository.py +7 -7
- digitalkin/core/task_manager/task_session.py +60 -98
- digitalkin/grpc_servers/module_server.py +109 -168
- digitalkin/grpc_servers/module_servicer.py +38 -16
- digitalkin/grpc_servers/utils/grpc_client_wrapper.py +24 -8
- digitalkin/grpc_servers/utils/utility_schema_extender.py +100 -0
- digitalkin/models/__init__.py +1 -1
- digitalkin/models/core/job_manager_models.py +0 -8
- digitalkin/models/core/task_monitor.py +4 -0
- digitalkin/models/grpc_servers/models.py +91 -6
- digitalkin/models/module/__init__.py +18 -13
- digitalkin/models/module/base_types.py +61 -0
- digitalkin/models/module/module_context.py +173 -13
- digitalkin/models/module/module_types.py +28 -392
- digitalkin/models/module/setup_types.py +490 -0
- digitalkin/models/module/tool_cache.py +68 -0
- digitalkin/models/module/tool_reference.py +117 -0
- digitalkin/models/module/utility.py +167 -0
- digitalkin/models/services/registry.py +35 -0
- digitalkin/modules/__init__.py +5 -1
- digitalkin/modules/_base_module.py +154 -61
- digitalkin/modules/archetype_module.py +6 -1
- digitalkin/modules/tool_module.py +6 -1
- digitalkin/modules/triggers/__init__.py +8 -0
- digitalkin/modules/triggers/healthcheck_ping_trigger.py +45 -0
- digitalkin/modules/triggers/healthcheck_services_trigger.py +63 -0
- digitalkin/modules/triggers/healthcheck_status_trigger.py +52 -0
- digitalkin/services/__init__.py +4 -0
- digitalkin/services/communication/__init__.py +7 -0
- digitalkin/services/communication/communication_strategy.py +76 -0
- digitalkin/services/communication/default_communication.py +101 -0
- digitalkin/services/communication/grpc_communication.py +234 -0
- digitalkin/services/cost/grpc_cost.py +1 -1
- digitalkin/services/filesystem/grpc_filesystem.py +1 -1
- digitalkin/services/registry/__init__.py +22 -1
- digitalkin/services/registry/default_registry.py +135 -4
- digitalkin/services/registry/exceptions.py +47 -0
- digitalkin/services/registry/grpc_registry.py +306 -0
- digitalkin/services/registry/registry_models.py +15 -0
- digitalkin/services/registry/registry_strategy.py +88 -4
- digitalkin/services/services_config.py +25 -3
- digitalkin/services/services_models.py +5 -1
- digitalkin/services/setup/default_setup.py +1 -1
- digitalkin/services/setup/grpc_setup.py +1 -1
- digitalkin/services/storage/grpc_storage.py +1 -1
- digitalkin/services/user_profile/__init__.py +11 -0
- digitalkin/services/user_profile/grpc_user_profile.py +2 -2
- digitalkin/services/user_profile/user_profile_strategy.py +0 -15
- digitalkin/utils/schema_splitter.py +207 -0
- {digitalkin-0.3.1.dev2.dist-info → digitalkin-0.3.2.dev14.dist-info}/METADATA +5 -5
- digitalkin-0.3.2.dev14.dist-info/RECORD +143 -0
- {digitalkin-0.3.1.dev2.dist-info → digitalkin-0.3.2.dev14.dist-info}/top_level.txt +1 -0
- modules/archetype_with_tools_module.py +244 -0
- modules/cpu_intensive_module.py +1 -1
- modules/dynamic_setup_module.py +5 -29
- modules/minimal_llm_module.py +1 -1
- modules/text_transform_module.py +1 -1
- monitoring/digitalkin_observability/__init__.py +46 -0
- monitoring/digitalkin_observability/http_server.py +150 -0
- monitoring/digitalkin_observability/interceptors.py +176 -0
- monitoring/digitalkin_observability/metrics.py +201 -0
- monitoring/digitalkin_observability/prometheus.py +137 -0
- monitoring/tests/test_metrics.py +172 -0
- services/filesystem_module.py +7 -5
- services/storage_module.py +4 -2
- digitalkin/grpc_servers/registry_server.py +0 -65
- digitalkin/grpc_servers/registry_servicer.py +0 -456
- digitalkin-0.3.1.dev2.dist-info/RECORD +0 -119
- {digitalkin-0.3.1.dev2.dist-info → digitalkin-0.3.2.dev14.dist-info}/WHEEL +0 -0
- {digitalkin-0.3.1.dev2.dist-info → digitalkin-0.3.2.dev14.dist-info}/licenses/LICENSE +0 -0
services/filesystem_module.py
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import datetime
|
|
5
5
|
from collections.abc import Callable
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import Any
|
|
7
7
|
|
|
8
8
|
from pydantic import BaseModel, Field
|
|
9
9
|
|
|
10
10
|
from digitalkin.logger import logger
|
|
11
11
|
from digitalkin.models.module import ModuleStatus
|
|
12
12
|
from digitalkin.modules.archetype_module import ArchetypeModule
|
|
13
|
+
from digitalkin.services.filesystem.filesystem_strategy import FileFilter, UploadFileData
|
|
13
14
|
from digitalkin.services.services_config import ServicesConfig
|
|
14
15
|
from digitalkin.services.services_models import ServicesMode
|
|
15
|
-
from digitalkin.services.filesystem.filesystem_strategy import FilesystemRecord, FileFilter, UploadFileData
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class ExampleInput(BaseModel):
|
|
@@ -62,7 +62,10 @@ class ExampleModule(ArchetypeModule[ExampleInput, ExampleOutput, ExampleSetup, E
|
|
|
62
62
|
|
|
63
63
|
# Define services_config_params with default values
|
|
64
64
|
services_config_strategies = {}
|
|
65
|
-
services_config_params = {
|
|
65
|
+
services_config_params = {
|
|
66
|
+
"cost": {"config": {}},
|
|
67
|
+
"storage": {"config": {}},
|
|
68
|
+
} # Filesystem has no config but it's enabled
|
|
66
69
|
|
|
67
70
|
def __init__(self, job_id: str, mission_id: str, setup_version_id: str) -> None:
|
|
68
71
|
"""Initialize the example module.
|
|
@@ -128,7 +131,6 @@ class ExampleModule(ArchetypeModule[ExampleInput, ExampleOutput, ExampleSetup, E
|
|
|
128
131
|
callback(record.model_dump())
|
|
129
132
|
# Call the callback with the output data
|
|
130
133
|
|
|
131
|
-
|
|
132
134
|
# Wait a bit to simulate processing time
|
|
133
135
|
await asyncio.sleep(1)
|
|
134
136
|
|
|
@@ -173,7 +175,7 @@ async def test_module() -> None:
|
|
|
173
175
|
|
|
174
176
|
# Check the storage
|
|
175
177
|
if module.status == ModuleStatus.STOPPED:
|
|
176
|
-
files,
|
|
178
|
+
files, _nb_results = module.filesystem.get_files(
|
|
177
179
|
filters=FileFilter(name="example_output.txt", context="test-mission-123"),
|
|
178
180
|
)
|
|
179
181
|
for file in files:
|
services/storage_module.py
CHANGED
|
@@ -64,7 +64,7 @@ class ExampleModule(ArchetypeModule[ExampleInput, ExampleOutput, ExampleSetup, E
|
|
|
64
64
|
|
|
65
65
|
# Define services_config_params with default values
|
|
66
66
|
services_config_strategies = {}
|
|
67
|
-
services_config_params = {"storage": {"config": {"example": ExampleOutput}},"cost": {"config":{}}}
|
|
67
|
+
services_config_params = {"storage": {"config": {"example": ExampleOutput}}, "cost": {"config": {}}}
|
|
68
68
|
|
|
69
69
|
def __init__(self, job_id: str, mission_id: str, setup_version_id: str) -> None:
|
|
70
70
|
"""Initialize the example module.
|
|
@@ -184,7 +184,9 @@ async def test_module() -> None:
|
|
|
184
184
|
def test_storage_directly() -> None:
|
|
185
185
|
"""Test the storage service directly."""
|
|
186
186
|
# Initialize storage service
|
|
187
|
-
storage = ServicesConfig().storage(
|
|
187
|
+
storage = ServicesConfig().storage(
|
|
188
|
+
mission_id="test-mission", setup_version_id="test-setup-123", config={"example": ExampleStorage}
|
|
189
|
+
)
|
|
188
190
|
|
|
189
191
|
# Create a test record
|
|
190
192
|
storage.store("example", "test_table", {"test_key": "test_value"}, "OUTPUT")
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
"""Registry gRPC server implementation for DigitalKin."""
|
|
2
|
-
|
|
3
|
-
from digitalkin_proto.agentic_mesh_protocol.module_registry.v1 import (
|
|
4
|
-
module_registry_service_pb2,
|
|
5
|
-
module_registry_service_pb2_grpc,
|
|
6
|
-
)
|
|
7
|
-
|
|
8
|
-
from digitalkin.grpc_servers._base_server import BaseServer
|
|
9
|
-
from digitalkin.grpc_servers.registry_servicer import RegistryModule, RegistryServicer
|
|
10
|
-
from digitalkin.logger import logger
|
|
11
|
-
from digitalkin.models.grpc_servers.models import RegistryServerConfig
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class RegistryServer(BaseServer):
|
|
15
|
-
"""gRPC server for DigitalKin module registry.
|
|
16
|
-
|
|
17
|
-
This server implements the ModuleRegistryService which allows modules to register
|
|
18
|
-
themselves and be discovered by other components in the system.
|
|
19
|
-
|
|
20
|
-
Attributes:
|
|
21
|
-
config: Server configuration.
|
|
22
|
-
registry_servicer: The gRPC servicer handling registry requests.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(
|
|
26
|
-
self,
|
|
27
|
-
config: RegistryServerConfig,
|
|
28
|
-
) -> None:
|
|
29
|
-
"""Initialize the registry server.
|
|
30
|
-
|
|
31
|
-
Args:
|
|
32
|
-
config: Server configuration.
|
|
33
|
-
"""
|
|
34
|
-
super().__init__(config)
|
|
35
|
-
self.config = config
|
|
36
|
-
self.registry_servicer: RegistryServicer | None = None
|
|
37
|
-
|
|
38
|
-
def _register_servicers(self) -> None:
|
|
39
|
-
"""Register the registry servicer with the gRPC server.
|
|
40
|
-
|
|
41
|
-
Raises:
|
|
42
|
-
RuntimeError: If server is not registered during server creation
|
|
43
|
-
"""
|
|
44
|
-
if self.server is None:
|
|
45
|
-
msg = "Server must be created before registering servicers"
|
|
46
|
-
raise RuntimeError(msg)
|
|
47
|
-
|
|
48
|
-
logger.debug("Registering registry servicer")
|
|
49
|
-
self.registry_servicer = RegistryServicer()
|
|
50
|
-
self.register_servicer(
|
|
51
|
-
self.registry_servicer,
|
|
52
|
-
module_registry_service_pb2_grpc.add_ModuleRegistryServiceServicer_to_server,
|
|
53
|
-
service_descriptor=module_registry_service_pb2.DESCRIPTOR,
|
|
54
|
-
)
|
|
55
|
-
logger.debug("Registered registry servicer")
|
|
56
|
-
|
|
57
|
-
def get_registered_modules(self) -> list[RegistryModule]:
|
|
58
|
-
"""Get a list of all registered modules.
|
|
59
|
-
|
|
60
|
-
Returns:
|
|
61
|
-
A list of module information objects.
|
|
62
|
-
"""
|
|
63
|
-
if self.registry_servicer:
|
|
64
|
-
return list(self.registry_servicer.registered_modules.values())
|
|
65
|
-
return []
|
|
@@ -1,456 +0,0 @@
|
|
|
1
|
-
"""Registry servicer implementation for DigitalKin.
|
|
2
|
-
|
|
3
|
-
This module provides the gRPC service implementation for the Module Registry,
|
|
4
|
-
which handles registration, deregistration, discovery, and status management
|
|
5
|
-
of DigitalKin modules.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from collections.abc import Iterator
|
|
9
|
-
from enum import Enum
|
|
10
|
-
|
|
11
|
-
import grpc
|
|
12
|
-
from digitalkin_proto.agentic_mesh_protocol.module_registry.v1 import (
|
|
13
|
-
discover_pb2,
|
|
14
|
-
metadata_pb2,
|
|
15
|
-
module_registry_service_pb2_grpc,
|
|
16
|
-
registration_pb2,
|
|
17
|
-
status_pb2,
|
|
18
|
-
)
|
|
19
|
-
from pydantic import BaseModel
|
|
20
|
-
from typing_extensions import Self
|
|
21
|
-
|
|
22
|
-
from digitalkin.logger import logger
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class ExtendedEnum(Enum):
|
|
26
|
-
"""Tool enum class."""
|
|
27
|
-
|
|
28
|
-
@classmethod
|
|
29
|
-
def list(cls) -> list:
|
|
30
|
-
"""Classmethod to generate a list of enum values.
|
|
31
|
-
|
|
32
|
-
Returns:
|
|
33
|
-
list: Enum members' values
|
|
34
|
-
"""
|
|
35
|
-
return [c.value for c in cls]
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class ModuleStatus(ExtendedEnum):
|
|
39
|
-
"""Describe a Module current status.
|
|
40
|
-
|
|
41
|
-
Represents the possible states a module can be in during its lifecycle.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
# RUNNING: Module alive.
|
|
45
|
-
RUNNING = 0
|
|
46
|
-
# IDLE: Module waiting for an event / update.
|
|
47
|
-
IDLE = 1
|
|
48
|
-
# ENDED: Module signals the end of task or have been killed.
|
|
49
|
-
ENDED = 2
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class Tag(BaseModel):
|
|
53
|
-
"""Words representing a module capabilities.
|
|
54
|
-
|
|
55
|
-
Used for module discovery and categorization.
|
|
56
|
-
"""
|
|
57
|
-
|
|
58
|
-
# tag: Describe a Module function.
|
|
59
|
-
tag: str
|
|
60
|
-
|
|
61
|
-
def to_proto(self) -> metadata_pb2.Tag:
|
|
62
|
-
"""Convert Tag object from Pydantic to Proto.
|
|
63
|
-
|
|
64
|
-
Returns:
|
|
65
|
-
metadata_pb2.Tag: The protobuf representation of this tag.
|
|
66
|
-
"""
|
|
67
|
-
return metadata_pb2.Tag(tag=self.tag)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class Metadata(BaseModel):
|
|
71
|
-
"""Different informations to index and describe a module.
|
|
72
|
-
|
|
73
|
-
Contains human-readable information about a module and its capabilities.
|
|
74
|
-
"""
|
|
75
|
-
|
|
76
|
-
# name: Module's name
|
|
77
|
-
name: str
|
|
78
|
-
# tags: List of tag to describe a module functionalities.
|
|
79
|
-
tags: list[Tag]
|
|
80
|
-
# description: Module's description for search and indexing
|
|
81
|
-
description: str | None
|
|
82
|
-
|
|
83
|
-
def to_proto(self) -> metadata_pb2.Metadata:
|
|
84
|
-
"""Convert Metadata object from Pydantic to Proto.
|
|
85
|
-
|
|
86
|
-
Returns:
|
|
87
|
-
metadata_pb2.Metadata: The protobuf representation of this metadata.
|
|
88
|
-
"""
|
|
89
|
-
return metadata_pb2.Metadata(
|
|
90
|
-
name=self.name,
|
|
91
|
-
tags=(t.to_proto() for t in self.tags),
|
|
92
|
-
description=self.description,
|
|
93
|
-
)
|
|
94
|
-
|
|
95
|
-
@classmethod
|
|
96
|
-
def from_proto(cls, request_metadata: metadata_pb2.Metadata) -> Self:
|
|
97
|
-
"""Create Metadata object from Proto message.
|
|
98
|
-
|
|
99
|
-
Args:
|
|
100
|
-
request_metadata: The protobuf metadata to convert.
|
|
101
|
-
|
|
102
|
-
Returns:
|
|
103
|
-
Metadata: The Pydantic model representation of the metadata.
|
|
104
|
-
"""
|
|
105
|
-
return cls(
|
|
106
|
-
name=request_metadata.name,
|
|
107
|
-
tags=[Tag(tag=t.tag) for t in request_metadata.tags],
|
|
108
|
-
description=request_metadata.description,
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class RegistryModule(BaseModel):
|
|
113
|
-
"""Module's technical representation to index, search and monitor.
|
|
114
|
-
|
|
115
|
-
Contains all the information needed to identify, locate and communicate
|
|
116
|
-
with a module in the system.
|
|
117
|
-
"""
|
|
118
|
-
|
|
119
|
-
# module_id: Id of the module
|
|
120
|
-
module_id: str
|
|
121
|
-
# module_type: Type of the module (trigger, tool, kin, view)
|
|
122
|
-
module_type: str
|
|
123
|
-
# address: Address used to communicate with the module
|
|
124
|
-
address: str
|
|
125
|
-
# port: Port used to communicate with the module
|
|
126
|
-
port: int
|
|
127
|
-
# version: Current module version.
|
|
128
|
-
version: str
|
|
129
|
-
# metadata: user defined module name, description and tags
|
|
130
|
-
metadata: Metadata
|
|
131
|
-
# status: Representation of the Module current state (running, idle, ended...).
|
|
132
|
-
status: ModuleStatus
|
|
133
|
-
# message: (Optional) Details about the status.
|
|
134
|
-
message: str | None
|
|
135
|
-
|
|
136
|
-
def to_proto(self) -> discover_pb2.DiscoverInfoResponse:
|
|
137
|
-
"""Convert RegistryModule object from Pydantic to Proto.
|
|
138
|
-
|
|
139
|
-
Returns:
|
|
140
|
-
metadata_pb2.Metadata: The protobuf representation of this metadata.
|
|
141
|
-
"""
|
|
142
|
-
return discover_pb2.DiscoverInfoResponse(
|
|
143
|
-
module_id=self.module_id,
|
|
144
|
-
module_type=self.module_type,
|
|
145
|
-
address=self.address,
|
|
146
|
-
port=self.port,
|
|
147
|
-
version=self.version,
|
|
148
|
-
metadata=self.metadata.to_proto(),
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
class RegistryServicer(module_registry_service_pb2_grpc.ModuleRegistryServiceServicer):
|
|
153
|
-
"""Implementation of the ModuleRegistryService.
|
|
154
|
-
|
|
155
|
-
This servicer handles the registration, deregistration, and discovery of modules.
|
|
156
|
-
It maintains an in-memory registry of all active modules and their metadata.
|
|
157
|
-
|
|
158
|
-
Attributes:
|
|
159
|
-
registered_modules: Dictionary mapping module_id to RegistryModule objects.
|
|
160
|
-
"""
|
|
161
|
-
|
|
162
|
-
registered_modules: dict[str, RegistryModule]
|
|
163
|
-
|
|
164
|
-
def __init__(self) -> None:
|
|
165
|
-
"""Initialize the registry servicer with an empty module registry."""
|
|
166
|
-
self.registered_modules = {} # TODO replace with a database
|
|
167
|
-
|
|
168
|
-
def RegisterModule( # noqa: N802
|
|
169
|
-
self,
|
|
170
|
-
request: registration_pb2.RegisterRequest,
|
|
171
|
-
context: grpc.ServicerContext,
|
|
172
|
-
) -> registration_pb2.RegisterResponse:
|
|
173
|
-
"""Register a module with the registry.
|
|
174
|
-
|
|
175
|
-
Adds a new module to the registry with its connection information and metadata.
|
|
176
|
-
Fails if a module with the same ID is already registered.
|
|
177
|
-
|
|
178
|
-
Args:
|
|
179
|
-
request: The register request containing module info and address.
|
|
180
|
-
context: The gRPC context for setting status codes and details.
|
|
181
|
-
|
|
182
|
-
Returns:
|
|
183
|
-
registration_pb2.RegisterResponse: A response indicating success or failure.
|
|
184
|
-
"""
|
|
185
|
-
module_id = request.module_id
|
|
186
|
-
logger.debug("Registering module: %s", module_id)
|
|
187
|
-
|
|
188
|
-
# Check if module is already registered
|
|
189
|
-
if module_id in self.registered_modules:
|
|
190
|
-
message = f"Module '{module_id}' already registered"
|
|
191
|
-
logger.warning(message)
|
|
192
|
-
|
|
193
|
-
context.set_code(grpc.StatusCode.ALREADY_EXISTS)
|
|
194
|
-
context.set_details(message)
|
|
195
|
-
return registration_pb2.RegisterResponse(success=False)
|
|
196
|
-
|
|
197
|
-
# Store the module info with address
|
|
198
|
-
self.registered_modules[module_id] = RegistryModule(
|
|
199
|
-
module_id=request.module_id,
|
|
200
|
-
module_type=request.module_type,
|
|
201
|
-
address=request.address,
|
|
202
|
-
port=request.port,
|
|
203
|
-
version=request.version,
|
|
204
|
-
metadata=Metadata.from_proto(request.metadata),
|
|
205
|
-
status=ModuleStatus.RUNNING,
|
|
206
|
-
message=None,
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
logger.debug("Module %s registered at %s:%d", module_id, request.address, request.port)
|
|
210
|
-
return registration_pb2.RegisterResponse(success=True)
|
|
211
|
-
|
|
212
|
-
def DeregisterModule( # noqa: N802
|
|
213
|
-
self,
|
|
214
|
-
request: registration_pb2.DeregisterRequest,
|
|
215
|
-
context: grpc.ServicerContext,
|
|
216
|
-
) -> registration_pb2.DeregisterResponse:
|
|
217
|
-
"""Deregister a module from the registry.
|
|
218
|
-
|
|
219
|
-
Removes a module from the registry based on its ID.
|
|
220
|
-
Fails if the specified module is not found in the registry.
|
|
221
|
-
|
|
222
|
-
Args:
|
|
223
|
-
request: The deregister request containing the module ID.
|
|
224
|
-
context: The gRPC context for setting status codes and details.
|
|
225
|
-
|
|
226
|
-
Returns:
|
|
227
|
-
registration_pb2.DeregisterResponse: A response indicating success or failure.
|
|
228
|
-
"""
|
|
229
|
-
module_id = request.module_id
|
|
230
|
-
logger.debug("Deregistering module: %s", module_id)
|
|
231
|
-
|
|
232
|
-
# Check if module exists in registry
|
|
233
|
-
if module_id not in self.registered_modules:
|
|
234
|
-
message = f"Module {module_id} not found in registry"
|
|
235
|
-
logger.warning(message)
|
|
236
|
-
|
|
237
|
-
context.set_code(grpc.StatusCode.NOT_FOUND)
|
|
238
|
-
context.set_details(message)
|
|
239
|
-
return registration_pb2.DeregisterResponse()
|
|
240
|
-
|
|
241
|
-
# Remove the module
|
|
242
|
-
del self.registered_modules[module_id]
|
|
243
|
-
|
|
244
|
-
logger.debug("Module %s deregistered", module_id)
|
|
245
|
-
return registration_pb2.DeregisterResponse(success=True)
|
|
246
|
-
|
|
247
|
-
def DiscoverInfoModule( # noqa: N802
|
|
248
|
-
self,
|
|
249
|
-
request: discover_pb2.DiscoverInfoRequest,
|
|
250
|
-
context: grpc.ServicerContext,
|
|
251
|
-
) -> discover_pb2.DiscoverInfoResponse:
|
|
252
|
-
"""Discover detailed information about a specific module.
|
|
253
|
-
|
|
254
|
-
Retrieves complete information about a module based on its ID.
|
|
255
|
-
|
|
256
|
-
Args:
|
|
257
|
-
request: The discover request containing the module ID.
|
|
258
|
-
context: The gRPC context (unused).
|
|
259
|
-
|
|
260
|
-
Returns:
|
|
261
|
-
discover_pb2.DiscoverInfoResponse: A response containing the module's information.
|
|
262
|
-
"""
|
|
263
|
-
logger.debug("Discovering module: %s", request.module_id)
|
|
264
|
-
|
|
265
|
-
# Check if module exists in registry
|
|
266
|
-
if request.module_id not in self.registered_modules:
|
|
267
|
-
message = f"Module {request.module_id} not found in registry"
|
|
268
|
-
logger.warning(message)
|
|
269
|
-
context.set_code(grpc.StatusCode.NOT_FOUND)
|
|
270
|
-
context.set_details(message)
|
|
271
|
-
return discover_pb2.DiscoverInfoResponse()
|
|
272
|
-
return self.registered_modules[request.module_id].to_proto()
|
|
273
|
-
|
|
274
|
-
def DiscoverSearchModule( # noqa: N802
|
|
275
|
-
self,
|
|
276
|
-
request: discover_pb2.DiscoverSearchRequest,
|
|
277
|
-
context: grpc.ServicerContext, # noqa: ARG002
|
|
278
|
-
) -> discover_pb2.DiscoverSearchResponse:
|
|
279
|
-
"""Discover modules based on the specified criteria.
|
|
280
|
-
|
|
281
|
-
Searches for modules that match the provided filters such as name,
|
|
282
|
-
type, and tags.
|
|
283
|
-
|
|
284
|
-
Args:
|
|
285
|
-
request: The discover request containing search criteria.
|
|
286
|
-
context: The gRPC context (unused).
|
|
287
|
-
|
|
288
|
-
Returns:
|
|
289
|
-
discover_pb2.DiscoverSearchResponse: A response containing matching modules.
|
|
290
|
-
"""
|
|
291
|
-
logger.debug("Discovering modules with criteria:")
|
|
292
|
-
|
|
293
|
-
# Start with all modules
|
|
294
|
-
results = list(self.registered_modules.values())
|
|
295
|
-
logger.debug("%s", list(results))
|
|
296
|
-
# Filter by name if specified
|
|
297
|
-
if request.name:
|
|
298
|
-
logger.debug("\tname %s", request.name)
|
|
299
|
-
results = [m for m in results if request.name in m.metadata.name]
|
|
300
|
-
|
|
301
|
-
# Filter by type if specified
|
|
302
|
-
if request.module_type:
|
|
303
|
-
logger.debug("\tmodule_type %s", request.module_type)
|
|
304
|
-
results = [m for m in results if m.module_type == request.module_type]
|
|
305
|
-
|
|
306
|
-
# Filter by tags if specified
|
|
307
|
-
if request.tags:
|
|
308
|
-
logger.debug("\ttags %s", request.tags)
|
|
309
|
-
results = [m for m in results if any(tag in m.metadata.tags for tag in request.tags)]
|
|
310
|
-
|
|
311
|
-
# Filter by description if specified
|
|
312
|
-
"""
|
|
313
|
-
if request.description:
|
|
314
|
-
results = [m for m in results if request.description in m.metadata.description]
|
|
315
|
-
"""
|
|
316
|
-
|
|
317
|
-
logger.debug("Found %d matching modules", len(results))
|
|
318
|
-
return discover_pb2.DiscoverSearchResponse(modules=[r.to_proto() for r in results])
|
|
319
|
-
|
|
320
|
-
def GetModuleStatus( # noqa: N802
|
|
321
|
-
self,
|
|
322
|
-
request: status_pb2.ModuleStatusRequest,
|
|
323
|
-
context: grpc.ServicerContext,
|
|
324
|
-
) -> status_pb2.ModuleStatusResponse:
|
|
325
|
-
"""Query a specific module's status.
|
|
326
|
-
|
|
327
|
-
Retrieves the current status of a module based on its ID.
|
|
328
|
-
|
|
329
|
-
Args:
|
|
330
|
-
request: The status request containing the module ID.
|
|
331
|
-
context: The gRPC context (unused).
|
|
332
|
-
|
|
333
|
-
Returns:
|
|
334
|
-
status_pb2.ModuleStatusResponse: A response containing the module's status.
|
|
335
|
-
"""
|
|
336
|
-
logger.debug("Getting status for module: %s", request.module_id)
|
|
337
|
-
|
|
338
|
-
# Check if module exists in registry
|
|
339
|
-
if request.module_id not in self.registered_modules:
|
|
340
|
-
message = f"Module {request.module_id} not found in registry"
|
|
341
|
-
logger.warning(message)
|
|
342
|
-
context.set_code(grpc.StatusCode.NOT_FOUND)
|
|
343
|
-
context.set_details(message)
|
|
344
|
-
return status_pb2.ModuleStatusResponse()
|
|
345
|
-
|
|
346
|
-
module = self.registered_modules[request.module_id]
|
|
347
|
-
return status_pb2.ModuleStatusResponse(module_id=module.module_id, status=module.status.value)
|
|
348
|
-
|
|
349
|
-
def ListModuleStatus( # noqa: N802
|
|
350
|
-
self,
|
|
351
|
-
request: status_pb2.ListModulesStatusRequest,
|
|
352
|
-
context: grpc.ServicerContext,
|
|
353
|
-
) -> status_pb2.ListModulesStatusResponse:
|
|
354
|
-
"""Get a paginated list of registered modules and their statuses.
|
|
355
|
-
|
|
356
|
-
Returns a subset of registered modules based on pagination parameters.
|
|
357
|
-
|
|
358
|
-
Args:
|
|
359
|
-
request: The request containing offset and list_size for pagination.
|
|
360
|
-
context: The gRPC context (unused).
|
|
361
|
-
|
|
362
|
-
Returns:
|
|
363
|
-
status_pb2.ListModulesStatusResponse: A response containing a list of module statuses.
|
|
364
|
-
"""
|
|
365
|
-
logger.debug(
|
|
366
|
-
"Getting registered modules with offset %d and limit %d",
|
|
367
|
-
request.offset,
|
|
368
|
-
request.list_size,
|
|
369
|
-
)
|
|
370
|
-
if request.offset > len(self.registered_modules):
|
|
371
|
-
message = f"Out of range {request.offset}"
|
|
372
|
-
logger.warning(message)
|
|
373
|
-
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
|
|
374
|
-
context.set_details(message)
|
|
375
|
-
return status_pb2.ListModulesStatusResponse()
|
|
376
|
-
|
|
377
|
-
list_size = request.list_size
|
|
378
|
-
if list_size == 0:
|
|
379
|
-
list_size = len(self.registered_modules)
|
|
380
|
-
|
|
381
|
-
modules_statuses = [
|
|
382
|
-
status_pb2.ModuleStatusResponse(module_id=module.module_id, status=module.status.value)
|
|
383
|
-
for module in list(self.registered_modules.values())[request.offset : request.offset + list_size]
|
|
384
|
-
]
|
|
385
|
-
|
|
386
|
-
logger.debug("Found %d registered modules", len(modules_statuses))
|
|
387
|
-
return status_pb2.ListModulesStatusResponse(
|
|
388
|
-
list_size=len(modules_statuses),
|
|
389
|
-
modules_statuses=modules_statuses,
|
|
390
|
-
)
|
|
391
|
-
|
|
392
|
-
def GetAllModuleStatus( # noqa: N802
|
|
393
|
-
self,
|
|
394
|
-
request: status_pb2.GetAllModulesStatusRequest, # noqa: ARG002
|
|
395
|
-
context: grpc.ServicerContext, # noqa: ARG002
|
|
396
|
-
) -> Iterator[status_pb2.ModuleStatusResponse]:
|
|
397
|
-
"""Get all registered modules via a stream.
|
|
398
|
-
|
|
399
|
-
Streams the status of all registered modules one by one.
|
|
400
|
-
|
|
401
|
-
Args:
|
|
402
|
-
request: The get all modules request (unused).
|
|
403
|
-
context: The gRPC context (unused).
|
|
404
|
-
|
|
405
|
-
Yields:
|
|
406
|
-
status_pb2.ModuleStatusResponse: Responses containing individual module statuses.
|
|
407
|
-
"""
|
|
408
|
-
logger.debug("Streaming all %d registered modules", len(self.registered_modules))
|
|
409
|
-
for module in self.registered_modules.values():
|
|
410
|
-
yield status_pb2.ModuleStatusResponse(
|
|
411
|
-
module_id=module.module_id,
|
|
412
|
-
status=module.status.value,
|
|
413
|
-
)
|
|
414
|
-
|
|
415
|
-
def UpdateModuleStatus( # noqa: N802
|
|
416
|
-
self,
|
|
417
|
-
request: status_pb2.UpdateStatusRequest,
|
|
418
|
-
context: grpc.ServicerContext,
|
|
419
|
-
) -> status_pb2.UpdateStatusResponse:
|
|
420
|
-
"""Update the status of a registered module.
|
|
421
|
-
|
|
422
|
-
Changes the current status of a module based on the provided request.
|
|
423
|
-
Fails if the specified module is not found in the registry.
|
|
424
|
-
|
|
425
|
-
Args:
|
|
426
|
-
request: The update status request with module ID and new status.
|
|
427
|
-
context: The gRPC context (unused).
|
|
428
|
-
|
|
429
|
-
Returns:
|
|
430
|
-
status_pb2.UpdateStatusResponse: A response indicating success or failure.
|
|
431
|
-
"""
|
|
432
|
-
module_id = request.module_id
|
|
433
|
-
logger.debug("Updating status for module: %s to %s", module_id, request.status)
|
|
434
|
-
|
|
435
|
-
# Check if module exists in registry
|
|
436
|
-
if request.module_id not in self.registered_modules:
|
|
437
|
-
message = f"Module {request.module_id} not found in registry"
|
|
438
|
-
logger.warning(message)
|
|
439
|
-
context.set_code(grpc.StatusCode.NOT_FOUND)
|
|
440
|
-
context.set_details(message)
|
|
441
|
-
return status_pb2.UpdateStatusResponse()
|
|
442
|
-
|
|
443
|
-
# Check if module status is correct
|
|
444
|
-
if request.status not in ModuleStatus.list() or request.status is None:
|
|
445
|
-
message = f"ModuleStatus {request.status} is unknonw, please check the requested status"
|
|
446
|
-
logger.warning(message)
|
|
447
|
-
context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
|
|
448
|
-
context.set_details(message)
|
|
449
|
-
return status_pb2.UpdateStatusResponse(success=False)
|
|
450
|
-
|
|
451
|
-
# Update module status
|
|
452
|
-
module_info = self.registered_modules[module_id]
|
|
453
|
-
module_info.status = ModuleStatus(request.status)
|
|
454
|
-
|
|
455
|
-
logger.debug("Status for module %s updated to %s", module_id, request.status)
|
|
456
|
-
return status_pb2.UpdateStatusResponse(success=True)
|