koi-net 1.2.0b1__py3-none-any.whl → 1.2.0b3__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.

Potentially problematic release.


This version of koi-net might be problematic. Click here for more details.

Files changed (52) hide show
  1. koi_net/__init__.py +1 -1
  2. koi_net/assembler.py +95 -0
  3. koi_net/cli/models.py +2 -2
  4. koi_net/config/core.py +71 -0
  5. koi_net/config/full_node.py +31 -0
  6. koi_net/config/loader.py +46 -0
  7. koi_net/config/partial_node.py +18 -0
  8. koi_net/core.py +43 -206
  9. koi_net/default_actions.py +1 -2
  10. koi_net/effector.py +27 -15
  11. koi_net/entrypoints/__init__.py +2 -0
  12. koi_net/entrypoints/base.py +5 -0
  13. koi_net/{poller.py → entrypoints/poller.py} +14 -12
  14. koi_net/entrypoints/server.py +94 -0
  15. koi_net/handshaker.py +5 -5
  16. koi_net/identity.py +3 -4
  17. koi_net/lifecycle.py +42 -34
  18. koi_net/logger.py +176 -0
  19. koi_net/network/error_handler.py +7 -7
  20. koi_net/network/event_queue.py +9 -7
  21. koi_net/network/graph.py +8 -8
  22. koi_net/network/poll_event_buffer.py +26 -0
  23. koi_net/network/request_handler.py +23 -28
  24. koi_net/network/resolver.py +14 -14
  25. koi_net/network/response_handler.py +74 -9
  26. koi_net/{context.py → processor/context.py} +11 -19
  27. koi_net/processor/handler.py +4 -1
  28. koi_net/processor/{default_handlers.py → knowledge_handlers.py} +32 -31
  29. koi_net/processor/knowledge_object.py +2 -3
  30. koi_net/processor/kobj_queue.py +4 -4
  31. koi_net/processor/{knowledge_pipeline.py → pipeline.py} +25 -28
  32. koi_net/protocol/api_models.py +5 -2
  33. koi_net/protocol/envelope.py +5 -6
  34. koi_net/protocol/model_map.py +61 -0
  35. koi_net/protocol/node.py +3 -3
  36. koi_net/protocol/secure.py +14 -8
  37. koi_net/secure.py +6 -7
  38. koi_net/workers/__init__.py +2 -0
  39. koi_net/{worker.py → workers/base.py} +7 -0
  40. koi_net/{processor → workers}/event_worker.py +19 -23
  41. koi_net/{kobj_worker.py → workers/kobj_worker.py} +12 -13
  42. {koi_net-1.2.0b1.dist-info → koi_net-1.2.0b3.dist-info}/METADATA +2 -1
  43. koi_net-1.2.0b3.dist-info/RECORD +56 -0
  44. koi_net/behaviors.py +0 -51
  45. koi_net/config.py +0 -161
  46. koi_net/models.py +0 -14
  47. koi_net/poll_event_buffer.py +0 -17
  48. koi_net/server.py +0 -145
  49. koi_net-1.2.0b1.dist-info/RECORD +0 -49
  50. {koi_net-1.2.0b1.dist-info → koi_net-1.2.0b3.dist-info}/WHEEL +0 -0
  51. {koi_net-1.2.0b1.dist-info → koi_net-1.2.0b3.dist-info}/entry_points.txt +0 -0
  52. {koi_net-1.2.0b1.dist-info → koi_net-1.2.0b3.dist-info}/licenses/LICENSE +0 -0
koi_net/__init__.py CHANGED
@@ -1 +1 @@
1
- from .core import NodeContainer
1
+ from . import logger
koi_net/assembler.py ADDED
@@ -0,0 +1,95 @@
1
+ import inspect
2
+ from typing import Protocol
3
+ from dataclasses import make_dataclass
4
+
5
+ from pydantic import BaseModel
6
+ import structlog
7
+
8
+ from .entrypoints.base import EntryPoint
9
+
10
+ log = structlog.stdlib.get_logger()
11
+
12
+
13
+ class BuildOrderer(type):
14
+ def __new__(cls, name: str, bases: tuple, dct: dict[str]):
15
+ """Sets `cls._build_order` from component order in class definition."""
16
+ cls = super().__new__(cls, name, bases, dct)
17
+
18
+ if "_build_order" not in dct:
19
+ components = {}
20
+ # adds components from base classes (including cls)
21
+ for base in reversed(inspect.getmro(cls)[:-1]):
22
+ for k, v in vars(base).items():
23
+ # excludes built in and private attributes
24
+ if not k.startswith("_"):
25
+ components[k] = v
26
+
27
+ # recipe list constructed from names of non-None components
28
+ cls._build_order = [
29
+ name for name, _type in components.items()
30
+ if _type is not None
31
+ ]
32
+
33
+ return cls
34
+
35
+ class NodeContainer(Protocol):
36
+ entrypoint = EntryPoint
37
+
38
+ class NodeAssembler(metaclass=BuildOrderer):
39
+ def __new__(self) -> NodeContainer:
40
+ return self._build()
41
+
42
+ @classmethod
43
+ def _build(cls) -> NodeContainer:
44
+ components = {}
45
+ for comp_name in cls._build_order:
46
+ comp = getattr(cls, comp_name, None)
47
+
48
+ if comp is None:
49
+ raise Exception(f"Couldn't find factory for component '{comp_name}'")
50
+
51
+ print(comp_name)
52
+
53
+ if not callable(comp):
54
+ print(f"Treating {comp_name} as a literal")
55
+ components[comp_name] = comp
56
+ continue
57
+
58
+ if issubclass(comp, BaseModel):
59
+ print(f"Treating {comp_name} as a pydantic model")
60
+ components[comp_name] = comp
61
+ continue
62
+
63
+ sig = inspect.signature(comp)
64
+
65
+ required_comps = []
66
+ for name, param in sig.parameters.items():
67
+ required_comps.append((name, param.annotation))
68
+
69
+ if len(required_comps) == 0:
70
+ s = comp_name
71
+ else:
72
+ s = f"{comp_name} -> {', '.join([name for name, _type in required_comps])}"
73
+
74
+ # print(s.replace("graph", "_graph"), end=";\n")
75
+
76
+ dependencies = {}
77
+ for req_comp_name, req_comp_type in required_comps:
78
+ if req_comp_name not in components:
79
+ raise Exception(f"Couldn't find required component '{req_comp_name}'")
80
+
81
+ dependencies[req_comp_name] = components[req_comp_name]
82
+
83
+ components[comp_name] = comp(**dependencies)
84
+
85
+ NodeContainer = make_dataclass(
86
+ cls_name="NodeContainer",
87
+ fields=[
88
+ (name, type(component))
89
+ for name, component
90
+ in components.items()
91
+ ],
92
+ frozen=True
93
+ )
94
+
95
+ return NodeContainer(**components)
koi_net/cli/models.py CHANGED
@@ -1,9 +1,9 @@
1
- from pydantic import BaseModel, Field, PrivateAttr
1
+ from pydantic import BaseModel, PrivateAttr
2
2
  from ruamel.yaml import YAML
3
3
 
4
4
 
5
5
  class KoiNetworkConfig(BaseModel):
6
- nodes: dict[str, str] = Field(default_factory=dict)
6
+ nodes: dict[str, str] = {}
7
7
  _file_path: str = PrivateAttr(default="koi-net-config.yaml")
8
8
 
9
9
  @classmethod
koi_net/config/core.py ADDED
@@ -0,0 +1,71 @@
1
+ import os
2
+ from pydantic import BaseModel, model_validator
3
+ from dotenv import load_dotenv
4
+ from rid_lib import RIDType
5
+ from rid_lib.types import KoiNetNode
6
+
7
+ from koi_net.protocol.secure import PrivateKey
8
+ from ..protocol.node import NodeProfile
9
+
10
+
11
+ class NodeContact(BaseModel):
12
+ rid: KoiNetNode | None = None
13
+ url: str | None = None
14
+
15
+ class KoiNetConfig(BaseModel):
16
+ """Config for KOI-net."""
17
+
18
+ node_name: str
19
+ node_rid: KoiNetNode | None = None
20
+ node_profile: NodeProfile
21
+
22
+ rid_types_of_interest: list[RIDType] = [KoiNetNode]
23
+
24
+ cache_directory_path: str = ".rid_cache"
25
+ event_queues_path: str = "event_queues.json"
26
+ private_key_pem_path: str = "priv_key.pem"
27
+
28
+ first_contact: NodeContact = NodeContact()
29
+
30
+ class EnvConfig(BaseModel):
31
+ """Config for environment variables.
32
+
33
+ Values set in the config are the variables names, and are loaded
34
+ from the environment at runtime. For example, if the config YAML
35
+ sets `priv_key_password: PRIV_KEY_PASSWORD` accessing
36
+ `priv_key_password` would retrieve the value of `PRIV_KEY_PASSWORD`
37
+ from the environment.
38
+ """
39
+
40
+ priv_key_password: str = "PRIV_KEY_PASSWORD"
41
+
42
+ def __init__(self, **kwargs):
43
+ super().__init__(**kwargs)
44
+ load_dotenv()
45
+
46
+ def __getattribute__(self, name):
47
+ value = super().__getattribute__(name)
48
+ if name in type(self).model_fields:
49
+ env_val = os.getenv(value)
50
+ if env_val is None:
51
+ raise ValueError(f"Required environment variable {value} not set")
52
+ return env_val
53
+ return value
54
+
55
+ class NodeConfig(BaseModel):
56
+ koi_net: KoiNetConfig
57
+ env: EnvConfig = EnvConfig()
58
+
59
+ @model_validator(mode="after")
60
+ def generate_rid_cascade(self):
61
+ if not self.koi_net.node_rid:
62
+ priv_key = PrivateKey.generate()
63
+ pub_key = priv_key.public_key()
64
+
65
+ self.koi_net.node_rid = pub_key.to_node_rid(self.koi_net.node_name)
66
+
67
+ with open(self.koi_net.private_key_pem_path, "w") as f:
68
+ f.write(priv_key.to_pem(self.env.priv_key_password))
69
+
70
+ self.koi_net.node_profile.public_key = pub_key.to_der()
71
+ return self
@@ -0,0 +1,31 @@
1
+ from pydantic import BaseModel, model_validator
2
+ from koi_net.config.core import NodeConfig, KoiNetConfig as BaseKoiNetConfig
3
+ from ..protocol.node import NodeProfile as BaseNodeProfile, NodeType, NodeProvides
4
+
5
+
6
+ class NodeProfile(BaseNodeProfile):
7
+ node_type: NodeType = NodeType.FULL
8
+
9
+ class KoiNetConfig(BaseKoiNetConfig):
10
+ node_profile: NodeProfile
11
+
12
+ class ServerConfig(BaseModel):
13
+ """Config for the node server (full node only)."""
14
+
15
+ host: str = "127.0.0.1"
16
+ port: int = 8000
17
+ path: str | None = "/koi-net"
18
+
19
+ @property
20
+ def url(self) -> str:
21
+ return f"http://{self.host}:{self.port}{self.path or ''}"
22
+
23
+ class FullNodeConfig(NodeConfig):
24
+ koi_net: KoiNetConfig
25
+ server: ServerConfig = ServerConfig()
26
+
27
+ @model_validator(mode="after")
28
+ def check_url(self):
29
+ if not self.koi_net.node_profile.base_url:
30
+ self.koi_net.node_profile.base_url = self.server.url
31
+ return self
@@ -0,0 +1,46 @@
1
+ from ruamel.yaml import YAML
2
+ from .core import NodeConfig
3
+
4
+
5
+ class ConfigLoader:
6
+ _config: NodeConfig
7
+
8
+ _file_path: str = "config.yaml"
9
+ _file_content: str
10
+
11
+ def __init__(self, config_cls: type[NodeConfig]):
12
+ self._config_cls = config_cls
13
+ self.load_from_yaml()
14
+
15
+ def __getattr__(self, name):
16
+ return getattr(self._config, name)
17
+
18
+ def load_from_yaml(self):
19
+ """Loads config state from YAML file."""
20
+ yaml = YAML()
21
+
22
+ try:
23
+ with open(self._file_path, "r") as f:
24
+ self._file_content = f.read()
25
+ config_data = yaml.load(self._file_content)
26
+ self._config = self._config_cls.model_validate(config_data)
27
+
28
+ except FileNotFoundError:
29
+ self._config = self._config_cls()
30
+
31
+ self.save_to_yaml()
32
+
33
+
34
+ def save_to_yaml(self):
35
+ yaml = YAML()
36
+
37
+ with open(self._file_path, "w") as f:
38
+ try:
39
+ config_data = self._config.model_dump(mode="json")
40
+ yaml.dump(config_data, f)
41
+ except Exception as e:
42
+ if self._file_content:
43
+ f.seek(0)
44
+ f.truncate()
45
+ f.write(self._file_content)
46
+ raise e
@@ -0,0 +1,18 @@
1
+ from pydantic import BaseModel
2
+ from koi_net.config.core import NodeConfig, KoiNetConfig
3
+ from ..protocol.node import NodeProfile, NodeType, NodeProvides
4
+
5
+
6
+ class NodeProfile(NodeProfile):
7
+ base_url: str | None = None
8
+ node_type: NodeType = NodeType.PARTIAL
9
+
10
+ class KoiNetConfig(KoiNetConfig):
11
+ node_profile: NodeProfile
12
+
13
+ class PollerConfig(BaseModel):
14
+ polling_interval: int = 5
15
+
16
+ class PartialNodeConfig(NodeConfig):
17
+ koi_net: KoiNetConfig
18
+ poller: PollerConfig = PollerConfig()
koi_net/core.py CHANGED
@@ -1,22 +1,26 @@
1
- from dataclasses import dataclass
2
1
  from rid_lib.ext import Cache
3
- from koi_net.behaviors import Behaviors
4
- from koi_net.config import NodeConfig
5
- from koi_net.context import ActionContext, HandlerContext
6
- from koi_net.effector import Effector
7
- from koi_net.handshaker import Handshaker
8
- from koi_net.identity import NodeIdentity
9
- from koi_net.kobj_worker import KnowledgeProcessingWorker
10
- from koi_net.lifecycle import NodeLifecycle
11
- from koi_net.network.error_handler import ErrorHandler
12
- from koi_net.network.event_queue import EventQueue
13
- from koi_net.network.graph import NetworkGraph
14
- from koi_net.network.request_handler import RequestHandler
15
- from koi_net.network.resolver import NetworkResolver
16
- from koi_net.network.response_handler import ResponseHandler
17
- from koi_net.poll_event_buffer import PollEventBuffer
18
- from koi_net.poller import NodePoller
19
- from koi_net.processor.default_handlers import (
2
+
3
+ from .config.loader import ConfigLoader
4
+ from .assembler import NodeAssembler
5
+ from .config.core import NodeConfig
6
+ from .processor.context import HandlerContext
7
+ from .effector import Effector
8
+ from .handshaker import Handshaker
9
+ from .identity import NodeIdentity
10
+ from .workers import KnowledgeProcessingWorker, EventProcessingWorker
11
+ from .lifecycle import NodeLifecycle
12
+ from .network.error_handler import ErrorHandler
13
+ from .network.event_queue import EventQueue
14
+ from .network.graph import NetworkGraph
15
+ from .network.request_handler import RequestHandler
16
+ from .network.resolver import NetworkResolver
17
+ from .network.response_handler import ResponseHandler
18
+ from .network.poll_event_buffer import PollEventBuffer
19
+ from .processor.pipeline import KnowledgePipeline
20
+ from .processor.kobj_queue import KobjQueue
21
+ from .secure import Secure
22
+ from .entrypoints import NodeServer, NodePoller
23
+ from .processor.knowledge_handlers import (
20
24
  basic_manifest_handler,
21
25
  basic_network_output_filter,
22
26
  basic_rid_handler,
@@ -25,50 +29,14 @@ from koi_net.processor.default_handlers import (
25
29
  forget_edge_on_node_deletion,
26
30
  secure_profile_handler
27
31
  )
28
- from koi_net.processor.event_worker import EventProcessingWorker
29
- from koi_net.processor.knowledge_pipeline import KnowledgePipeline
30
- from koi_net.processor.kobj_queue import KobjQueue
31
- from koi_net.secure import Secure
32
- from koi_net.server import NodeServer
33
-
34
32
 
35
- @dataclass
36
- class NodeContainer:
37
- poll_event_buf: PollEventBuffer
38
- kobj_queue: KobjQueue
39
- event_queue: EventQueue
40
- config: NodeConfig
41
- cache: Cache
42
- identity: NodeIdentity
43
- graph: NetworkGraph
44
- secure: Secure
45
- request_handler: RequestHandler
46
- response_handler: ResponseHandler
47
- resolver: NetworkResolver
48
- handler_context: HandlerContext
49
- behaviors: Behaviors
50
- pipeline: KnowledgePipeline
51
- kobj_worker: KnowledgeProcessingWorker
52
- event_worker: EventProcessingWorker
53
- error_handler: ErrorHandler
54
- lifecycle: NodeLifecycle
55
- server: NodeServer
56
- poller: NodePoller
57
-
58
33
 
59
- class NodeAssembler:
60
- poll_event_buf = PollEventBuffer
34
+ class BaseNode(NodeAssembler):
35
+ config_cls = NodeConfig
61
36
  kobj_queue = KobjQueue
62
37
  event_queue = EventQueue
63
- config = NodeConfig
64
- cache = Cache
65
- identity = NodeIdentity
66
- graph = NetworkGraph
67
- secure = Secure
68
- handshaker = Handshaker
69
- request_handler = RequestHandler
70
- response_handler = ResponseHandler
71
- resolver = NetworkResolver
38
+ poll_event_buf = PollEventBuffer
39
+ config = ConfigLoader
72
40
  knowledge_handlers = [
73
41
  basic_rid_handler,
74
42
  basic_manifest_handler,
@@ -78,156 +46,25 @@ class NodeAssembler:
78
46
  basic_network_output_filter,
79
47
  forget_edge_on_node_deletion
80
48
  ]
81
- handler_context = HandlerContext
82
- action_context = ActionContext
49
+ cache = lambda config: Cache(
50
+ directory_path=config.koi_net.cache_directory_path)
51
+ identity = NodeIdentity
52
+ graph = NetworkGraph
53
+ secure = Secure
54
+ handshaker = Handshaker
55
+ error_handler = ErrorHandler
56
+ request_handler = RequestHandler
57
+ response_handler = ResponseHandler
58
+ resolver = NetworkResolver
83
59
  effector = Effector
84
- behaviors = Behaviors
60
+ handler_context = HandlerContext
85
61
  pipeline = KnowledgePipeline
86
62
  kobj_worker = KnowledgeProcessingWorker
87
63
  event_worker = EventProcessingWorker
88
- error_handler = ErrorHandler
89
64
  lifecycle = NodeLifecycle
90
- server = NodeServer
91
- poller = NodePoller
92
-
93
- @classmethod
94
- def create(cls) -> NodeContainer:
95
- poll_event_buffer = cls.poll_event_buf()
96
- kobj_queue = cls.kobj_queue()
97
- event_queue = cls.event_queue()
98
- config = cls.config.load_from_yaml()
99
- cache = cls.cache(
100
- directory_path=config.koi_net.cache_directory_path
101
- )
102
- identity = cls.identity(
103
- config=config
104
- )
105
- graph = cls.graph(
106
- cache=cache,
107
- identity=identity
108
- )
109
- secure = cls.secure(
110
- identity=identity,
111
- cache=cache,
112
- config=config
113
- )
114
- handshaker = cls.handshaker(
115
- cache=cache,
116
- identity=identity,
117
- event_queue=event_queue
118
- )
119
- error_handler = cls.error_handler(
120
- kobj_queue=kobj_queue,
121
- handshaker=handshaker
122
- )
123
- request_handler = cls.request_handler(
124
- cache=cache,
125
- identity=identity,
126
- secure=secure,
127
- error_handler=error_handler
128
- )
129
- response_handler = cls.response_handler(
130
- cache=cache
131
- )
132
- resolver = cls.resolver(
133
- config=config,
134
- cache=cache,
135
- identity=identity,
136
- graph=graph,
137
- request_handler=request_handler
138
- )
139
- handler_context = cls.handler_context(
140
- identity=identity,
141
- config=config,
142
- cache=cache,
143
- event_queue=event_queue,
144
- kobj_queue=kobj_queue,
145
- graph=graph,
146
- request_handler=request_handler,
147
- resolver=resolver
148
- )
149
- action_context = cls.action_context(
150
- identity=identity
151
- )
152
- effector = cls.effector(
153
- cache=cache,
154
- resolver=resolver,
155
- kobj_queue=kobj_queue,
156
- action_context=action_context
157
- )
158
- behaviors = cls.behaviors(
159
- cache=cache,
160
- identity=identity,
161
- event_queue=event_queue,
162
- resolver=resolver,
163
- request_handler=request_handler,
164
- kobj_queue=kobj_queue
165
- )
166
- pipeline = cls.pipeline(
167
- handler_context=handler_context,
168
- cache=cache,
169
- request_handler=request_handler,
170
- event_queue=event_queue,
171
- graph=graph,
172
- knowledge_handlers=cls.knowledge_handlers
173
- )
174
- kobj_worker = cls.kobj_worker(
175
- kobj_queue=kobj_queue,
176
- pipeline=pipeline
177
- )
178
- event_worker = cls.event_worker(
179
- config=config,
180
- cache=cache,
181
- event_queue=event_queue,
182
- request_handler=request_handler,
183
- poll_event_buf=poll_event_buffer
184
- )
185
- lifecycle = cls.lifecycle(
186
- config=config,
187
- identity=identity,
188
- graph=graph,
189
- kobj_queue=kobj_queue,
190
- kobj_worker=kobj_worker,
191
- event_queue=event_queue,
192
- event_worker=event_worker,
193
- cache=cache,
194
- handshaker=handshaker,
195
- behaviors=behaviors
196
- )
197
- server = cls.server(
198
- config=config,
199
- lifecycle=lifecycle,
200
- secure=secure,
201
- kobj_queue=kobj_queue,
202
- response_handler=response_handler,
203
- poll_event_buf=poll_event_buffer
204
- )
205
- poller = cls.poller(
206
- kobj_queue=kobj_queue,
207
- lifecycle=lifecycle,
208
- resolver=resolver,
209
- config=config
210
- )
211
-
212
- return NodeContainer(
213
- poll_event_buf=poll_event_buffer,
214
- kobj_queue=kobj_queue,
215
- event_queue=event_queue,
216
- config=config,
217
- cache=cache,
218
- identity=identity,
219
- graph=graph,
220
- secure=secure,
221
- request_handler=request_handler,
222
- response_handler=response_handler,
223
- resolver=resolver,
224
- handler_context=handler_context,
225
- behaviors=behaviors,
226
- pipeline=pipeline,
227
- kobj_worker=kobj_worker,
228
- event_worker=event_worker,
229
- error_handler=error_handler,
230
- lifecycle=lifecycle,
231
- server=server,
232
- poller=poller
233
- )
65
+
66
+ class FullNode(BaseNode):
67
+ entrypoint = NodeServer
68
+
69
+ class PartialNode(BaseNode):
70
+ entrypoint = NodePoller
@@ -1,9 +1,8 @@
1
1
  """Implementations of default dereference actions."""
2
2
 
3
- from .context import ActionContext
4
3
  from rid_lib.types import KoiNetNode
5
4
  from rid_lib.ext import Bundle
6
- from .effector import Effector
5
+ from .effector import Effector, ActionContext
7
6
 
8
7
 
9
8
  @Effector.register_default_action(KoiNetNode)
koi_net/effector.py CHANGED
@@ -1,4 +1,4 @@
1
- import logging
1
+ import structlog
2
2
  from typing import Callable
3
3
  from enum import StrEnum
4
4
  from rid_lib.ext import Cache, Bundle
@@ -6,11 +6,23 @@ from rid_lib.core import RID, RIDType
6
6
  from rid_lib.types import KoiNetNode
7
7
  from .network.resolver import NetworkResolver
8
8
  from .processor.kobj_queue import KobjQueue
9
- from .context import ActionContext
9
+ from .identity import NodeIdentity
10
10
 
11
- logger = logging.getLogger(__name__)
11
+ log = structlog.stdlib.get_logger()
12
12
 
13
13
 
14
+ class ActionContext:
15
+ """Provides action handlers access to other subsystems."""
16
+
17
+ identity: NodeIdentity
18
+
19
+ def __init__(
20
+ self,
21
+ identity: NodeIdentity,
22
+ ):
23
+ self.identity = identity
24
+
25
+
14
26
  class BundleSource(StrEnum):
15
27
  CACHE = "CACHE"
16
28
  ACTION = "ACTION"
@@ -35,12 +47,12 @@ class Effector:
35
47
  cache: Cache,
36
48
  resolver: NetworkResolver,
37
49
  kobj_queue: KobjQueue,
38
- action_context: ActionContext
50
+ identity: NodeIdentity
39
51
  ):
40
52
  self.cache = cache
41
53
  self.resolver = resolver
42
54
  self.kobj_queue = kobj_queue
43
- self.action_context = action_context
55
+ self.action_context = ActionContext(identity)
44
56
  self._action_table = self.__class__._action_table.copy()
45
57
 
46
58
  @classmethod
@@ -70,18 +82,18 @@ class Effector:
70
82
  bundle = self.cache.read(rid)
71
83
 
72
84
  if bundle:
73
- logger.debug("Cache hit")
85
+ log.debug("Cache hit")
74
86
  return bundle, BundleSource.CACHE
75
87
  else:
76
- logger.debug("Cache miss")
88
+ log.debug("Cache miss")
77
89
  return None
78
90
 
79
91
  def _try_action(self, rid: RID) -> tuple[Bundle, BundleSource] | None:
80
92
  if type(rid) not in self._action_table:
81
- logger.debug("No action available")
93
+ log.debug("No action available")
82
94
  return None
83
95
 
84
- logger.debug("Action available")
96
+ log.debug("Action available")
85
97
  func = self._action_table[type(rid)]
86
98
  bundle = func(
87
99
  ctx=self.action_context,
@@ -89,10 +101,10 @@ class Effector:
89
101
  )
90
102
 
91
103
  if bundle:
92
- logger.debug("Action hit")
104
+ log.debug("Action hit")
93
105
  return bundle, BundleSource.ACTION
94
106
  else:
95
- logger.debug("Action miss")
107
+ log.debug("Action miss")
96
108
  return None
97
109
 
98
110
 
@@ -100,10 +112,10 @@ class Effector:
100
112
  bundle, source = self.resolver.fetch_remote_bundle(rid)
101
113
 
102
114
  if bundle:
103
- logger.debug("Network hit")
115
+ log.debug("Network hit")
104
116
  return bundle, source
105
117
  else:
106
- logger.debug("Network miss")
118
+ log.debug("Network miss")
107
119
  return None
108
120
 
109
121
 
@@ -127,7 +139,7 @@ class Effector:
127
139
  handle_result: handles resulting bundle with knowledge pipeline when `True`
128
140
  """
129
141
 
130
- logger.debug(f"Dereferencing {rid!r}")
142
+ log.debug(f"Dereferencing {rid!r}")
131
143
 
132
144
  bundle, source = (
133
145
  # if `refresh_cache`, skip try cache
@@ -143,7 +155,7 @@ class Effector:
143
155
  and bundle is not None
144
156
  and source != BundleSource.CACHE
145
157
  ):
146
- self.kobj_queue.put_kobj(
158
+ self.kobj_queue.push(
147
159
  bundle=bundle,
148
160
  source=source if type(source) is KoiNetNode else None
149
161
  )
@@ -0,0 +1,2 @@
1
+ from .poller import NodePoller
2
+ from .server import NodeServer
@@ -0,0 +1,5 @@
1
+ from koi_net.config.core import NodeConfig
2
+
3
+
4
+ class EntryPoint:
5
+ def run(self): ...