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
@@ -0,0 +1,26 @@
1
+ from rid_lib.types import KoiNetNode
2
+
3
+ from koi_net.protocol.event import Event
4
+
5
+
6
+ class PollEventBuffer:
7
+ buffers: dict[KoiNetNode, list[Event]]
8
+
9
+ def __init__(self):
10
+ self.buffers = dict()
11
+
12
+ def push(self, node: KoiNetNode, event: Event):
13
+ event_buf = self.buffers.setdefault(node, [])
14
+ event_buf.append(event)
15
+
16
+ def flush(self, node: KoiNetNode, limit: int = 0):
17
+ event_buf = self.buffers.get(node, [])
18
+
19
+ if limit and len(event_buf) > limit:
20
+ to_return = event_buf[:limit]
21
+ self.buffers[node] = event_buf[limit:]
22
+ else:
23
+ to_return = event_buf.copy()
24
+ self.buffers[node] = []
25
+
26
+ return to_return
@@ -1,9 +1,11 @@
1
- import logging
1
+ import structlog
2
2
  import httpx
3
3
  from rid_lib import RID
4
4
  from rid_lib.ext import Cache
5
5
  from rid_lib.types.koi_net_node import KoiNetNode
6
6
 
7
+ from koi_net.protocol.model_map import API_MODEL_MAP
8
+
7
9
  from ..identity import NodeIdentity
8
10
  from ..protocol.api_models import (
9
11
  RidsPayload,
@@ -30,8 +32,7 @@ from ..protocol.node import NodeProfile, NodeType
30
32
  from ..secure import Secure
31
33
  from .error_handler import ErrorHandler
32
34
 
33
-
34
- logger = logging.getLogger(__name__)
35
+ log = structlog.stdlib.get_logger()
35
36
 
36
37
 
37
38
  # Custom error types for request handling
@@ -74,7 +75,7 @@ class RequestHandler:
74
75
  def get_url(self, node_rid: KoiNetNode) -> str:
75
76
  """Retrieves URL of a node from its RID."""
76
77
 
77
- logger.debug(f"Getting URL for {node_rid!r}")
78
+ log.debug(f"Getting URL for {node_rid!r}")
78
79
  node_url = None
79
80
 
80
81
  if node_rid == self.identity.rid:
@@ -84,20 +85,20 @@ class RequestHandler:
84
85
 
85
86
  if node_bundle:
86
87
  node_profile = node_bundle.validate_contents(NodeProfile)
87
- logger.debug(f"Found node profile: {node_profile}")
88
+ log.debug(f"Found node profile: {node_profile}")
88
89
  if node_profile.node_type != NodeType.FULL:
89
90
  raise PartialNodeQueryError("Can't query partial node")
90
91
  node_url = node_profile.base_url
91
92
 
92
93
  else:
93
94
  if node_rid == self.identity.config.koi_net.first_contact.rid:
94
- logger.debug("Found URL of first contact")
95
+ log.debug("Found URL of first contact")
95
96
  node_url = self.identity.config.koi_net.first_contact.url
96
97
 
97
98
  if not node_url:
98
99
  raise NodeNotFoundError("Node not found")
99
100
 
100
- logger.debug(f"Resolved {node_rid!r} to {node_url}")
101
+ log.debug(f"Resolved {node_rid!r} to {node_url}")
101
102
  return node_url
102
103
 
103
104
  def make_request(
@@ -108,7 +109,7 @@ class RequestHandler:
108
109
  ) -> ResponseModels | None:
109
110
  """Makes a request to a node."""
110
111
  url = self.get_url(node) + path
111
- logger.info(f"Making request to {url}")
112
+ log.info(f"Making request to {url}")
112
113
 
113
114
  signed_envelope = self.secure.create_envelope(
114
115
  payload=request,
@@ -116,9 +117,12 @@ class RequestHandler:
116
117
  )
117
118
 
118
119
  try:
119
- result = httpx.post(url, data=signed_envelope.model_dump_json(exclude_none=True))
120
+ result = httpx.post(
121
+ url,
122
+ data=signed_envelope.model_dump_json(exclude_none=True)
123
+ )
120
124
  except httpx.ConnectError as err:
121
- logger.debug("Failed to connect")
125
+ log.debug("Failed to connect")
122
126
  self.error_handler.handle_connection_error(node)
123
127
  raise err
124
128
 
@@ -127,20 +131,11 @@ class RequestHandler:
127
131
  self.error_handler.handle_protocol_error(resp.error, node)
128
132
  return resp
129
133
 
130
- if path == BROADCAST_EVENTS_PATH:
131
- return None
132
- elif path == POLL_EVENTS_PATH:
133
- EnvelopeModel = SignedEnvelope[EventsPayload]
134
- elif path == FETCH_RIDS_PATH:
135
- EnvelopeModel = SignedEnvelope[RidsPayload]
136
- elif path == FETCH_MANIFESTS_PATH:
137
- EnvelopeModel = SignedEnvelope[ManifestsPayload]
138
- elif path == FETCH_BUNDLES_PATH:
139
- EnvelopeModel = SignedEnvelope[BundlesPayload]
140
- else:
141
- raise UnknownPathError(f"Unknown path '{path}'")
134
+ resp_env_model = API_MODEL_MAP[path].response_envelope
135
+ if resp_env_model is None:
136
+ return
142
137
 
143
- resp_envelope = EnvelopeModel.model_validate_json(result.text)
138
+ resp_envelope = resp_env_model.model_validate_json(result.text)
144
139
  self.secure.validate_envelope(resp_envelope)
145
140
 
146
141
  return resp_envelope.payload
@@ -157,7 +152,7 @@ class RequestHandler:
157
152
  """
158
153
  request = req or EventsPayload.model_validate(kwargs)
159
154
  self.make_request(node, BROADCAST_EVENTS_PATH, request)
160
- logger.info(f"Broadcasted {len(request.events)} event(s) to {node!r}")
155
+ log.info(f"Broadcasted {len(request.events)} event(s) to {node!r}")
161
156
 
162
157
  def poll_events(
163
158
  self,
@@ -172,7 +167,7 @@ class RequestHandler:
172
167
  request = req or PollEvents.model_validate(kwargs)
173
168
  resp = self.make_request(node, POLL_EVENTS_PATH, request)
174
169
  if type(resp) != ErrorResponse:
175
- logger.info(f"Polled {len(resp.events)} events from {node!r}")
170
+ log.info(f"Polled {len(resp.events)} events from {node!r}")
176
171
  return resp
177
172
 
178
173
  def fetch_rids(
@@ -188,7 +183,7 @@ class RequestHandler:
188
183
  request = req or FetchRids.model_validate(kwargs)
189
184
  resp = self.make_request(node, FETCH_RIDS_PATH, request)
190
185
  if type(resp) != ErrorResponse:
191
- logger.info(f"Fetched {len(resp.rids)} RID(s) from {node!r}")
186
+ log.info(f"Fetched {len(resp.rids)} RID(s) from {node!r}")
192
187
  return resp
193
188
 
194
189
  def fetch_manifests(
@@ -204,7 +199,7 @@ class RequestHandler:
204
199
  request = req or FetchManifests.model_validate(kwargs)
205
200
  resp = self.make_request(node, FETCH_MANIFESTS_PATH, request)
206
201
  if type(resp) != ErrorResponse:
207
- logger.info(f"Fetched {len(resp.manifests)} manifest(s) from {node!r}")
202
+ log.info(f"Fetched {len(resp.manifests)} manifest(s) from {node!r}")
208
203
  return resp
209
204
 
210
205
  def fetch_bundles(
@@ -220,5 +215,5 @@ class RequestHandler:
220
215
  request = req or FetchBundles.model_validate(kwargs)
221
216
  resp = self.make_request(node, FETCH_BUNDLES_PATH, request)
222
217
  if type(resp) != ErrorResponse:
223
- logger.info(f"Fetched {len(resp.bundles)} bundle(s) from {node!r}")
218
+ log.info(f"Fetched {len(resp.bundles)} bundle(s) from {node!r}")
224
219
  return resp
@@ -1,4 +1,4 @@
1
- import logging
1
+ import structlog
2
2
  import httpx
3
3
  from rid_lib import RID
4
4
  from rid_lib.core import RIDType
@@ -11,9 +11,9 @@ from ..protocol.node import NodeProfile, NodeType
11
11
  from ..protocol.event import Event
12
12
  from ..protocol.api_models import ErrorResponse
13
13
  from ..identity import NodeIdentity
14
- from ..config import NodeConfig
14
+ from ..config.core import NodeConfig
15
15
 
16
- logger = logging.getLogger(__name__)
16
+ log = structlog.stdlib.get_logger()
17
17
 
18
18
 
19
19
  class NetworkResolver:
@@ -45,7 +45,7 @@ class NetworkResolver:
45
45
  def get_state_providers(self, rid_type: RIDType) -> list[KoiNetNode]:
46
46
  """Returns list of node RIDs which provide state for specified RID type."""
47
47
 
48
- logger.debug(f"Looking for state providers of {rid_type}")
48
+ log.debug(f"Looking for state providers of {rid_type}")
49
49
  provider_nodes = []
50
50
  for node_rid in self.cache.list_rids(rid_types=[KoiNetNode]):
51
51
  if node_rid == self.identity.rid:
@@ -56,17 +56,17 @@ class NetworkResolver:
56
56
  node_profile = node_bundle.validate_contents(NodeProfile)
57
57
 
58
58
  if (node_profile.node_type == NodeType.FULL) and (rid_type in node_profile.provides.state):
59
- logger.debug(f"Found provider {node_rid!r}")
59
+ log.debug(f"Found provider {node_rid!r}")
60
60
  provider_nodes.append(node_rid)
61
61
 
62
62
  if not provider_nodes:
63
- logger.debug("Failed to find providers")
63
+ log.debug("Failed to find providers")
64
64
  return provider_nodes
65
65
 
66
66
  def fetch_remote_bundle(self, rid: RID) -> tuple[Bundle | None, KoiNetNode | None]:
67
67
  """Attempts to fetch a bundle by RID from known peer nodes."""
68
68
 
69
- logger.debug(f"Fetching remote bundle {rid!r}")
69
+ log.debug(f"Fetching remote bundle {rid!r}")
70
70
  remote_bundle, node_rid = None, None
71
71
  for node_rid in self.get_state_providers(type(rid)):
72
72
  payload = self.request_handler.fetch_bundles(
@@ -74,18 +74,18 @@ class NetworkResolver:
74
74
 
75
75
  if payload.bundles:
76
76
  remote_bundle = payload.bundles[0]
77
- logger.debug(f"Got bundle from {node_rid!r}")
77
+ log.debug(f"Got bundle from {node_rid!r}")
78
78
  break
79
79
 
80
80
  if not remote_bundle:
81
- logger.warning("Failed to fetch remote bundle")
81
+ log.warning("Failed to fetch remote bundle")
82
82
 
83
83
  return remote_bundle, node_rid
84
84
 
85
85
  def fetch_remote_manifest(self, rid: RID) -> tuple[Bundle | None, KoiNetNode | None]:
86
86
  """Attempts to fetch a manifest by RID from known peer nodes."""
87
87
 
88
- logger.debug(f"Fetching remote manifest {rid!r}")
88
+ log.debug(f"Fetching remote manifest {rid!r}")
89
89
  remote_manifest, node_rid = None, None
90
90
  for node_rid in self.get_state_providers(type(rid)):
91
91
  payload = self.request_handler.fetch_manifests(
@@ -93,11 +93,11 @@ class NetworkResolver:
93
93
 
94
94
  if payload.manifests:
95
95
  remote_manifest = payload.manifests[0]
96
- logger.debug(f"Got bundle from {node_rid!r}")
96
+ log.debug(f"Got bundle from {node_rid!r}")
97
97
  break
98
98
 
99
99
  if not remote_manifest:
100
- logger.warning("Failed to fetch remote bundle")
100
+ log.warning("Failed to fetch remote bundle")
101
101
 
102
102
  return remote_manifest, node_rid
103
103
 
@@ -136,12 +136,12 @@ class NetworkResolver:
136
136
  continue
137
137
 
138
138
  if payload.events:
139
- logger.debug(f"Received {len(payload.events)} events from {node_rid!r}")
139
+ log.debug(f"Received {len(payload.events)} events from {node_rid!r}")
140
140
 
141
141
  event_dict[node_rid] = payload.events
142
142
 
143
143
  except httpx.ConnectError:
144
- logger.debug(f"Failed to reach node {node_rid!r}")
144
+ log.debug(f"Failed to reach node {node_rid!r}")
145
145
  continue
146
146
 
147
147
  return event_dict
@@ -1,10 +1,20 @@
1
- import logging
1
+ import structlog
2
2
  from rid_lib import RID
3
3
  from rid_lib.types import KoiNetNode
4
4
  from rid_lib.ext import Manifest, Cache
5
5
  from rid_lib.ext.bundle import Bundle
6
6
 
7
+ from koi_net.network.poll_event_buffer import PollEventBuffer
8
+ from koi_net.processor.kobj_queue import KobjQueue
9
+ from koi_net.protocol.consts import BROADCAST_EVENTS_PATH, FETCH_BUNDLES_PATH, FETCH_MANIFESTS_PATH, FETCH_RIDS_PATH, POLL_EVENTS_PATH
10
+ from koi_net.protocol.envelope import SignedEnvelope
11
+ from koi_net.protocol.model_map import API_MODEL_MAP
12
+ from koi_net.secure import Secure
13
+
7
14
  from ..protocol.api_models import (
15
+ ApiModels,
16
+ EventsPayload,
17
+ PollEvents,
8
18
  RidsPayload,
9
19
  ManifestsPayload,
10
20
  BundlesPayload,
@@ -13,30 +23,81 @@ from ..protocol.api_models import (
13
23
  FetchBundles,
14
24
  )
15
25
 
16
- logger = logging.getLogger(__name__)
26
+ log = structlog.stdlib.get_logger()
17
27
 
18
28
 
19
29
  class ResponseHandler:
20
30
  """Handles generating responses to requests from other KOI nodes."""
21
31
 
22
32
  cache: Cache
33
+ kobj_queue: KobjQueue
34
+ poll_event_buf: PollEventBuffer
23
35
 
24
36
  def __init__(
25
37
  self,
26
- cache: Cache,
38
+ cache: Cache,
39
+ kobj_queue: KobjQueue,
40
+ poll_event_buf: PollEventBuffer,
41
+ secure: Secure
27
42
  ):
28
43
  self.cache = cache
44
+ self.kobj_queue = kobj_queue
45
+ self.poll_event_buf = poll_event_buf
46
+ self.secure = secure
47
+
48
+ def handle_response(self, path: str, req: SignedEnvelope):
49
+ self.secure.validate_envelope(req)
50
+
51
+ response_map = {
52
+ BROADCAST_EVENTS_PATH: self.broadcast_events_handler,
53
+ POLL_EVENTS_PATH: self.poll_events_handler,
54
+ FETCH_RIDS_PATH: self.fetch_rids_handler,
55
+ FETCH_MANIFESTS_PATH: self.fetch_manifests_handler,
56
+ FETCH_BUNDLES_PATH: self.fetch_bundles_handler
57
+ }
58
+
59
+ response = response_map[path](req.payload, req.source_node)
60
+
61
+ if response is None:
62
+ return
63
+
64
+ return self.secure.create_envelope(
65
+ payload=response,
66
+ target=req.source_node
67
+ )
29
68
 
30
- def fetch_rids(self, req: FetchRids, source: KoiNetNode) -> RidsPayload:
69
+ def broadcast_events_handler(self, req: EventsPayload, source: KoiNetNode):
70
+ log.info(f"Request to broadcast events, received {len(req.events)} event(s)")
71
+
72
+ for event in req.events:
73
+ self.kobj_queue.push(event=event, source=source)
74
+
75
+ def poll_events_handler(
76
+ self,
77
+ req: PollEvents,
78
+ source: KoiNetNode
79
+ ) -> EventsPayload:
80
+ log.info(f"Request to poll events")
81
+ events = self.poll_event_buf.flush(source, limit=req.limit)
82
+ return EventsPayload(events=events)
83
+
84
+ def fetch_rids_handler(
85
+ self,
86
+ req: FetchRids,
87
+ source: KoiNetNode
88
+ ) -> RidsPayload:
31
89
  """Returns response to fetch RIDs request."""
32
- logger.info(f"Request to fetch rids, allowed types {req.rid_types}")
90
+ log.info(f"Request to fetch rids, allowed types {req.rid_types}")
33
91
  rids = self.cache.list_rids(req.rid_types)
34
92
 
35
93
  return RidsPayload(rids=rids)
36
94
 
37
- def fetch_manifests(self, req: FetchManifests, source: KoiNetNode) -> ManifestsPayload:
95
+ def fetch_manifests_handler(self,
96
+ req: FetchManifests,
97
+ source: KoiNetNode
98
+ ) -> ManifestsPayload:
38
99
  """Returns response to fetch manifests request."""
39
- logger.info(f"Request to fetch manifests, allowed types {req.rid_types}, rids {req.rids}")
100
+ log.info(f"Request to fetch manifests, allowed types {req.rid_types}, rids {req.rids}")
40
101
 
41
102
  manifests: list[Manifest] = []
42
103
  not_found: list[RID] = []
@@ -50,9 +111,13 @@ class ResponseHandler:
50
111
 
51
112
  return ManifestsPayload(manifests=manifests, not_found=not_found)
52
113
 
53
- def fetch_bundles(self, req: FetchBundles, source: KoiNetNode) -> BundlesPayload:
114
+ def fetch_bundles_handler(
115
+ self,
116
+ req: FetchBundles,
117
+ source: KoiNetNode
118
+ ) -> BundlesPayload:
54
119
  """Returns response to fetch bundles request."""
55
- logger.info(f"Request to fetch bundles, requested rids {req.rids}")
120
+ log.info(f"Request to fetch bundles, requested rids {req.rids}")
56
121
 
57
122
  bundles: list[Bundle] = []
58
123
  not_found: list[RID] = []
@@ -1,26 +1,15 @@
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
- from .config import NodeConfig
5
- from .network.graph import NetworkGraph
6
- from .network.event_queue import EventQueue
7
- from .network.request_handler import RequestHandler
8
- from .identity import NodeIdentity
9
- from .processor.kobj_queue import KobjQueue
5
+ from ..config.core import NodeConfig
6
+ from ..network.graph import NetworkGraph
7
+ from ..network.event_queue import EventQueue
8
+ from ..network.request_handler import RequestHandler
9
+ from ..identity import NodeIdentity
10
+ from .kobj_queue import KobjQueue
10
11
 
11
12
 
12
- class ActionContext:
13
- """Provides action handlers access to other subsystems."""
14
-
15
- identity: NodeIdentity
16
-
17
- def __init__(
18
- self,
19
- identity: NodeIdentity,
20
- ):
21
- self.identity = identity
22
-
23
-
24
13
  class HandlerContext:
25
14
  """Provides knowledge handlers access to other subsystems."""
26
15
 
@@ -32,6 +21,7 @@ class HandlerContext:
32
21
  graph: NetworkGraph
33
22
  request_handler: RequestHandler
34
23
  resolver: NetworkResolver
24
+ effector: Effector
35
25
 
36
26
  def __init__(
37
27
  self,
@@ -43,6 +33,7 @@ class HandlerContext:
43
33
  graph: NetworkGraph,
44
34
  request_handler: RequestHandler,
45
35
  resolver: NetworkResolver,
36
+ effector: Effector
46
37
  ):
47
38
  self.identity = identity
48
39
  self.config = config
@@ -51,4 +42,5 @@ class HandlerContext:
51
42
  self.kobj_queue = kobj_queue
52
43
  self.graph = graph
53
44
  self.request_handler = request_handler
54
- self.resolver = resolver
45
+ self.resolver = resolver
46
+ self.effector = effector
@@ -2,7 +2,10 @@ from dataclasses import dataclass
2
2
  from enum import StrEnum
3
3
  from typing import Callable
4
4
  from rid_lib import RIDType
5
+
5
6
  from ..protocol.event import EventType
7
+ from .knowledge_object import KnowledgeObject
8
+ from .context import HandlerContext
6
9
 
7
10
 
8
11
  class StopChain:
@@ -32,7 +35,7 @@ class HandlerType(StrEnum):
32
35
  class KnowledgeHandler:
33
36
  """Handles knowledge processing events of the provided types."""
34
37
 
35
- func: Callable
38
+ func: Callable[[HandlerContext, KnowledgeObject], None | KnowledgeObject | StopChain]
36
39
  handler_type: HandlerType
37
40
  rid_types: list[RIDType] | None
38
41
  event_types: list[EventType | None] | None = None
@@ -1,18 +1,19 @@
1
1
  """Implementation of default knowledge handlers."""
2
2
 
3
- import logging
3
+ import structlog
4
4
  from rid_lib.ext import Bundle
5
5
  from rid_lib.ext.utils import sha256_hash
6
6
  from rid_lib.types import KoiNetNode, KoiNetEdge
7
7
  from koi_net.protocol.node import NodeType
8
8
  from .handler import KnowledgeHandler, HandlerType, STOP_CHAIN
9
9
  from .knowledge_object import KnowledgeObject
10
- from ..context import HandlerContext
10
+ from .context import HandlerContext
11
11
  from ..protocol.event import Event, EventType
12
- from ..protocol.edge import EdgeProfile, EdgeStatus, EdgeType, generate_edge_bundle
12
+ from ..protocol.edge import EdgeProfile, EdgeStatus, EdgeType
13
13
  from ..protocol.node import NodeProfile
14
14
 
15
- logger = logging.getLogger(__name__)
15
+ log = structlog.stdlib.get_logger()
16
+
16
17
 
17
18
  # RID handlers
18
19
 
@@ -24,7 +25,7 @@ def basic_rid_handler(ctx: HandlerContext, kobj: KnowledgeObject):
24
25
  RID is known to this node.
25
26
  """
26
27
  if (kobj.rid == ctx.identity.rid and kobj.source):
27
- logger.debug("Don't let anyone else tell me who I am!")
28
+ log.debug("Don't let anyone else tell me who I am!")
28
29
  return STOP_CHAIN
29
30
 
30
31
  if kobj.event_type == EventType.FORGET:
@@ -45,17 +46,17 @@ def basic_manifest_handler(ctx: HandlerContext, kobj: KnowledgeObject):
45
46
 
46
47
  if prev_bundle:
47
48
  if kobj.manifest.sha256_hash == prev_bundle.manifest.sha256_hash:
48
- logger.debug("Hash of incoming manifest is same as existing knowledge, ignoring")
49
+ log.debug("Hash of incoming manifest is same as existing knowledge, ignoring")
49
50
  return STOP_CHAIN
50
51
  if kobj.manifest.timestamp <= prev_bundle.manifest.timestamp:
51
- logger.debug("Timestamp of incoming manifest is the same or older than existing knowledge, ignoring")
52
+ log.debug("Timestamp of incoming manifest is the same or older than existing knowledge, ignoring")
52
53
  return STOP_CHAIN
53
54
 
54
- logger.debug("RID previously known to me, labeling as 'UPDATE'")
55
+ log.debug("RID previously known to me, labeling as 'UPDATE'")
55
56
  kobj.normalized_event_type = EventType.UPDATE
56
57
 
57
58
  else:
58
- logger.debug("RID previously unknown to me, labeling as 'NEW'")
59
+ log.debug("RID previously unknown to me, labeling as 'NEW'")
59
60
  kobj.normalized_event_type = EventType.NEW
60
61
 
61
62
  return kobj
@@ -78,7 +79,7 @@ def secure_profile_handler(ctx: HandlerContext, kobj: KnowledgeObject):
78
79
  node_rid: KoiNetNode = kobj.rid
79
80
 
80
81
  if sha256_hash(node_profile.public_key) != node_rid.hash:
81
- logger.warning(f"Public key hash mismatch for {node_rid!r}!")
82
+ log.warning(f"Public key hash mismatch for {node_rid!r}!")
82
83
  return STOP_CHAIN
83
84
 
84
85
  @KnowledgeHandler.create(
@@ -104,13 +105,13 @@ def edge_negotiation_handler(ctx: HandlerContext, kobj: KnowledgeObject):
104
105
  if edge_profile.status != EdgeStatus.PROPOSED:
105
106
  return
106
107
 
107
- logger.debug("Handling edge negotiation")
108
+ log.debug("Handling edge negotiation")
108
109
 
109
110
  peer_rid = edge_profile.target
110
111
  peer_bundle = ctx.cache.read(peer_rid)
111
112
 
112
113
  if not peer_bundle:
113
- logger.warning(f"Peer {peer_rid!r} unknown to me")
114
+ log.warning(f"Peer {peer_rid!r} unknown to me")
114
115
  return STOP_CHAIN
115
116
 
116
117
  peer_profile = peer_bundle.validate_contents(NodeProfile)
@@ -125,30 +126,30 @@ def edge_negotiation_handler(ctx: HandlerContext, kobj: KnowledgeObject):
125
126
  abort = False
126
127
  if (edge_profile.edge_type == EdgeType.WEBHOOK and
127
128
  peer_profile.node_type == NodeType.PARTIAL):
128
- logger.debug("Partial nodes cannot use webhooks")
129
+ log.debug("Partial nodes cannot use webhooks")
129
130
  abort = True
130
131
 
131
132
  if not set(edge_profile.rid_types).issubset(provided_events):
132
- logger.debug("Requested RID types not provided by this node")
133
+ log.debug("Requested RID types not provided by this node")
133
134
  abort = True
134
135
 
135
136
  if abort:
136
137
  event = Event.from_rid(EventType.FORGET, kobj.rid)
137
- ctx.event_queue.push_event_to(event, peer_rid, flush=True)
138
+ ctx.event_queue.push(event, peer_rid, flush=True)
138
139
  return STOP_CHAIN
139
140
 
140
141
  else:
141
142
  # approve edge profile
142
- logger.debug("Approving proposed edge")
143
+ log.debug("Approving proposed edge")
143
144
  edge_profile.status = EdgeStatus.APPROVED
144
145
  updated_bundle = Bundle.generate(kobj.rid, edge_profile.model_dump())
145
146
 
146
- ctx.kobj_queue.put_kobj(bundle=updated_bundle, event_type=EventType.UPDATE)
147
+ ctx.kobj_queue.push(bundle=updated_bundle, event_type=EventType.UPDATE)
147
148
  return
148
149
 
149
150
  elif edge_profile.target == ctx.identity.rid:
150
151
  if edge_profile.status == EdgeStatus.APPROVED:
151
- logger.debug("Edge approved by other node!")
152
+ log.debug("Edge approved by other node!")
152
153
 
153
154
 
154
155
  # Network handlers
@@ -176,8 +177,8 @@ def node_contact_handler(ctx: HandlerContext, kobj: KnowledgeObject):
176
177
  if not available_rid_types:
177
178
  return
178
179
 
179
- logger.info("Identified a coordinator!")
180
- logger.info("Proposing new edge")
180
+ log.info("Identified a coordinator!")
181
+ log.info("Proposing new edge")
181
182
 
182
183
  # already have an edge established
183
184
  edge_rid = ctx.graph.get_edge(
@@ -215,9 +216,9 @@ def node_contact_handler(ctx: HandlerContext, kobj: KnowledgeObject):
215
216
 
216
217
  # queued for processing
217
218
  edge_bundle = Bundle.generate(edge_rid, edge_profile.model_dump())
218
- ctx.kobj_queue.put_kobj(bundle=edge_bundle)
219
+ ctx.kobj_queue.push(bundle=edge_bundle)
219
220
 
220
- logger.info("Catching up on network state")
221
+ log.info("Catching up on network state")
221
222
 
222
223
  payload = ctx.request_handler.fetch_rids(
223
224
  node=kobj.rid,
@@ -225,16 +226,16 @@ def node_contact_handler(ctx: HandlerContext, kobj: KnowledgeObject):
225
226
  )
226
227
  for rid in payload.rids:
227
228
  if rid == ctx.identity.rid:
228
- logger.info("Skipping myself")
229
+ log.info("Skipping myself")
229
230
  continue
230
231
  if ctx.cache.exists(rid):
231
- logger.info(f"Skipping known RID {rid!r}")
232
+ log.info(f"Skipping known RID {rid!r}")
232
233
  continue
233
234
 
234
235
  # marked as external since we are handling RIDs from another node
235
236
  # will fetch remotely instead of checking local cache
236
- ctx.kobj_queue.put_kobj(rid=rid, source=kobj.rid)
237
- logger.info("Done")
237
+ ctx.kobj_queue.push(rid=rid, source=kobj.rid)
238
+ log.info("Done")
238
239
 
239
240
 
240
241
  @KnowledgeHandler.create(HandlerType.Network)
@@ -260,12 +261,12 @@ def basic_network_output_filter(ctx: HandlerContext, kobj: KnowledgeObject):
260
261
  edge_profile = kobj.bundle.validate_contents(EdgeProfile)
261
262
 
262
263
  if edge_profile.source == ctx.identity.rid:
263
- logger.debug(f"Adding edge target '{edge_profile.target!r}' to network targets")
264
+ log.debug(f"Adding edge target '{edge_profile.target!r}' to network targets")
264
265
  kobj.network_targets.update([edge_profile.target])
265
266
  involves_me = True
266
267
 
267
268
  elif edge_profile.target == ctx.identity.rid:
268
- logger.debug(f"Adding edge source '{edge_profile.source!r}' to network targets")
269
+ log.debug(f"Adding edge source '{edge_profile.source!r}' to network targets")
269
270
  kobj.network_targets.update([edge_profile.source])
270
271
  involves_me = True
271
272
 
@@ -276,7 +277,7 @@ def basic_network_output_filter(ctx: HandlerContext, kobj: KnowledgeObject):
276
277
  allowed_type=type(kobj.rid)
277
278
  )
278
279
 
279
- logger.debug(f"Updating network targets with '{type(kobj.rid)}' subscribers: {subscribers}")
280
+ log.debug(f"Updating network targets with '{type(kobj.rid)}' subscribers: {subscribers}")
280
281
  kobj.network_targets.update(subscribers)
281
282
 
282
283
  return kobj
@@ -294,5 +295,5 @@ def forget_edge_on_node_deletion(ctx: HandlerContext, kobj: KnowledgeObject):
294
295
  edge_profile = edge_bundle.validate_contents(EdgeProfile)
295
296
 
296
297
  if kobj.rid in (edge_profile.source, edge_profile.target):
297
- logger.debug("Identified edge with forgotten node")
298
- ctx.kobj_queue.put_kobj(rid=edge_rid, event_type=EventType.FORGET)
298
+ log.debug("Identified edge with forgotten node")
299
+ ctx.kobj_queue.push(rid=edge_rid, event_type=EventType.FORGET)
@@ -1,8 +1,7 @@
1
1
  from pydantic import BaseModel
2
2
  from rid_lib import RID
3
- from rid_lib.ext import Manifest
4
- from rid_lib.ext.bundle import Bundle
5
- from rid_lib.types.koi_net_node import KoiNetNode
3
+ from rid_lib.ext import Manifest, Bundle
4
+ from rid_lib.types import KoiNetNode
6
5
  from ..protocol.event import Event, EventType
7
6
 
8
7