digitalkin 0.2.12__py3-none-any.whl → 0.2.13__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.
Files changed (36) hide show
  1. digitalkin/__version__.py +1 -1
  2. digitalkin/grpc_servers/_base_server.py +15 -17
  3. digitalkin/grpc_servers/module_server.py +9 -10
  4. digitalkin/grpc_servers/module_servicer.py +107 -85
  5. digitalkin/grpc_servers/registry_server.py +3 -6
  6. digitalkin/grpc_servers/registry_servicer.py +18 -19
  7. digitalkin/grpc_servers/utils/grpc_client_wrapper.py +3 -5
  8. digitalkin/logger.py +45 -1
  9. digitalkin/models/module/module.py +1 -0
  10. digitalkin/modules/_base_module.py +44 -5
  11. digitalkin/modules/job_manager/base_job_manager.py +139 -0
  12. digitalkin/modules/job_manager/job_manager_models.py +44 -0
  13. digitalkin/modules/job_manager/single_job_manager.py +218 -0
  14. digitalkin/modules/job_manager/taskiq_broker.py +173 -0
  15. digitalkin/modules/job_manager/taskiq_job_manager.py +213 -0
  16. digitalkin/services/cost/default_cost.py +8 -4
  17. digitalkin/services/cost/grpc_cost.py +15 -7
  18. digitalkin/services/filesystem/default_filesystem.py +2 -4
  19. digitalkin/services/filesystem/grpc_filesystem.py +8 -5
  20. digitalkin/services/setup/__init__.py +1 -0
  21. digitalkin/services/setup/default_setup.py +10 -12
  22. digitalkin/services/setup/grpc_setup.py +8 -10
  23. digitalkin/services/storage/default_storage.py +11 -5
  24. digitalkin/services/storage/grpc_storage.py +23 -8
  25. digitalkin/utils/arg_parser.py +5 -48
  26. digitalkin/utils/development_mode_action.py +51 -0
  27. {digitalkin-0.2.12.dist-info → digitalkin-0.2.13.dist-info}/METADATA +42 -11
  28. {digitalkin-0.2.12.dist-info → digitalkin-0.2.13.dist-info}/RECORD +35 -28
  29. {digitalkin-0.2.12.dist-info → digitalkin-0.2.13.dist-info}/WHEEL +1 -1
  30. modules/cpu_intensive_module.py +271 -0
  31. modules/minimal_llm_module.py +200 -56
  32. modules/storage_module.py +5 -6
  33. modules/text_transform_module.py +1 -1
  34. digitalkin/modules/job_manager.py +0 -177
  35. {digitalkin-0.2.12.dist-info → digitalkin-0.2.13.dist-info}/licenses/LICENSE +0 -0
  36. {digitalkin-0.2.12.dist-info → digitalkin-0.2.13.dist-info}/top_level.txt +0 -0
@@ -1,16 +1,21 @@
1
1
  """Grpc filesystem."""
2
2
 
3
- import logging
4
3
  from collections.abc import Generator
5
4
  from contextlib import contextmanager
6
5
  from typing import Any
7
6
 
8
- from digitalkin_proto.digitalkin.filesystem.v2 import filesystem_pb2, filesystem_service_pb2_grpc
9
- from digitalkin_proto.digitalkin.filesystem.v2.filesystem_pb2 import FileType as FileTypeProto
7
+ from digitalkin_proto.digitalkin.filesystem.v2 import (
8
+ filesystem_pb2,
9
+ filesystem_service_pb2_grpc,
10
+ )
11
+ from digitalkin_proto.digitalkin.filesystem.v2.filesystem_pb2 import (
12
+ FileType as FileTypeProto,
13
+ )
10
14
 
11
15
  from digitalkin.grpc_servers.utils.exceptions import ServerError
12
16
  from digitalkin.grpc_servers.utils.grpc_client_wrapper import GrpcClientWrapper
13
17
  from digitalkin.grpc_servers.utils.models import ClientConfig
18
+ from digitalkin.logger import logger
14
19
  from digitalkin.services.filesystem.filesystem_strategy import (
15
20
  FilesystemData,
16
21
  FilesystemServiceError,
@@ -18,8 +23,6 @@ from digitalkin.services.filesystem.filesystem_strategy import (
18
23
  FileType,
19
24
  )
20
25
 
21
- logger = logging.getLogger(__name__)
22
-
23
26
 
24
27
  class GrpcFilesystem(FilesystemStrategy, GrpcClientWrapper):
25
28
  """Default state filesystem strategy."""
@@ -0,0 +1 @@
1
+ """This module is responsible for handling the setup service."""
@@ -1,17 +1,15 @@
1
1
  """This module contains the abstract base class for setup strategies."""
2
2
 
3
- import logging
4
3
  import secrets
5
4
  import string
6
5
  from typing import Any
7
6
 
8
7
  from pydantic import ValidationError
9
8
 
9
+ from digitalkin.logger import logger
10
10
  from digitalkin.services.setup.grpc_setup import SetupData, SetupVersionData
11
11
  from digitalkin.services.setup.setup_strategy import SetupServiceError, SetupStrategy
12
12
 
13
- logger = logging.getLogger(__name__)
14
-
15
13
 
16
14
  class DefaultSetup(SetupStrategy):
17
15
  """Abstract base class for setup strategies."""
@@ -49,7 +47,7 @@ class DefaultSetup(SetupStrategy):
49
47
  )
50
48
  valid_data.id = setup_id
51
49
  self.setups[setup_id] = valid_data
52
- logger.info("CREATE SETUP DATA %s:%s succesfull", setup_id, valid_data)
50
+ logger.debug("CREATE SETUP DATA %s:%s succesfull", setup_id, valid_data)
53
51
  return setup_id
54
52
 
55
53
  def get_setup(self, setup_dict: dict[str, Any]) -> SetupData:
@@ -64,7 +62,7 @@ class DefaultSetup(SetupStrategy):
64
62
  Returns:
65
63
  Dict[str, Any]: Setup details including optional setup version.
66
64
  """
67
- logger.info("GET setup_id = %s", setup_dict["setup_id"])
65
+ logger.debug("GET setup_id = %s", setup_dict["setup_id"])
68
66
  if setup_dict["setup_id"] not in self.setups:
69
67
  msg = f"GET setup_id = {setup_dict['setup_id']}: setup_id DOESN'T EXIST"
70
68
  logger.error(msg)
@@ -84,7 +82,7 @@ class DefaultSetup(SetupStrategy):
84
82
  bool: Success status of the update operation.
85
83
  """
86
84
  if setup_dict["setup_id"] not in self.setups:
87
- logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_dict["setup_id"])
85
+ logger.debug("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_dict["setup_id"])
88
86
  return False
89
87
 
90
88
  try:
@@ -106,7 +104,7 @@ class DefaultSetup(SetupStrategy):
106
104
  bool: Success status of deletion.
107
105
  """
108
106
  if setup_dict["setup_id"] not in self.setups:
109
- logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_dict["setup_id"])
107
+ logger.debug("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_dict["setup_id"])
110
108
  return False
111
109
  del self.setups[setup_dict["setup_id"]]
112
110
  return True
@@ -133,7 +131,7 @@ class DefaultSetup(SetupStrategy):
133
131
  if setup_version_dict["setup_id"] not in self.setup_versions:
134
132
  self.setup_versions[setup_version_dict["setup_id"]] = {}
135
133
  self.setup_versions[setup_version_dict["setup_id"]][valid_data.version] = valid_data
136
- logger.info("CREATE SETUP VERSION DATA %s:%s succesfull", setup_version_dict["setup_id"], valid_data)
134
+ logger.debug("CREATE SETUP VERSION DATA %s:%s succesfull", setup_version_dict["setup_id"], valid_data)
137
135
  return valid_data.version
138
136
 
139
137
  def get_setup_version(self, setup_version_dict: dict[str, Any]) -> SetupVersionData:
@@ -148,7 +146,7 @@ class DefaultSetup(SetupStrategy):
148
146
  Returns:
149
147
  Dict[str, Any]: Setup version details.
150
148
  """
151
- logger.info("GET setup_id = %s: version = %s", setup_version_dict["setup_id"], setup_version_dict["version"])
149
+ logger.debug("GET setup_id = %s: version = %s", setup_version_dict["setup_id"], setup_version_dict["version"])
152
150
  if setup_version_dict["setup_id"] not in self.setup_versions:
153
151
  msg = f"GET setup_id = {setup_version_dict['setup_id']}: setup_id DOESN'T EXIST"
154
152
  logger.error(msg)
@@ -189,11 +187,11 @@ class DefaultSetup(SetupStrategy):
189
187
  bool: Success status of the update operation.
190
188
  """
191
189
  if setup_version_dict["setup_id"] not in self.setup_versions:
192
- logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
190
+ logger.debug("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
193
191
  return False
194
192
 
195
193
  if setup_version_dict["version"] not in self.setup_versions["setup_id"]:
196
- logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
194
+ logger.debug("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
197
195
  return False
198
196
 
199
197
  try:
@@ -215,7 +213,7 @@ class DefaultSetup(SetupStrategy):
215
213
  bool: Success status of version deletion.
216
214
  """
217
215
  if setup_version_dict["setup_id"] not in self.setup_versions:
218
- logger.info("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
216
+ logger.debug("UPDATE setup_id = %s: setup_id DOESN'T EXIST", setup_version_dict["setup_id"])
219
217
  return False
220
218
 
221
219
  del self.setup_versions[setup_version_dict["setup_id"]][setup_version_dict["version"]]
@@ -1,6 +1,5 @@
1
1
  """Digital Kin Setup Service gRPC Client."""
2
2
 
3
- import logging
4
3
  from collections.abc import Generator
5
4
  from contextlib import contextmanager
6
5
  from typing import Any
@@ -17,10 +16,9 @@ from pydantic import ValidationError
17
16
  from digitalkin.grpc_servers.utils.exceptions import ServerError
18
17
  from digitalkin.grpc_servers.utils.grpc_client_wrapper import GrpcClientWrapper
19
18
  from digitalkin.grpc_servers.utils.models import ClientConfig
19
+ from digitalkin.logger import logger
20
20
  from digitalkin.services.setup.setup_strategy import SetupData, SetupServiceError, SetupStrategy, SetupVersionData
21
21
 
22
- logger = logging.getLogger(__name__)
23
-
24
22
 
25
23
  class GrpcSetup(SetupStrategy, GrpcClientWrapper):
26
24
  """This class implements the gRPC setup service."""
@@ -32,7 +30,7 @@ class GrpcSetup(SetupStrategy, GrpcClientWrapper):
32
30
  """
33
31
  channel = self._init_channel(config)
34
32
  self.stub = setup_service_pb2_grpc.SetupServiceStub(channel)
35
- logger.info("Channel client 'setup' initialized succesfully")
33
+ logger.debug("Channel client 'setup' initialized succesfully")
36
34
 
37
35
  @contextmanager
38
36
  def _handle_grpc_errors(self, operation: str) -> Generator[Any, Any, Any]: # noqa: PLR6301
@@ -89,7 +87,7 @@ class GrpcSetup(SetupStrategy, GrpcClientWrapper):
89
87
  current_setup_version=setup_pb2.SetupVersion(**valid_data.current_setup_version.model_dump()),
90
88
  )
91
89
  response = self.exec_grpc_query("CreateSetup", request)
92
- logger.info("Setup '%s' query sent successfully", valid_data.name)
90
+ logger.debug("Setup '%s' query sent successfully", valid_data.name)
93
91
  return response
94
92
 
95
93
  def get_setup(self, setup_dict: dict[str, Any]) -> SetupData:
@@ -146,7 +144,7 @@ class GrpcSetup(SetupStrategy, GrpcClientWrapper):
146
144
  current_setup_version=current_setup_version,
147
145
  )
148
146
  response = self.exec_grpc_query("UpdateSetup", request)
149
- logger.info("Setup '%s' query sent successfully", valid_data.name)
147
+ logger.debug("Setup '%s' query sent successfully", valid_data.name)
150
148
  return getattr(response, "success", False)
151
149
 
152
150
  def delete_setup(self, setup_dict: dict[str, Any]) -> bool:
@@ -170,7 +168,7 @@ class GrpcSetup(SetupStrategy, GrpcClientWrapper):
170
168
  raise ValidationError(msg)
171
169
  request = setup_pb2.DeleteSetupRequest(setup_id=setup_id)
172
170
  response = self.exec_grpc_query("DeleteSetup", request)
173
- logger.info("Setup '%s' query sent successfully", setup_id)
171
+ logger.debug("Setup '%s' query sent successfully", setup_id)
174
172
  return getattr(response, "success", False)
175
173
 
176
174
  def create_setup_version(self, setup_version_dict: dict[str, Any]) -> str:
@@ -196,7 +194,7 @@ class GrpcSetup(SetupStrategy, GrpcClientWrapper):
196
194
  version=valid_data.version,
197
195
  content=content_struct,
198
196
  )
199
- logger.info(
197
+ logger.debug(
200
198
  "Setup Version '%s' for setup '%s' query sent successfully",
201
199
  valid_data.version,
202
200
  valid_data.setup_id,
@@ -275,7 +273,7 @@ class GrpcSetup(SetupStrategy, GrpcClientWrapper):
275
273
  content=content_struct,
276
274
  )
277
275
  response = self.exec_grpc_query("UpdateSetupVersion", request)
278
- logger.info(
276
+ logger.debug(
279
277
  "Setup Version '%s' for setup '%s' query sent successfully",
280
278
  valid_data.id,
281
279
  valid_data.setup_id,
@@ -303,5 +301,5 @@ class GrpcSetup(SetupStrategy, GrpcClientWrapper):
303
301
  raise ValidationError(msg)
304
302
  request = setup_pb2.DeleteSetupVersionRequest(setup_version_id=setup_version_id)
305
303
  response = self.exec_grpc_query("DeleteSetupVersion", request)
306
- logger.info("Setup Version '%s' query sent successfully", setup_version_id)
304
+ logger.debug("Setup Version '%s' query sent successfully", setup_version_id)
307
305
  return getattr(response, "success", False)
@@ -2,16 +2,18 @@
2
2
 
3
3
  import datetime
4
4
  import json
5
- import logging
6
5
  import tempfile
7
6
  from pathlib import Path
8
7
  from typing import Any
9
8
 
10
9
  from pydantic import BaseModel
11
10
 
12
- from digitalkin.services.storage.storage_strategy import DataType, StorageRecord, StorageStrategy
13
-
14
- logger = logging.getLogger(__name__)
11
+ from digitalkin.logger import logger
12
+ from digitalkin.services.storage.storage_strategy import (
13
+ DataType,
14
+ StorageRecord,
15
+ StorageStrategy,
16
+ )
15
17
 
16
18
 
17
19
  class DefaultStorage(StorageStrategy):
@@ -80,7 +82,11 @@ class DefaultStorage(StorageStrategy):
80
82
  """Atomically write `self.storage` back to disk as JSON."""
81
83
  self.storage_file.parent.mkdir(parents=True, exist_ok=True)
82
84
  with tempfile.NamedTemporaryFile(
83
- mode="w", encoding="utf-8", delete=False, dir=str(self.storage_file.parent), suffix=".tmp"
85
+ mode="w",
86
+ encoding="utf-8",
87
+ delete=False,
88
+ dir=str(self.storage_file.parent),
89
+ suffix=".tmp",
84
90
  ) as temp:
85
91
  try:
86
92
  # Convert storage to a serializable format
@@ -1,7 +1,5 @@
1
1
  """This module implements the default storage strategy."""
2
2
 
3
- import logging
4
-
5
3
  from digitalkin_proto.digitalkin.storage.v2 import data_pb2, storage_service_pb2_grpc
6
4
  from google.protobuf import json_format
7
5
  from google.protobuf.struct_pb2 import Struct
@@ -9,9 +7,13 @@ from pydantic import BaseModel
9
7
 
10
8
  from digitalkin.grpc_servers.utils.grpc_client_wrapper import GrpcClientWrapper
11
9
  from digitalkin.grpc_servers.utils.models import ClientConfig
12
- from digitalkin.services.storage.storage_strategy import DataType, StorageRecord, StorageServiceError, StorageStrategy
13
-
14
- logger = logging.getLogger(__name__)
10
+ from digitalkin.logger import logger
11
+ from digitalkin.services.storage.storage_strategy import (
12
+ DataType,
13
+ StorageRecord,
14
+ StorageServiceError,
15
+ StorageStrategy,
16
+ )
15
17
 
16
18
 
17
19
  class GrpcStorage(StorageStrategy, GrpcClientWrapper):
@@ -73,7 +75,11 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
73
75
  resp = self.exec_grpc_query("StoreRecord", req)
74
76
  return self._build_record_from_proto(resp.stored_data)
75
77
  except Exception as e:
76
- logger.exception("gRPC StoreRecord failed for %s:%s", record.collection, record.record_id)
78
+ logger.exception(
79
+ "gRPC StoreRecord failed for %s:%s",
80
+ record.collection,
81
+ record.record_id,
82
+ )
77
83
  raise StorageServiceError(str(e)) from e
78
84
 
79
85
  def _read(self, collection: str, record_id: str) -> StorageRecord | None:
@@ -94,7 +100,12 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
94
100
  logger.exception("gRPC ReadRecord failed for %s:%s", collection, record_id)
95
101
  return None
96
102
 
97
- def _update(self, collection: str, record_id: str, data: BaseModel) -> StorageRecord | None:
103
+ def _update(
104
+ self,
105
+ collection: str,
106
+ record_id: str,
107
+ data: BaseModel,
108
+ ) -> StorageRecord | None:
98
109
  """Overwrite a document via gRPC.
99
110
 
100
111
  Args:
@@ -138,7 +149,11 @@ class GrpcStorage(StorageStrategy, GrpcClientWrapper):
138
149
  )
139
150
  self.exec_grpc_query("RemoveRecord", req)
140
151
  except Exception:
141
- logger.exception("gRPC RemoveRecord failed for %s:%s", collection, record_id)
152
+ logger.exception(
153
+ "gRPC RemoveRecord failed for %s:%s",
154
+ collection,
155
+ record_id,
156
+ )
142
157
  return False
143
158
  return True
144
159
 
@@ -1,15 +1,13 @@
1
1
  """ArgParser and Action classes to ease command lines arguments settings."""
2
2
 
3
3
  import logging
4
- import os
5
- from argparse import Action, ArgumentParser, Namespace, _HelpAction, _SubParsersAction # noqa: PLC2701
4
+ from argparse import ArgumentParser, Namespace, _HelpAction, _SubParsersAction # noqa: PLC2701
6
5
  from collections.abc import Sequence
7
6
  from typing import Any
8
7
 
9
- from digitalkin.services.services_models import ServicesMode
8
+ from digitalkin.logger import logger
10
9
 
11
- logging.getLogger().setLevel(logging.INFO)
12
- logger = logging.getLogger(__name__)
10
+ logger.setLevel(logging.INFO)
13
11
 
14
12
 
15
13
  class ArgParser:
@@ -81,11 +79,9 @@ class ArgParser:
81
79
  def _add_parser_args(self, parser: ArgumentParser) -> None:
82
80
  parser.add_argument("-h", "--help", action=self.HelpAction, help="help usage")
83
81
 
84
- @staticmethod
85
- def _add_exclusive_args(parser: ArgumentParser) -> None: ...
82
+ def _add_exclusive_args(self, parser: ArgumentParser) -> None: ...
86
83
 
87
- @staticmethod
88
- def _add_subparser_args(parser: ArgumentParser) -> None: ...
84
+ def _add_subparser_args(self, parser: ArgumentParser) -> None: ...
89
85
 
90
86
  def __init__(self, prog: str = "PROG") -> None:
91
87
  """Create prser and call abstract methods."""
@@ -94,42 +90,3 @@ class ArgParser:
94
90
  self._add_exclusive_args(self.parser)
95
91
  self._add_subparser_args(self.parser)
96
92
  self.args, _ = self.parser.parse_known_args()
97
-
98
-
99
- class DevelopmentModeMappingAction(Action):
100
- """."""
101
-
102
- def __init__(
103
- self,
104
- env_var: str,
105
- required: bool = True, # noqa: FBT001, FBT002
106
- default: str | None = None,
107
- **kwargs: dict[str, Any],
108
- ) -> None:
109
- """."""
110
- default = ServicesMode(os.environ.get(env_var, default))
111
-
112
- if required and default:
113
- required = False
114
- super().__init__(default=default, required=required, **kwargs) # type: ignore
115
-
116
- def __call__(
117
- self,
118
- parser: ArgumentParser, # noqa: ARG002
119
- namespace: Namespace,
120
- values: str | Sequence[Any] | None,
121
- option_string: str | None = None, # noqa: ARG002
122
- ) -> None:
123
- """Set the attribute to the corresponding class.
124
-
125
- Raises:
126
- TypeError: if the value is not a string.
127
- """
128
- # Check if the value is a string and convert it to lowercase
129
- if isinstance(values, str):
130
- values = values.lower()
131
- else:
132
- msg = "values must be a string"
133
- raise TypeError(msg)
134
- mode = ServicesMode(values)
135
- setattr(namespace, self.dest, mode)
@@ -0,0 +1,51 @@
1
+ """ArgParser and Action classes to ease command lines arguments settings."""
2
+
3
+ import logging
4
+ import os
5
+ from argparse import Action, ArgumentParser, Namespace
6
+ from collections.abc import Sequence
7
+ from typing import Any
8
+
9
+ from digitalkin.logger import logger
10
+ from digitalkin.services.services_models import ServicesMode
11
+
12
+ logger.setLevel(logging.INFO)
13
+
14
+
15
+ class DevelopmentModeMappingAction(Action):
16
+ """."""
17
+
18
+ def __init__(
19
+ self,
20
+ env_var: str,
21
+ required: bool = True, # noqa: FBT001, FBT002
22
+ default: str | None = None,
23
+ **kwargs: dict[str, Any],
24
+ ) -> None:
25
+ """."""
26
+ default = ServicesMode(os.environ.get(env_var, default))
27
+
28
+ if required and default:
29
+ required = False
30
+ super().__init__(default=default, required=required, **kwargs) # type: ignore
31
+
32
+ def __call__(
33
+ self,
34
+ parser: ArgumentParser, # noqa: ARG002
35
+ namespace: Namespace,
36
+ values: str | Sequence[Any] | None,
37
+ option_string: str | None = None, # noqa: ARG002
38
+ ) -> None:
39
+ """Set the attribute to the corresponding class.
40
+
41
+ Raises:
42
+ TypeError: if the value is not a string.
43
+ """
44
+ # Check if the value is a string and convert it to lowercase
45
+ if isinstance(values, str):
46
+ values = values.lower()
47
+ else:
48
+ msg = "values must be a string"
49
+ raise TypeError(msg)
50
+ mode = ServicesMode(values)
51
+ setattr(namespace, self.dest, mode)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: digitalkin
3
- Version: 0.2.12
3
+ Version: 0.2.13
4
4
  Summary: SDK to build kin used in DigitalKin
5
5
  Author-email: "DigitalKin.ai" <contact@digitalkin.ai>
6
6
  License: Attribution-NonCommercial-ShareAlike 4.0 International
@@ -456,25 +456,32 @@ Requires-Dist: digitalkin-proto>=0.1.10
456
456
  Requires-Dist: grpcio-health-checking>=1.71.0
457
457
  Requires-Dist: grpcio-reflection>=1.71.0
458
458
  Requires-Dist: grpcio-status>=1.71.0
459
- Requires-Dist: openai>=1.76.2
460
459
  Requires-Dist: pydantic>=2.11.4
461
460
  Provides-Extra: dev
462
- Requires-Dist: pytest>=8.3.4; extra == "dev"
463
- Requires-Dist: pytest-asyncio>=0.26.0; extra == "dev"
464
- Requires-Dist: pytest-cov>=6.1.0; extra == "dev"
465
- Requires-Dist: typos>=1.31.2; extra == "dev"
466
- Requires-Dist: ruff>=0.11.7; extra == "dev"
461
+ Requires-Dist: typos>=1.32.0; extra == "dev"
462
+ Requires-Dist: ruff>=0.11.9; extra == "dev"
467
463
  Requires-Dist: mypy>=1.15.0; extra == "dev"
468
464
  Requires-Dist: pyright>=1.1.400; extra == "dev"
469
465
  Requires-Dist: pre-commit>=4.2.0; extra == "dev"
470
466
  Requires-Dist: bump2version>=1.0.1; extra == "dev"
471
467
  Requires-Dist: build>=1.2.2; extra == "dev"
472
468
  Requires-Dist: twine>=6.1.0; extra == "dev"
473
- Requires-Dist: cryptography>=44.0.2; extra == "dev"
474
- Requires-Dist: grpcio-testing>=1.71.0; extra == "dev"
475
- Requires-Dist: freezegun>=1.5.1; extra == "dev"
469
+ Requires-Dist: cryptography>=44.0.3; extra == "dev"
470
+ Requires-Dist: taskiq[reload]>=0.11.17; extra == "dev"
476
471
  Provides-Extra: examples
477
- Requires-Dist: openai>=1.66.3; extra == "examples"
472
+ Requires-Dist: openai>=1.75.0; extra == "examples"
473
+ Provides-Extra: tests
474
+ Requires-Dist: freezegun>=1.5.1; extra == "tests"
475
+ Requires-Dist: hdrhistogram>=0.10.3; extra == "tests"
476
+ Requires-Dist: grpcio-testing>=1.71.0; extra == "tests"
477
+ Requires-Dist: psutil>=7.0.0; extra == "tests"
478
+ Requires-Dist: pytest>=8.3.4; extra == "tests"
479
+ Requires-Dist: pytest-asyncio>=0.26.0; extra == "tests"
480
+ Requires-Dist: pytest-cov>=6.1.0; extra == "tests"
481
+ Provides-Extra: taskiq
482
+ Requires-Dist: rstream>=0.20.9; extra == "taskiq"
483
+ Requires-Dist: taskiq-aio-pika>=0.4.2; extra == "taskiq"
484
+ Requires-Dist: taskiq-redis>=1.0.8; extra == "taskiq"
478
485
  Dynamic: license-file
479
486
 
480
487
  # DigitalKin Python SDK
@@ -509,6 +516,16 @@ To install the DigitalKin SDK, simply run:
509
516
  pip install digitalkin
510
517
  ```
511
518
 
519
+ **Optional Taskiq Integration**: Asynchronous task execution powered by Taskiq, backed by RabbitMQ and Redis
520
+ To enable the Rabbitmq streaming capabilities, run:
521
+
522
+ ```sh
523
+ sudo rabbitmq-plugins enable rabbitmq_stream
524
+
525
+ # Core + Taskiq integration (RabbitMQ broker)
526
+ pip install digitalkin[taskiq]
527
+ ```
528
+
512
529
  ## 🛠️ Usage
513
530
 
514
531
  ### Basic Import
@@ -519,6 +536,20 @@ Start by importing the necessary modules:
519
536
  import digitalkin
520
537
  ```
521
538
 
539
+ ## Features
540
+
541
+ ### Taskiq with RabbitMQ
542
+
543
+ TaskIQ intergration allows the module to scale for heavy CPU tasks by having the request's stateless module in a new instance.
544
+
545
+ - **Decoupled Scalability**: RabbitMQ brokers messages, letting producers and consumers scale independently.
546
+ - **Reliability**: Durable queues, acknowledgements, and dead-lettering ensure tasks aren’t lost.
547
+ - **Concurrency Control**: Taskiq’s worker pool manages parallel execution without custom schedulers.
548
+ - **Flexibility**: Built-in retries, exponential backoff, and Redis result-backend for resilient workflows.
549
+ - **Ecosystem**: Battle-tested `aio-pika` AMQP client plus Taskiq’s decorator-based API.
550
+
551
+ By combining Taskiq’s async API with RabbitMQ’s guarantees, you get a robust, production-ready queue with minimal boilerplate.
552
+
522
553
  ## 👷‍♂️ Development
523
554
 
524
555
  ### Prerequisites
@@ -7,33 +7,37 @@ base_server/mock/__init__.py,sha256=YZFT-F1l_TpvJYuIPX-7kTeE1CfOjhx9YmNRXVoi-jQ,
7
7
  base_server/mock/mock_pb2.py,sha256=sETakcS3PAAm4E-hTCV1jIVaQTPEAIoVVHupB8Z_k7Y,1843
8
8
  base_server/mock/mock_pb2_grpc.py,sha256=BbOT70H6q3laKgkHfOx1QdfmCS_HxCY4wCOX84YAdG4,3180
9
9
  digitalkin/__init__.py,sha256=7LLBAba0th-3SGqcpqFO-lopWdUkVLKzLZiMtB-mW3M,162
10
- digitalkin/__version__.py,sha256=NhqSkQ1MfEwCjG1RWIYDONpYEZDeyyeAwIaGaE1q-Tk,191
11
- digitalkin/logger.py,sha256=9cDgyJV2QXXT8F--xRODFlZyDgjuTTXNdpCU3GdqCsk,382
10
+ digitalkin/__version__.py,sha256=FYm4fUSZE0epsu7qiHq0IkVIvAs5ZzTEDWDQWZeryGs,191
11
+ digitalkin/logger.py,sha256=cFbIAZHOFx3nddOssRNYLXyqUPzR4CgDR_c-5wmB-og,1685
12
12
  digitalkin/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  digitalkin/grpc_servers/__init__.py,sha256=0cJBlwipSmFdXkyH3T0i6OJ1WpAtNsZgYX7JaSnkbtg,804
14
- digitalkin/grpc_servers/_base_server.py,sha256=ec4xmgAuOMVg45a63O_PEa2T7mI4tJ6boxcXauFyZ5g,18649
15
- digitalkin/grpc_servers/module_server.py,sha256=0jC5MN-H4MGA9O9J87gnlM8EHcbrkb0chuCm8yZh7gI,10232
16
- digitalkin/grpc_servers/module_servicer.py,sha256=mbXbfCXjRZHl8ueaYIedWMqw0OneoBU60mtbHV5yAe4,13734
17
- digitalkin/grpc_servers/registry_server.py,sha256=PmWaH4Xmg5Sj7NtFVLBNTOzkOfqo7dw_qyVBnaW4jy4,2238
18
- digitalkin/grpc_servers/registry_servicer.py,sha256=mCAjNhdMq5DozZMEPsJK__DIxePEYxSWV-gAq-Xctk4,16469
14
+ digitalkin/grpc_servers/_base_server.py,sha256=NXnnZPjJqUDWoumhEbb7EOEWB7d8XYwpQs-l97NTe4k,18647
15
+ digitalkin/grpc_servers/module_server.py,sha256=tc4n8fu7bcMkwCI3CKkAKR4cZqyP_JTEW0lGtqsc5hs,10283
16
+ digitalkin/grpc_servers/module_servicer.py,sha256=I6S8qDhKOwDD1tofoUhAfhN8VH6A7hAM5UAlwu91_Is,14747
17
+ digitalkin/grpc_servers/registry_server.py,sha256=StY18DKYoPKQIU1SIzgito6D4_QA1aMVddZ8O2WGlHY,2223
18
+ digitalkin/grpc_servers/registry_servicer.py,sha256=dqsKGHZ0LnaIvGt4ipaAuigd37sbJBndT4MAT029GsY,16471
19
19
  digitalkin/grpc_servers/utils/exceptions.py,sha256=I00OM8p8up20He4dU1fiHsvdLj1DymjR_UmoeUm2MSA,785
20
20
  digitalkin/grpc_servers/utils/factory.py,sha256=jm6rFjiqmtSv7BIHNAOxsG9xXtSvWpx9TfzSQiX97MQ,5899
21
- digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=6gj98T2_siZNlsamfz2Qkg89ebv4rS8Gm_X2FpE6Iow,2613
21
+ digitalkin/grpc_servers/utils/grpc_client_wrapper.py,sha256=GXRqCTCufwWd8sVMoClnl-JpeBjgmdlSCD0a3YMU9D0,2594
22
22
  digitalkin/grpc_servers/utils/models.py,sha256=80F5oHiv8MOqMoDZJBXmJSRoVYJRyhaVcijQ2LinAig,8428
23
23
  digitalkin/grpc_servers/utils/types.py,sha256=rQ78s4nAet2jy-NIDj_PUWriT0kuGHr_w6ELjmjgBao,539
24
24
  digitalkin/models/__init__.py,sha256=hDHtUfswaNh8wo4NZaBItg9JqC0uNSRqXArNWSrGynY,163
25
25
  digitalkin/models/module/__init__.py,sha256=ihvRlemJuFvU4armZIL-Vq-zaJx9UrjDoJAVPbEG8jw,345
26
- digitalkin/models/module/module.py,sha256=vlIeWmH61NVEiJpRx0Crk4iB8hAUV4mG30likSyRFP4,686
26
+ digitalkin/models/module/module.py,sha256=NWOwCeD_NH0NL89AF_NJ0SwE7G1n-HTcRalodLCDmpM,749
27
27
  digitalkin/models/module/module_types.py,sha256=SxwzfDDnkyuQe50glVrxN6VPuJCkbB313FRyVZugIMw,312
28
28
  digitalkin/models/services/__init__.py,sha256=HsW7MUGFPvH7Ri28WN4BHHBfEQk5dzU_9FOWAc-0lSE,56
29
29
  digitalkin/models/services/cost.py,sha256=QTEuFD6xz62nob0z4ksE-INJWcZ-iFiuNW5mvXhpFes,1599
30
30
  digitalkin/models/services/storage.py,sha256=cYTVIriGKiprF9OerhSxmc_jM6fUTVwmeon1yQCinkE,143
31
31
  digitalkin/modules/__init__.py,sha256=ppYARmhvdVi55ofC0QZerIempSlcJYDeCXhcl4qXObw,278
32
- digitalkin/modules/_base_module.py,sha256=jzsB5d51Sp6-K_e9PxJBVLAv0TeVRo7WhYOKM2SvZ_4,9198
32
+ digitalkin/modules/_base_module.py,sha256=EwfCCIy3N1eBdBUj6KAdx0WzNRFJsyQDVCdA8Lwvtn4,10463
33
33
  digitalkin/modules/archetype_module.py,sha256=T2Ehj7EpAC2MO9WQbJv39hqRw7rh3exhVZTEL3JPM8U,421
34
- digitalkin/modules/job_manager.py,sha256=EB53_HZJZOkOR3MXidN8ZiJte8_kOJZ3hnOFVfm5v64,6243
35
34
  digitalkin/modules/tool_module.py,sha256=86g0M1wHZ1ReIc7AkKfyjnlGN2QYJBGxrEQpKVlyrZI,421
36
35
  digitalkin/modules/trigger_module.py,sha256=kVoI4Gdkw7WWUP5T6hSCNqw5FxibTxL6Tpq9KP7gg78,379
36
+ digitalkin/modules/job_manager/base_job_manager.py,sha256=I3bduyGDjCJ6RsbwQvLp_NA6ucP8MJJVoIKpEbaP9ss,4706
37
+ digitalkin/modules/job_manager/job_manager_models.py,sha256=onHy-DfInLZQveniMIWIKwTKSQjojz500JvHB54x93c,1129
38
+ digitalkin/modules/job_manager/single_job_manager.py,sha256=Dekcnn8wb4epqGrWFAZ86YvvII553Hw0xjipgAINl4A,7745
39
+ digitalkin/modules/job_manager/taskiq_broker.py,sha256=OnHZy-hAtVDU5FU4W9folZZKCrDrUk16VfHlfoECuiQ,5930
40
+ digitalkin/modules/job_manager/taskiq_job_manager.py,sha256=ODqC7Snf-Flo0ugotqicrTgjFu4wgll6bUu7CM3l7ZE,7459
37
41
  digitalkin/services/__init__.py,sha256=LqGk_5DJy8Bzz62ajIq9jCeYNKQUIgtSCpafZk15FLc,910
38
42
  digitalkin/services/base_strategy.py,sha256=QAQnJw1BbqcYMSzwlFyhHP5juBH2WKrZzWxqDr_sDHI,638
39
43
  digitalkin/services/services_config.py,sha256=4hc7-rHgSigoS3SuV0V9FReD2Dz7XoMXcD6iMBP2KKM,7391
@@ -43,37 +47,40 @@ digitalkin/services/agent/agent_strategy.py,sha256=42Q9RciHX6tg3CgDQkbrlIx4h_TX0
43
47
  digitalkin/services/agent/default_agent.py,sha256=4N_E_eQxJGOx1KVUUg5jNOje-3ncMxF3ePB-uDuGrJc,345
44
48
  digitalkin/services/cost/__init__.py,sha256=Wi9ZB4LSXFsUYgkX-V1UJQkVXYDNDpp8q2dXccR2uRM,303
45
49
  digitalkin/services/cost/cost_strategy.py,sha256=VhHeqi9WnE1yoDBBVp5qmqwIt5tTZHU6_Z_jld8CVeE,2535
46
- digitalkin/services/cost/default_cost.py,sha256=Be_OZiFBSD4XeM--Cd1B8J2GYMhdoX5z9xAszExmKDg,3860
47
- digitalkin/services/cost/grpc_cost.py,sha256=nGJD6vj8QSPYXTNX9-TJfqeWGHH35EsDZaEISKcznBs,6213
50
+ digitalkin/services/cost/default_cost.py,sha256=mEd0VL_tMcGU41q0f9MFeBYeKZBenv0mIHuwgXlQ7uQ,3869
51
+ digitalkin/services/cost/grpc_cost.py,sha256=p_5mG72N7e4bxwBOD9DNokvLtinBILiqCfllmkqpmhw,6253
48
52
  digitalkin/services/filesystem/__init__.py,sha256=BhwMl_BUvM0d65fmglkp0SVwn3RfYiUOKJgIMnOCaGM,381
49
- digitalkin/services/filesystem/default_filesystem.py,sha256=PNRmLiBOkvAdo84WNZRNLYFXhSTPcJLPtfvY9vRBGPk,7396
53
+ digitalkin/services/filesystem/default_filesystem.py,sha256=8pRO80GtJ3n7StNllvwsgM6vMurJso1Xj4bWBt_zbjw,7381
50
54
  digitalkin/services/filesystem/filesystem_strategy.py,sha256=g5duep7Trc_NWq9WNtCrnheVxfMUvX6vJyx4W0hwwiY,2348
51
- digitalkin/services/filesystem/grpc_filesystem.py,sha256=9wZRnS6S6sssyRJEDtGDunietfxo1bJjJB2prRY155w,8320
55
+ digitalkin/services/filesystem/grpc_filesystem.py,sha256=IN2HX05lzUzsE9BZdp_nhEKYV2GNLJRQLduzFh1JN-w,8326
52
56
  digitalkin/services/identity/__init__.py,sha256=InkeyLgFYYwItx8mePA8HpfacOMWZwwuc0G4pWtKq9s,270
53
57
  digitalkin/services/identity/default_identity.py,sha256=Y2auZHrGSZTIN5D8HyjLvLcNbYFM1CNUE23x7p5VIGw,386
54
58
  digitalkin/services/identity/identity_strategy.py,sha256=skappBbds1_qa0Gr24FGrNX1N0_OYhYT1Lh7dUaAirE,429
55
59
  digitalkin/services/registry/__init__.py,sha256=Zl4QAkCe9tOmmKGBWVuLQVFepdZiL0ec3VDj27IeyYM,270
56
60
  digitalkin/services/registry/default_registry.py,sha256=VnWkF6nHpFxUKuUbZLPqzXqdA6oXmyV_ySpeuOCf_ko,277
57
61
  digitalkin/services/registry/registry_strategy.py,sha256=uBXgZIv25jeXbeVO8vWvlNPxxNYu7_KiCw2PoE6AWr8,423
58
- digitalkin/services/setup/default_setup.py,sha256=x1J6trXhyLC7V2OTe5pRY5mIFkQ4oyi3-aG50a1G1U4,8253
59
- digitalkin/services/setup/grpc_setup.py,sha256=4rLra3Ao0cwVX1L380VYwmGactoIk8gmcNHGlkrpEo8,12449
62
+ digitalkin/services/setup/__init__.py,sha256=t6xcvEWqTbcRZstBFK9cESEqaZKvpW14VtYygxIqfYQ,65
63
+ digitalkin/services/setup/default_setup.py,sha256=9VM3KwsuQcFQQ08RoOHWOE_-9BsRW0YGRtDWYTbQGdA,8246
64
+ digitalkin/services/setup/grpc_setup.py,sha256=jLw9tfHMFhdVYXCIGC2ffx2HUgyNpgMi9G265nvkvMg,12440
60
65
  digitalkin/services/setup/setup_strategy.py,sha256=ZnJ_HwWCkHCPrqKekSD5L9y3p8wMwfjQ8sj2hLZq6go,4004
61
66
  digitalkin/services/snapshot/__init__.py,sha256=Uzlnzo0CYlSpVsdiI37hW7xQk8hu3YA1fOI6O6MSzB0,270
62
67
  digitalkin/services/snapshot/default_snapshot.py,sha256=Mb8QwWRsHh9I_tN0ln_ZiFa1QCZxOVWmuVLemQOTWpc,1058
63
68
  digitalkin/services/snapshot/snapshot_strategy.py,sha256=B1TU3V_k9A-OdqBkdyc41-ihnrW5Btcwd1KyQdHT46A,898
64
69
  digitalkin/services/storage/__init__.py,sha256=T-ocYLLphudkQgzvG47jBOm5GQsRFRIGA88y7Ur4akg,341
65
- digitalkin/services/storage/default_storage.py,sha256=AWcayUtdSI1ns4loOqEYkIFiXKPV_0lclt6n94UgqSU,7883
66
- digitalkin/services/storage/grpc_storage.py,sha256=Or94uk9KqjhLvz9IeJcuSXrNBOLczgZ1GhftQAMmn14,7003
70
+ digitalkin/services/storage/default_storage.py,sha256=m53sLOx0JVbua4weD_4GQBKK3c0UDf9HC5BnvSJAkvg,7933
71
+ digitalkin/services/storage/grpc_storage.py,sha256=EU2gcT2bOCSqOsnLwQcu3VOeOvdBlP1g0ALfBb07JxY,7172
67
72
  digitalkin/services/storage/storage_strategy.py,sha256=vZWPk49AyJs7RwhSfUwDiTG1A7C4Ccd8y-VVPslyf0w,8734
68
73
  digitalkin/utils/__init__.py,sha256=sJnY-ZUgsjMfojAjONC1VN14mhgIDnzyOlGkw21rRnM,28
69
- digitalkin/utils/arg_parser.py,sha256=3YyI6oZhhrlTmPTrzlwpQzbCNWDFAT3pggcLxNtJoc0,4388
74
+ digitalkin/utils/arg_parser.py,sha256=nvjI1pKDY1HfS0oGcMQPtdTQcggXLtpxXMbnMxNEKRU,3109
75
+ digitalkin/utils/development_mode_action.py,sha256=TqRuAF_A7bDD4twRB4PnZcRoNeaiAnEdxM5kvy4aoaA,1511
70
76
  digitalkin/utils/llm_ready_schema.py,sha256=JjMug_lrQllqFoanaC091VgOqwAd-_YzcpqFlS7p778,2375
71
- digitalkin-0.2.12.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
77
+ digitalkin-0.2.13.dist-info/licenses/LICENSE,sha256=Ies4HFv2r2hzDRakJYxk3Y60uDFLiG-orIgeTpstnIo,20327
72
78
  modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
- modules/minimal_llm_module.py,sha256=W-E3OrRbAsRJ6hvSeTU8pzmacdJC_PbcWfDapRv5A1A,5617
74
- modules/storage_module.py,sha256=U9zxEgNORR5SuunWOZvbVivzXOgMGljY-0h791bztVw,6388
75
- modules/text_transform_module.py,sha256=1KaA7abwxltKKtbmiW1rkkIK3BTYFPegUq54px0LOQs,7277
76
- digitalkin-0.2.12.dist-info/METADATA,sha256=QYAoblLIWAUNEkl70DJzK9D0hO8EIvCLqMaMhGsu2ZU,29127
77
- digitalkin-0.2.12.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
78
- digitalkin-0.2.12.dist-info/top_level.txt,sha256=5_5e35inSM5YfWNZE21p5wGBojiVtQQML_WzbEk4BRU,31
79
- digitalkin-0.2.12.dist-info/RECORD,,
79
+ modules/cpu_intensive_module.py,sha256=LUfgd1qFJ0HfsWMapSXUivgf5KGDpANKPORbcQBUjc4,8089
80
+ modules/minimal_llm_module.py,sha256=6cygPliUb4mroOrUo5YirZfQQ1IeOT3xUHzPpDC_0Tc,10045
81
+ modules/storage_module.py,sha256=KJA75oxXDUxZrLfoY5KxeyI8Gm1b3DxFuFj7LGOkeaQ,6389
82
+ modules/text_transform_module.py,sha256=Db_WbJi7_gWyoNvQEVhHQf5VurDsU-jd9LMAalG0oZY,7277
83
+ digitalkin-0.2.13.dist-info/METADATA,sha256=CUpDclUxsamv7icPsWN-ImippAec3_EQZUGm1cQGHFQ,30577
84
+ digitalkin-0.2.13.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
85
+ digitalkin-0.2.13.dist-info/top_level.txt,sha256=5_5e35inSM5YfWNZE21p5wGBojiVtQQML_WzbEk4BRU,31
86
+ digitalkin-0.2.13.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.3.1)
2
+ Generator: setuptools (80.7.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5