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

@@ -11,7 +11,8 @@ from ..protocol.event import Event, EventType
11
11
  from .handler import (
12
12
  KnowledgeHandler,
13
13
  HandlerType,
14
- STOP_CHAIN
14
+ STOP_CHAIN,
15
+ StopChain
15
16
  )
16
17
  from .knowledge_object import (
17
18
  KnowledgeObject,
@@ -23,6 +24,8 @@ logger = logging.getLogger(__name__)
23
24
 
24
25
 
25
26
  class ProcessorInterface:
27
+ """Provides access to this node's knowledge processing pipeline."""
28
+
26
29
  cache: Cache
27
30
  network: NetworkInterface
28
31
  identity: NodeIdentity
@@ -41,28 +44,19 @@ class ProcessorInterface:
41
44
  self.identity = identity
42
45
  self.handlers: list[KnowledgeHandler] = default_handlers
43
46
  self.kobj_queue = Queue()
44
-
45
- @classmethod
46
- def as_handler(
47
- cls,
48
- handler_type: HandlerType,
49
- rid_types: list[RIDType] | None = None
50
- ):
51
- """Special decorator that returns a Handler instead of a function."""
52
- def decorator(func: Callable) -> KnowledgeHandler:
53
- handler = KnowledgeHandler(func, handler_type, rid_types, )
54
- return handler
55
- return decorator
47
+
48
+ def add_handler(self, handler: KnowledgeHandler):
49
+ self.handlers.append(handler)
56
50
 
57
51
  def register_handler(
58
52
  self,
59
53
  handler_type: HandlerType,
60
54
  rid_types: list[RIDType] | None = None
61
55
  ):
62
- """Assigns decorated function as handler for this Processor."""
56
+ """Assigns decorated function as handler for this processor."""
63
57
  def decorator(func: Callable) -> Callable:
64
58
  handler = KnowledgeHandler(func, handler_type, rid_types)
65
- self.handlers.append(handler)
59
+ self.add_handler(handler)
66
60
  return func
67
61
  return decorator
68
62
 
@@ -70,7 +64,17 @@ class ProcessorInterface:
70
64
  self,
71
65
  handler_type: HandlerType,
72
66
  kobj: KnowledgeObject
73
- ):
67
+ ) -> KnowledgeObject | StopChain:
68
+ """Calls handlers of provided type, chaining their inputs and outputs together.
69
+
70
+ The knowledge object provided when this function is called will be passed to the first handler. A handler may return one of three types:
71
+ - `KnowledgeObject` - to modify the knowledge object for the next handler in the chain
72
+ - `None` - to keep the same knowledge object for the next handler in the chain
73
+ - `STOP_CHAIN` - to stop the handler chain and immediately exit the processing pipeline
74
+
75
+ Handlers will only be called in the chain if their handler and RID type match that of the inputted knowledge object.
76
+ """
77
+
74
78
  for handler in self.handlers:
75
79
  if handler_type != handler.handler_type:
76
80
  continue
@@ -98,7 +102,19 @@ class ProcessorInterface:
98
102
  return kobj
99
103
 
100
104
 
101
- def handle_kobj(self, kobj: KnowledgeObject):
105
+ def process_kobj(self, kobj: KnowledgeObject) -> None:
106
+ """Sends provided knowledge obejct through knowledge processing pipeline.
107
+
108
+ Handler chains are called in between major events in the pipeline, indicated by their handler type. Each handler type is guaranteed to have access to certain knowledge, and may affect a subsequent action in the pipeline. The five handler types are as follows:
109
+ - RID - provided RID; if event type is `FORGET`, this handler decides whether to delete the knowledge from the cache by setting the normalized event type to `FORGET`, otherwise this handler decides whether to validate the manifest (and fetch it if not provided).
110
+ - Manifest - provided RID, manifest; decides whether to validate the bundle (and fetch it if not provided).
111
+ - Bundle - provided RID, manifest, contents (bundle); decides whether to write knowledge to the cache by setting the normalized event type to `NEW` or `UPDATE`.
112
+ - Network - provided RID, manifest, contents (bundle); decides which nodes (if any) to broadcast an event about this knowledge to. (Note, if event type is `FORGET`, the manifest and contents will be retrieved from the local cache, and indicate the last state of the knowledge before it was deleted.)
113
+ - Final - provided RID, manifests, contents (bundle); final action taken after network broadcast.
114
+
115
+ The pipeline may be stopped by any point by a single handler returning the `STOP_CHAIN` sentinel. In that case, the process will exit immediately. Further handlers of that type and later handler chains will not be called.
116
+ """
117
+
102
118
  logger.info(f"Handling {kobj!r}")
103
119
  kobj = self.call_handler_chain(HandlerType.RID, kobj)
104
120
  if kobj is STOP_CHAIN: return
@@ -183,19 +199,13 @@ class ProcessorInterface:
183
199
  self.network.flush_all_webhook_queues()
184
200
 
185
201
  kobj = self.call_handler_chain(HandlerType.Final, kobj)
186
-
187
- def queue_kobj(self, kobj: KnowledgeObject, flush: bool = False):
188
- self.kobj_queue.put(kobj)
189
- logger.info(f"Queued {kobj!r}")
190
-
191
- if flush:
192
- self.flush_kobj_queue()
193
202
 
194
203
  def flush_kobj_queue(self):
204
+ """Flushes all knowledge objects from queue and processes them."""
195
205
  while not self.kobj_queue.empty():
196
206
  kobj = self.kobj_queue.get()
197
207
  logger.info(f"Dequeued {kobj!r}")
198
- self.handle_kobj(kobj)
208
+ self.process_kobj(kobj)
199
209
  logger.info("Done handling")
200
210
 
201
211
  def handle(
@@ -204,19 +214,30 @@ class ProcessorInterface:
204
214
  manifest: Manifest | None = None,
205
215
  bundle: Bundle | None = None,
206
216
  event: Event | None = None,
217
+ kobj: KnowledgeObject | None = None,
207
218
  event_type: KnowledgeEventType = None,
208
219
  source: KnowledgeSource = KnowledgeSource.Internal,
209
220
  flush: bool = False
210
221
  ):
222
+ """Queues provided knowledge to be handled by processing pipeline.
223
+
224
+ Knowledge may take the form of an RID, manifest, bundle, event, or knowledge object (with an optional event type for RID, manifest, or bundle objects). All objects will be normalized into knowledge objects and queued. If `flush` is `True`, the queue will be flushed immediately after adding the new knowledge.
225
+ """
211
226
  if rid:
212
- kobj = KnowledgeObject.from_rid(rid, event_type, source)
227
+ _kobj = KnowledgeObject.from_rid(rid, event_type, source)
213
228
  elif manifest:
214
- kobj = KnowledgeObject.from_manifest(manifest, event_type, source)
229
+ _kobj = KnowledgeObject.from_manifest(manifest, event_type, source)
215
230
  elif bundle:
216
- kobj = KnowledgeObject.from_bundle(bundle, event_type, source)
231
+ _kobj = KnowledgeObject.from_bundle(bundle, event_type, source)
217
232
  elif event:
218
- kobj = KnowledgeObject.from_event(event, source)
233
+ _kobj = KnowledgeObject.from_event(event, source)
234
+ elif _kobj:
235
+ _kobj = kobj
219
236
  else:
220
- raise ValueError("One of 'rid', 'manifest', 'bundle', or 'event' must be provided")
221
-
222
- self.queue_kobj(kobj, flush)
237
+ raise ValueError("One of 'rid', 'manifest', 'bundle', 'event', or 'kobj' must be provided")
238
+
239
+ self.kobj_queue.put(kobj)
240
+ logger.info(f"Queued {kobj!r}")
241
+
242
+ if flush:
243
+ self.flush_kobj_queue()
@@ -14,6 +14,18 @@ class KnowledgeSource(StrEnum):
14
14
  External = "EXTERNAL"
15
15
 
16
16
  class KnowledgeObject(BaseModel):
17
+ """A normalized knowledge representation for internal processing.
18
+
19
+ Capable of representing an RID, manifest, bundle, or event. Contains three additional fields use for decision making in the knowledge processing pipeline.
20
+
21
+ The source indicates whether this object was generated by this node, or sourced from another node in the network.
22
+
23
+ The normalized event type indicates how the knowledge object is viewed from the perspective of this node, and what cache actions will take place. `NEW`, `UPDATE` -> cache write, `FORGET` -> cache delete, `None` -> no cache action.
24
+
25
+ The network targets indicate other nodes in the network this knowledge object will be sent to. The event sent to them will be constructed from this knowledge object's RID, manifest, contents, and normalized event type.
26
+
27
+ Constructors are provided to create a knowledge object from an RID, manifest, bundle, or event.
28
+ """
17
29
  rid: RID
18
30
  manifest: Manifest | None = None
19
31
  contents: dict | None = None
@@ -93,12 +105,19 @@ class KnowledgeObject(BaseModel):
93
105
 
94
106
  @property
95
107
  def normalized_event(self):
96
- if not self.normalized_event_type:
108
+ if self.normalized_event_type is None:
97
109
  raise ValueError("Internal event's normalized event type is None, cannot convert to Event")
98
110
 
99
- return Event(
100
- rid=self.rid,
101
- event_type=self.normalized_event_type,
102
- manifest=self.manifest,
103
- contents=self.contents
104
- )
111
+ elif self.normalized_event_type == EventType.FORGET:
112
+ return Event(
113
+ rid=self.rid,
114
+ event_type=EventType.FORGET
115
+ )
116
+
117
+ else:
118
+ return Event(
119
+ rid=self.rid,
120
+ event_type=self.normalized_event_type,
121
+ manifest=self.manifest,
122
+ contents=self.contents
123
+ )
@@ -1,3 +1,5 @@
1
+ """Pydantic models for request and response/payload objects in the KOI-net API."""
2
+
1
3
  from pydantic import BaseModel
2
4
  from rid_lib import RID, RIDType
3
5
  from rid_lib.ext import Bundle, Manifest
@@ -36,4 +38,10 @@ class BundlesPayload(BaseModel):
36
38
  deferred: list[RID] = []
37
39
 
38
40
  class EventsPayload(BaseModel):
39
- events: list[Event]
41
+ events: list[Event]
42
+
43
+
44
+ # TYPES
45
+
46
+ type RequestModels = EventsPayload | PollEvents | FetchRids | FetchManifests | FetchBundles
47
+ type ResponseModels = RidsPayload | ManifestsPayload | BundlesPayload | EventsPayload
@@ -1,3 +1,5 @@
1
+ """API paths for KOI-net protocol."""
2
+
1
3
  BROADCAST_EVENTS_PATH = "/events/broadcast"
2
4
  POLL_EVENTS_PATH = "/events/poll"
3
5
  FETCH_RIDS_PATH = "/rids/fetch"