koi-net 1.1.0b8__py3-none-any.whl → 1.2.0b2__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.
- koi_net/__init__.py +2 -1
- koi_net/assembler.py +82 -0
- koi_net/cli/__init__.py +1 -0
- koi_net/cli/commands.py +99 -0
- koi_net/cli/models.py +41 -0
- koi_net/config.py +34 -0
- koi_net/context.py +11 -28
- koi_net/core.py +63 -179
- koi_net/default_actions.py +10 -1
- koi_net/effector.py +61 -34
- koi_net/handshaker.py +39 -0
- koi_net/identity.py +2 -3
- koi_net/interfaces/entrypoint.py +5 -0
- koi_net/interfaces/worker.py +17 -0
- koi_net/lifecycle.py +85 -48
- koi_net/logger.py +176 -0
- koi_net/network/error_handler.py +18 -16
- koi_net/network/event_queue.py +17 -185
- koi_net/network/graph.py +15 -10
- koi_net/network/poll_event_buffer.py +26 -0
- koi_net/network/request_handler.py +54 -47
- koi_net/network/resolver.py +18 -21
- koi_net/network/response_handler.py +79 -15
- koi_net/poller.py +18 -9
- koi_net/processor/event_worker.py +117 -0
- koi_net/processor/handler.py +4 -2
- koi_net/processor/{default_handlers.py → handlers.py} +109 -59
- koi_net/processor/knowledge_object.py +19 -7
- koi_net/processor/kobj_queue.py +51 -0
- koi_net/processor/kobj_worker.py +44 -0
- koi_net/processor/{knowledge_pipeline.py → pipeline.py} +31 -53
- koi_net/protocol/api_models.py +7 -3
- koi_net/protocol/envelope.py +5 -6
- koi_net/protocol/model_map.py +61 -0
- koi_net/protocol/node.py +3 -3
- koi_net/protocol/secure.py +8 -8
- koi_net/secure.py +33 -13
- koi_net/sentry.py +13 -0
- koi_net/server.py +44 -78
- koi_net/utils.py +18 -0
- {koi_net-1.1.0b8.dist-info → koi_net-1.2.0b2.dist-info}/METADATA +8 -3
- koi_net-1.2.0b2.dist-info/RECORD +52 -0
- koi_net-1.2.0b2.dist-info/entry_points.txt +2 -0
- koi_net/actor.py +0 -60
- koi_net/processor/interface.py +0 -101
- koi_net-1.1.0b8.dist-info/RECORD +0 -38
- {koi_net-1.1.0b8.dist-info → koi_net-1.2.0b2.dist-info}/WHEEL +0 -0
- {koi_net-1.1.0b8.dist-info → koi_net-1.2.0b2.dist-info}/licenses/LICENSE +0 -0
koi_net/__init__.py
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
from .
|
|
1
|
+
from . import logger
|
|
2
|
+
from . import sentry
|
koi_net/assembler.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
from typing import Protocol
|
|
3
|
+
from dataclasses import make_dataclass
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
|
|
7
|
+
from .interfaces.entrypoint import EntryPoint
|
|
8
|
+
|
|
9
|
+
log = structlog.stdlib.get_logger()
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BuildOrderer(type):
|
|
13
|
+
def __new__(cls, name: str, bases: tuple, dct: dict[str]):
|
|
14
|
+
"""Sets `cls._build_order` from component order in class definition."""
|
|
15
|
+
cls = super().__new__(cls, name, bases, dct)
|
|
16
|
+
|
|
17
|
+
if "_build_order" not in dct:
|
|
18
|
+
components = {}
|
|
19
|
+
# adds components from base classes (including cls)
|
|
20
|
+
for base in reversed(inspect.getmro(cls)[:-1]):
|
|
21
|
+
for k, v in vars(base).items():
|
|
22
|
+
# excludes built in and private attributes
|
|
23
|
+
if not k.startswith("_"):
|
|
24
|
+
components[k] = v
|
|
25
|
+
|
|
26
|
+
# recipe list constructed from names of non-None components
|
|
27
|
+
cls._build_order = [
|
|
28
|
+
name for name, _type in components.items()
|
|
29
|
+
if _type is not None
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
return cls
|
|
33
|
+
|
|
34
|
+
class NodeContainer(Protocol):
|
|
35
|
+
entrypoint = EntryPoint
|
|
36
|
+
|
|
37
|
+
class NodeAssembler(metaclass=BuildOrderer):
|
|
38
|
+
def __new__(self) -> NodeContainer:
|
|
39
|
+
return self._build()
|
|
40
|
+
|
|
41
|
+
@classmethod
|
|
42
|
+
def _build(cls) -> NodeContainer:
|
|
43
|
+
components = {}
|
|
44
|
+
for comp_name in cls._build_order:
|
|
45
|
+
comp_factory = getattr(cls, comp_name, None)
|
|
46
|
+
|
|
47
|
+
if comp_factory is None:
|
|
48
|
+
raise Exception(f"Couldn't find factory for component '{comp_name}'")
|
|
49
|
+
|
|
50
|
+
sig = inspect.signature(comp_factory)
|
|
51
|
+
|
|
52
|
+
required_comps = []
|
|
53
|
+
for name, param in sig.parameters.items():
|
|
54
|
+
required_comps.append((name, param.annotation))
|
|
55
|
+
|
|
56
|
+
if len(required_comps) == 0:
|
|
57
|
+
s = comp_name
|
|
58
|
+
else:
|
|
59
|
+
s = f"{comp_name} -> {', '.join([name for name, _type in required_comps])}"
|
|
60
|
+
|
|
61
|
+
print(s.replace("graph", "_graph"), end=";\n")
|
|
62
|
+
|
|
63
|
+
dependencies = {}
|
|
64
|
+
for req_comp_name, req_comp_type in required_comps:
|
|
65
|
+
if req_comp_name not in components:
|
|
66
|
+
raise Exception(f"Couldn't find required component '{req_comp_name}'")
|
|
67
|
+
|
|
68
|
+
dependencies[req_comp_name] = components[req_comp_name]
|
|
69
|
+
|
|
70
|
+
components[comp_name] = comp_factory(**dependencies)
|
|
71
|
+
|
|
72
|
+
NodeContainer = make_dataclass(
|
|
73
|
+
cls_name="NodeContainer",
|
|
74
|
+
fields=[
|
|
75
|
+
(name, type(component))
|
|
76
|
+
for name, component
|
|
77
|
+
in components.items()
|
|
78
|
+
],
|
|
79
|
+
frozen=True
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
return NodeContainer(**components)
|
koi_net/cli/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .commands import app
|
koi_net/cli/commands.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import typer
|
|
3
|
+
from typing import Callable
|
|
4
|
+
from rich.console import Console
|
|
5
|
+
from rich.table import Table
|
|
6
|
+
|
|
7
|
+
from importlib.metadata import entry_points
|
|
8
|
+
|
|
9
|
+
from koi_net.cli.models import KoiNetworkConfig
|
|
10
|
+
from koi_net.core import NodeInterface
|
|
11
|
+
import shutil
|
|
12
|
+
|
|
13
|
+
app = typer.Typer()
|
|
14
|
+
console = Console()
|
|
15
|
+
|
|
16
|
+
installed_nodes = entry_points(group='koi_net.node')
|
|
17
|
+
|
|
18
|
+
net_config = KoiNetworkConfig.load_from_yaml()
|
|
19
|
+
|
|
20
|
+
@app.command()
|
|
21
|
+
def list_node_types():
|
|
22
|
+
table = Table(title="installed node types")
|
|
23
|
+
table.add_column("name", style="cyan")
|
|
24
|
+
table.add_column("module", style="magenta")
|
|
25
|
+
|
|
26
|
+
for node in installed_nodes:
|
|
27
|
+
table.add_row(node.name, node.module)
|
|
28
|
+
console.print(table)
|
|
29
|
+
|
|
30
|
+
@app.command()
|
|
31
|
+
def list_nodes():
|
|
32
|
+
table = Table(title="created nodes")
|
|
33
|
+
table.add_column("name", style="cyan")
|
|
34
|
+
table.add_column("rid", style="magenta")
|
|
35
|
+
|
|
36
|
+
for dir in os.listdir('.'):
|
|
37
|
+
if not os.path.isdir(dir):
|
|
38
|
+
continue
|
|
39
|
+
for file in os.listdir(dir):
|
|
40
|
+
file_path = os.path.join(dir, file)
|
|
41
|
+
if not (os.path.isfile(file_path) and file == "config.yaml"):
|
|
42
|
+
continue
|
|
43
|
+
|
|
44
|
+
print(os.getcwd())
|
|
45
|
+
os.chdir(dir)
|
|
46
|
+
print(os.getcwd())
|
|
47
|
+
|
|
48
|
+
node_type = net_config.nodes.get(dir)
|
|
49
|
+
|
|
50
|
+
ep = list(installed_nodes.select(name=node_type))[0]
|
|
51
|
+
create_node: Callable[[], NodeInterface] = ep.load()
|
|
52
|
+
|
|
53
|
+
node = create_node()
|
|
54
|
+
|
|
55
|
+
print(ep)
|
|
56
|
+
print(dir)
|
|
57
|
+
print(node.identity.rid)
|
|
58
|
+
|
|
59
|
+
table.add_row(dir, str(node.identity.rid))
|
|
60
|
+
|
|
61
|
+
os.chdir('..')
|
|
62
|
+
print(os.getcwd())
|
|
63
|
+
|
|
64
|
+
console.print(table)
|
|
65
|
+
|
|
66
|
+
@app.command()
|
|
67
|
+
def create(type: str, name: str):
|
|
68
|
+
# if name not in installed_nodes:
|
|
69
|
+
# console.print(f"[bold red]Error:[/bold red] node type '{name}' doesn't exist")
|
|
70
|
+
# raise typer.Exit(code=1)
|
|
71
|
+
|
|
72
|
+
eps = installed_nodes.select(name=type)
|
|
73
|
+
if eps:
|
|
74
|
+
ep = list(eps)[0]
|
|
75
|
+
|
|
76
|
+
os.mkdir(name)
|
|
77
|
+
os.chdir(name)
|
|
78
|
+
|
|
79
|
+
ep.load()
|
|
80
|
+
|
|
81
|
+
os.chdir('..')
|
|
82
|
+
|
|
83
|
+
net_config.nodes[name] = type
|
|
84
|
+
net_config.save_to_yaml()
|
|
85
|
+
|
|
86
|
+
@app.command()
|
|
87
|
+
def remove(name: str):
|
|
88
|
+
shutil.rmtree(name)
|
|
89
|
+
net_config.nodes.pop(name, None)
|
|
90
|
+
net_config.save_to_yaml()
|
|
91
|
+
|
|
92
|
+
@app.command()
|
|
93
|
+
def start(name: str):
|
|
94
|
+
os.chdir(name)
|
|
95
|
+
node_type = net_config.nodes.get(name)
|
|
96
|
+
ep = list(installed_nodes.select(name=node_type))[0]
|
|
97
|
+
create_node: Callable[[], NodeInterface] = ep.load()
|
|
98
|
+
|
|
99
|
+
create_node().server.run()
|
koi_net/cli/models.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from pydantic import BaseModel, Field, PrivateAttr
|
|
2
|
+
from ruamel.yaml import YAML
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class KoiNetworkConfig(BaseModel):
|
|
6
|
+
nodes: dict[str, str] = Field(default_factory=dict)
|
|
7
|
+
_file_path: str = PrivateAttr(default="koi-net-config.yaml")
|
|
8
|
+
|
|
9
|
+
@classmethod
|
|
10
|
+
def load_from_yaml(
|
|
11
|
+
cls,
|
|
12
|
+
file_path: str = "koi-net-config.yaml",
|
|
13
|
+
):
|
|
14
|
+
yaml = YAML()
|
|
15
|
+
|
|
16
|
+
try:
|
|
17
|
+
with open(file_path, "r") as f:
|
|
18
|
+
file_content = f.read()
|
|
19
|
+
config_data = yaml.load(file_content)
|
|
20
|
+
config = cls.model_validate(config_data)
|
|
21
|
+
|
|
22
|
+
except FileNotFoundError:
|
|
23
|
+
config = cls()
|
|
24
|
+
|
|
25
|
+
config._file_path = file_path
|
|
26
|
+
config.save_to_yaml()
|
|
27
|
+
return config
|
|
28
|
+
|
|
29
|
+
def save_to_yaml(self):
|
|
30
|
+
yaml = YAML()
|
|
31
|
+
|
|
32
|
+
with open(self._file_path, "w") as f:
|
|
33
|
+
try:
|
|
34
|
+
config_data = self.model_dump(mode="json")
|
|
35
|
+
yaml.dump(config_data, f)
|
|
36
|
+
except Exception as e:
|
|
37
|
+
if self._file_content:
|
|
38
|
+
f.seek(0)
|
|
39
|
+
f.truncate()
|
|
40
|
+
f.write(self._file_content)
|
|
41
|
+
raise e
|
koi_net/config.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from rid_lib import RIDType
|
|
2
3
|
from ruamel.yaml import YAML
|
|
3
4
|
from pydantic import BaseModel, Field, PrivateAttr
|
|
4
5
|
from dotenv import load_dotenv
|
|
@@ -9,6 +10,8 @@ from .protocol.node import NodeProfile, NodeType
|
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class ServerConfig(BaseModel):
|
|
13
|
+
"""Config for the node server (full node only)."""
|
|
14
|
+
|
|
12
15
|
host: str = "127.0.0.1"
|
|
13
16
|
port: int = 8000
|
|
14
17
|
path: str | None = "/koi-net"
|
|
@@ -22,10 +25,15 @@ class NodeContact(BaseModel):
|
|
|
22
25
|
url: str | None = None
|
|
23
26
|
|
|
24
27
|
class KoiNetConfig(BaseModel):
|
|
28
|
+
"""Config for KOI-net."""
|
|
29
|
+
|
|
25
30
|
node_name: str
|
|
26
31
|
node_rid: KoiNetNode | None = None
|
|
27
32
|
node_profile: NodeProfile
|
|
28
33
|
|
|
34
|
+
rid_types_of_interest: list[RIDType] = Field(
|
|
35
|
+
default_factory=lambda: [KoiNetNode])
|
|
36
|
+
|
|
29
37
|
cache_directory_path: str = ".rid_cache"
|
|
30
38
|
event_queues_path: str = "event_queues.json"
|
|
31
39
|
private_key_pem_path: str = "priv_key.pem"
|
|
@@ -36,6 +44,15 @@ class KoiNetConfig(BaseModel):
|
|
|
36
44
|
_priv_key: PrivateKey | None = PrivateAttr(default=None)
|
|
37
45
|
|
|
38
46
|
class EnvConfig(BaseModel):
|
|
47
|
+
"""Config for environment variables.
|
|
48
|
+
|
|
49
|
+
Values set in the config are the variables names, and are loaded
|
|
50
|
+
from the environment at runtime. For example, if the config YAML
|
|
51
|
+
sets `priv_key_password: PRIV_KEY_PASSWORD` accessing
|
|
52
|
+
`priv_key_password` would retrieve the value of `PRIV_KEY_PASSWORD`
|
|
53
|
+
from the environment.
|
|
54
|
+
"""
|
|
55
|
+
|
|
39
56
|
priv_key_password: str | None = "PRIV_KEY_PASSWORD"
|
|
40
57
|
|
|
41
58
|
def __init__(self, **kwargs):
|
|
@@ -52,6 +69,12 @@ class EnvConfig(BaseModel):
|
|
|
52
69
|
return value
|
|
53
70
|
|
|
54
71
|
class NodeConfig(BaseModel):
|
|
72
|
+
"""Base configuration class for all nodes.
|
|
73
|
+
|
|
74
|
+
Designed to be extensible for custom node implementations. Classes
|
|
75
|
+
inheriting from `NodeConfig` may add additional config groups.
|
|
76
|
+
"""
|
|
77
|
+
|
|
55
78
|
server: ServerConfig = Field(default_factory=ServerConfig)
|
|
56
79
|
koi_net: KoiNetConfig
|
|
57
80
|
env: EnvConfig = Field(default_factory=EnvConfig)
|
|
@@ -65,6 +88,12 @@ class NodeConfig(BaseModel):
|
|
|
65
88
|
file_path: str = "config.yaml",
|
|
66
89
|
generate_missing: bool = True
|
|
67
90
|
):
|
|
91
|
+
"""Loads config state from YAML file.
|
|
92
|
+
|
|
93
|
+
Defaults to `config.yaml`. If `generate_missing` is set to
|
|
94
|
+
`True`, a private key and RID will be generated if not already
|
|
95
|
+
present in the config.
|
|
96
|
+
"""
|
|
68
97
|
yaml = YAML()
|
|
69
98
|
|
|
70
99
|
try:
|
|
@@ -112,6 +141,11 @@ class NodeConfig(BaseModel):
|
|
|
112
141
|
return config
|
|
113
142
|
|
|
114
143
|
def save_to_yaml(self):
|
|
144
|
+
"""Saves config state to YAML file.
|
|
145
|
+
|
|
146
|
+
File path is set by `load_from_yaml` class method.
|
|
147
|
+
"""
|
|
148
|
+
|
|
115
149
|
yaml = YAML()
|
|
116
150
|
|
|
117
151
|
with open(self._file_path, "w") as f:
|
koi_net/context.py
CHANGED
|
@@ -1,45 +1,35 @@
|
|
|
1
1
|
from rid_lib.ext import Cache
|
|
2
2
|
|
|
3
|
+
from koi_net.effector import Effector
|
|
3
4
|
from koi_net.network.resolver import NetworkResolver
|
|
4
5
|
from .config import NodeConfig
|
|
5
|
-
from .effector import Effector
|
|
6
6
|
from .network.graph import NetworkGraph
|
|
7
|
-
from .network.event_queue import
|
|
7
|
+
from .network.event_queue import EventQueue
|
|
8
8
|
from .network.request_handler import RequestHandler
|
|
9
9
|
from .identity import NodeIdentity
|
|
10
|
-
from .processor.
|
|
10
|
+
from .processor.kobj_queue import KobjQueue
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
class ActionContext:
|
|
14
|
-
identity: NodeIdentity
|
|
15
|
-
effector: Effector
|
|
16
|
-
|
|
17
|
-
def __init__(
|
|
18
|
-
self,
|
|
19
|
-
identity: NodeIdentity,
|
|
20
|
-
effector: Effector
|
|
21
|
-
):
|
|
22
|
-
self.identity = identity
|
|
23
|
-
self.effector = effector
|
|
24
|
-
|
|
25
|
-
|
|
26
13
|
class HandlerContext:
|
|
14
|
+
"""Provides knowledge handlers access to other subsystems."""
|
|
15
|
+
|
|
27
16
|
identity: NodeIdentity
|
|
28
17
|
config: NodeConfig
|
|
29
18
|
cache: Cache
|
|
30
|
-
event_queue:
|
|
19
|
+
event_queue: EventQueue
|
|
20
|
+
kobj_queue: KobjQueue
|
|
31
21
|
graph: NetworkGraph
|
|
32
22
|
request_handler: RequestHandler
|
|
33
23
|
resolver: NetworkResolver
|
|
34
24
|
effector: Effector
|
|
35
|
-
_processor: ProcessorInterface | None
|
|
36
25
|
|
|
37
26
|
def __init__(
|
|
38
27
|
self,
|
|
39
28
|
identity: NodeIdentity,
|
|
40
29
|
config: NodeConfig,
|
|
41
30
|
cache: Cache,
|
|
42
|
-
event_queue:
|
|
31
|
+
event_queue: EventQueue,
|
|
32
|
+
kobj_queue: KobjQueue,
|
|
43
33
|
graph: NetworkGraph,
|
|
44
34
|
request_handler: RequestHandler,
|
|
45
35
|
resolver: NetworkResolver,
|
|
@@ -49,15 +39,8 @@ class HandlerContext:
|
|
|
49
39
|
self.config = config
|
|
50
40
|
self.cache = cache
|
|
51
41
|
self.event_queue = event_queue
|
|
42
|
+
self.kobj_queue = kobj_queue
|
|
52
43
|
self.graph = graph
|
|
53
44
|
self.request_handler = request_handler
|
|
54
45
|
self.resolver = resolver
|
|
55
|
-
self.effector = effector
|
|
56
|
-
self._processor = None
|
|
57
|
-
|
|
58
|
-
def set_processor(self, processor: ProcessorInterface):
|
|
59
|
-
self._processor = processor
|
|
60
|
-
|
|
61
|
-
@property
|
|
62
|
-
def handle(self):
|
|
63
|
-
return self._processor.handle
|
|
46
|
+
self.effector = effector
|
koi_net/core.py
CHANGED
|
@@ -1,194 +1,78 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from typing import Generic, TypeVar
|
|
3
1
|
from rid_lib.ext import Cache
|
|
4
|
-
from .
|
|
5
|
-
from .
|
|
2
|
+
from .assembler import NodeAssembler
|
|
3
|
+
from .config.base import BaseConfig
|
|
4
|
+
from .context import HandlerContext
|
|
5
|
+
from .effector import Effector
|
|
6
|
+
from .handshaker import Handshaker
|
|
7
|
+
from .identity import NodeIdentity
|
|
8
|
+
from .processor.kobj_worker import KnowledgeProcessingWorker
|
|
9
|
+
from .lifecycle import NodeLifecycle
|
|
10
|
+
from .network.error_handler import ErrorHandler
|
|
11
|
+
from .network.event_queue import EventQueue
|
|
6
12
|
from .network.graph import NetworkGraph
|
|
7
13
|
from .network.request_handler import RequestHandler
|
|
14
|
+
from .network.resolver import NetworkResolver
|
|
8
15
|
from .network.response_handler import ResponseHandler
|
|
9
|
-
from .network.
|
|
10
|
-
from .
|
|
11
|
-
from .processor.
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
from .network.poll_event_buffer import PollEventBuffer
|
|
17
|
+
from .poller import NodePoller
|
|
18
|
+
from .processor.handlers import (
|
|
19
|
+
basic_manifest_handler,
|
|
20
|
+
basic_network_output_filter,
|
|
21
|
+
basic_rid_handler,
|
|
22
|
+
node_contact_handler,
|
|
23
|
+
edge_negotiation_handler,
|
|
24
|
+
forget_edge_on_node_deletion,
|
|
25
|
+
secure_profile_handler
|
|
26
|
+
)
|
|
27
|
+
from .processor.event_worker import EventProcessingWorker
|
|
28
|
+
from .processor.pipeline import KnowledgePipeline
|
|
29
|
+
from .processor.kobj_queue import KobjQueue
|
|
16
30
|
from .secure import Secure
|
|
17
|
-
from .config import NodeConfig
|
|
18
|
-
from .context import HandlerContext, ActionContext
|
|
19
|
-
from .effector import Effector
|
|
20
31
|
from .server import NodeServer
|
|
21
|
-
from .lifecycle import NodeLifecycle
|
|
22
|
-
from .poller import NodePoller
|
|
23
|
-
from . import default_actions
|
|
24
|
-
|
|
25
|
-
logger = logging.getLogger(__name__)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
T = TypeVar("T", bound=NodeConfig)
|
|
29
32
|
|
|
30
|
-
class NodeInterface(Generic[T]):
|
|
31
|
-
config: T
|
|
32
|
-
cache: Cache
|
|
33
|
-
identity: NodeIdentity
|
|
34
|
-
resolver: NetworkResolver
|
|
35
|
-
event_queue: NetworkEventQueue
|
|
36
|
-
graph: NetworkGraph
|
|
37
|
-
processor: ProcessorInterface
|
|
38
|
-
secure: Secure
|
|
39
|
-
server: NodeServer
|
|
40
|
-
|
|
41
|
-
use_kobj_processor_thread: bool
|
|
42
|
-
|
|
43
|
-
def __init__(
|
|
44
|
-
self,
|
|
45
|
-
config: T,
|
|
46
|
-
use_kobj_processor_thread: bool = False,
|
|
47
|
-
handlers: list[KnowledgeHandler] | None = None,
|
|
48
|
-
|
|
49
|
-
CacheOverride: type[Cache] | None = None,
|
|
50
|
-
NodeIdentityOverride: type[NodeIdentity] | None = None,
|
|
51
|
-
EffectorOverride: type[Effector] | None = None,
|
|
52
|
-
NetworkGraphOverride: type[NetworkGraph] | None = None,
|
|
53
|
-
SecureOverride: type[Secure] | None = None,
|
|
54
|
-
RequestHandlerOverride: type[RequestHandler] | None = None,
|
|
55
|
-
ResponseHandlerOverride: type[ResponseHandler] | None = None,
|
|
56
|
-
NetworkResolverOverride: type[NetworkResolver] | None = None,
|
|
57
|
-
NetworkEventQueueOverride: type[NetworkEventQueue] | None = None,
|
|
58
|
-
ActorOverride: type[Actor] | None = None,
|
|
59
|
-
ActionContextOverride: type[ActionContext] | None = None,
|
|
60
|
-
HandlerContextOverride: type[HandlerContext] | None = None,
|
|
61
|
-
KnowledgePipelineOverride: type[KnowledgePipeline] | None = None,
|
|
62
|
-
ProcessorInterfaceOverride: type[ProcessorInterface] | None = None,
|
|
63
|
-
ErrorHandlerOverride: type[ErrorHandler] | None = None,
|
|
64
|
-
NodeLifecycleOverride: type[NodeLifecycle] | None = None,
|
|
65
|
-
NodeServerOverride: type[NodeServer] | None = None,
|
|
66
|
-
NodePollerOverride: type[NodePoller] | None = None,
|
|
67
|
-
):
|
|
68
|
-
self.config = config
|
|
69
|
-
self.cache = (CacheOverride or Cache)(
|
|
70
|
-
directory_path=self.config.koi_net.cache_directory_path
|
|
71
|
-
)
|
|
72
33
|
|
|
73
|
-
|
|
74
|
-
self.effector = (EffectorOverride or Effector)(cache=self.cache)
|
|
34
|
+
# factory functions for components with non standard initializiation
|
|
75
35
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
identity=self.identity
|
|
79
|
-
)
|
|
36
|
+
def make_config() -> BaseConfig:
|
|
37
|
+
return BaseConfig.load_from_yaml()
|
|
80
38
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
effector=self.effector,
|
|
84
|
-
config=self.config
|
|
85
|
-
)
|
|
39
|
+
def make_cache(config: BaseConfig) -> Cache:
|
|
40
|
+
return Cache(directory_path=config.koi_net.cache_directory_path)
|
|
86
41
|
|
|
87
|
-
self.request_handler = (RequestHandlerOverride or RequestHandler)(
|
|
88
|
-
effector=self.effector,
|
|
89
|
-
identity=self.identity,
|
|
90
|
-
secure=self.secure
|
|
91
|
-
)
|
|
92
42
|
|
|
93
|
-
|
|
43
|
+
class BaseNode(NodeAssembler):
|
|
44
|
+
config = lambda: None
|
|
45
|
+
kobj_queue = KobjQueue
|
|
46
|
+
event_queue = EventQueue
|
|
47
|
+
poll_event_buf = PollEventBuffer
|
|
48
|
+
knowledge_handlers = lambda: [
|
|
49
|
+
basic_rid_handler,
|
|
50
|
+
basic_manifest_handler,
|
|
51
|
+
secure_profile_handler,
|
|
52
|
+
edge_negotiation_handler,
|
|
53
|
+
node_contact_handler,
|
|
54
|
+
basic_network_output_filter,
|
|
55
|
+
forget_edge_on_node_deletion
|
|
56
|
+
]
|
|
57
|
+
cache = make_cache
|
|
58
|
+
identity = NodeIdentity
|
|
59
|
+
graph = NetworkGraph
|
|
60
|
+
secure = Secure
|
|
61
|
+
handshaker = Handshaker
|
|
62
|
+
error_handler = ErrorHandler
|
|
63
|
+
request_handler = RequestHandler
|
|
64
|
+
response_handler = ResponseHandler
|
|
65
|
+
resolver = NetworkResolver
|
|
66
|
+
effector = Effector
|
|
67
|
+
handler_context = HandlerContext
|
|
68
|
+
pipeline = KnowledgePipeline
|
|
69
|
+
kobj_worker = KnowledgeProcessingWorker
|
|
70
|
+
event_worker = EventProcessingWorker
|
|
71
|
+
lifecycle = NodeLifecycle
|
|
94
72
|
|
|
95
|
-
self.resolver = (NetworkResolverOverride or NetworkResolver)(
|
|
96
|
-
config=self.config,
|
|
97
|
-
cache=self.cache,
|
|
98
|
-
identity=self.identity,
|
|
99
|
-
graph=self.graph,
|
|
100
|
-
request_handler=self.request_handler,
|
|
101
|
-
effector=self.effector
|
|
102
|
-
)
|
|
103
73
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
cache=self.cache,
|
|
107
|
-
identity=self.identity,
|
|
108
|
-
graph=self.graph,
|
|
109
|
-
request_handler=self.request_handler,
|
|
110
|
-
effector=self.effector
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
self.actor = (ActorOverride or Actor)()
|
|
114
|
-
|
|
115
|
-
# pull all handlers defined in default_handlers module
|
|
116
|
-
if handlers is None:
|
|
117
|
-
handlers = [
|
|
118
|
-
obj for obj in vars(default_handlers).values()
|
|
119
|
-
if isinstance(obj, KnowledgeHandler)
|
|
120
|
-
]
|
|
74
|
+
class FullNode(BaseNode):
|
|
75
|
+
entrypoint = NodeServer
|
|
121
76
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
self.action_context = (ActionContextOverride or ActionContext)(
|
|
125
|
-
identity=self.identity,
|
|
126
|
-
effector=self.effector
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
self.handler_context = (HandlerContextOverride or HandlerContext)(
|
|
130
|
-
identity=self.identity,
|
|
131
|
-
config=self.config,
|
|
132
|
-
cache=self.cache,
|
|
133
|
-
event_queue=self.event_queue,
|
|
134
|
-
graph=self.graph,
|
|
135
|
-
request_handler=self.request_handler,
|
|
136
|
-
resolver=self.resolver,
|
|
137
|
-
effector=self.effector
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
self.pipeline = (KnowledgePipelineOverride or KnowledgePipeline)(
|
|
141
|
-
handler_context=self.handler_context,
|
|
142
|
-
cache=self.cache,
|
|
143
|
-
request_handler=self.request_handler,
|
|
144
|
-
event_queue=self.event_queue,
|
|
145
|
-
graph=self.graph,
|
|
146
|
-
default_handlers=handlers
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
self.processor = (ProcessorInterfaceOverride or ProcessorInterface)(
|
|
150
|
-
pipeline=self.pipeline,
|
|
151
|
-
use_kobj_processor_thread=self.use_kobj_processor_thread
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
self.error_handler = (ErrorHandlerOverride or ErrorHandler)(
|
|
155
|
-
processor=self.processor,
|
|
156
|
-
actor=self.actor
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
self.request_handler.set_error_handler(self.error_handler)
|
|
160
|
-
|
|
161
|
-
self.handler_context.set_processor(self.processor)
|
|
162
|
-
|
|
163
|
-
self.effector.set_processor(self.processor)
|
|
164
|
-
self.effector.set_resolver(self.resolver)
|
|
165
|
-
self.effector.set_action_context(self.action_context)
|
|
166
|
-
|
|
167
|
-
self.actor.set_ctx(self.handler_context)
|
|
168
|
-
|
|
169
|
-
self.lifecycle = (NodeLifecycleOverride or NodeLifecycle)(
|
|
170
|
-
config=self.config,
|
|
171
|
-
identity=self.identity,
|
|
172
|
-
graph=self.graph,
|
|
173
|
-
processor=self.processor,
|
|
174
|
-
effector=self.effector,
|
|
175
|
-
actor=self.actor,
|
|
176
|
-
use_kobj_processor_thread=use_kobj_processor_thread
|
|
177
|
-
)
|
|
178
|
-
|
|
179
|
-
# if self.config.koi_net.node_profile.node_type == NodeType.FULL:
|
|
180
|
-
self.server = (NodeServerOverride or NodeServer)(
|
|
181
|
-
config=self.config,
|
|
182
|
-
lifecycle=self.lifecycle,
|
|
183
|
-
secure=self.secure,
|
|
184
|
-
processor=self.processor,
|
|
185
|
-
event_queue=self.event_queue,
|
|
186
|
-
response_handler=self.response_handler
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
self.poller = (NodePollerOverride or NodePoller)(
|
|
190
|
-
processor=self.processor,
|
|
191
|
-
lifecycle=self.lifecycle,
|
|
192
|
-
resolver=self.resolver,
|
|
193
|
-
config=self.config
|
|
194
|
-
)
|
|
77
|
+
class PartialNode(BaseNode):
|
|
78
|
+
entrypoint = NodePoller
|
koi_net/default_actions.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""Implementations of default dereference actions."""
|
|
2
|
+
|
|
1
3
|
from .context import ActionContext
|
|
2
4
|
from rid_lib.types import KoiNetNode
|
|
3
5
|
from rid_lib.ext import Bundle
|
|
@@ -5,7 +7,14 @@ from .effector import Effector
|
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
@Effector.register_default_action(KoiNetNode)
|
|
8
|
-
def dereference_koi_node(
|
|
10
|
+
def dereference_koi_node(
|
|
11
|
+
ctx: ActionContext, rid: KoiNetNode
|
|
12
|
+
) -> Bundle | None:
|
|
13
|
+
"""Dereference function for this KOI node.
|
|
14
|
+
|
|
15
|
+
Generates a bundle from this node's profile data in the config.
|
|
16
|
+
"""
|
|
17
|
+
|
|
9
18
|
if rid != ctx.identity.rid:
|
|
10
19
|
return
|
|
11
20
|
|