Skip to content

Commit 804402a

Browse files
authored
Merge pull request #21 from BlockScience/dev
v1.2.0
2 parents 7a22b73 + e1eb4f7 commit 804402a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+2811
-1746
lines changed

.gitignore

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
rid-lib
22
__pycache__
3-
*.json
43
*.pem
54
*.yaml
5+
*.ndjson*
66
venv
77
.env
88
prototypes
99
.vscode
1010
dist/
1111
docs/
12-
*.ndjson
12+
tests/
13+
.rid_cache/
14+
*.ndjson

examples/coordinator.py

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,53 @@
1-
import logging
2-
from rich.logging import RichHandler
3-
from pydantic import Field
41
from rid_lib.types import KoiNetNode, KoiNetEdge
5-
from koi_net.config import NodeConfig, KoiNetConfig
6-
from koi_net.protocol.node import NodeProfile, NodeProvides, NodeType
7-
from koi_net import NodeInterface
8-
from koi_net.context import HandlerContext
9-
from koi_net.processor.handler import HandlerType
2+
import structlog
3+
from koi_net.config.full_node import (
4+
FullNodeConfig,
5+
ServerConfig,
6+
KoiNetConfig,
7+
NodeProfile,
8+
NodeProvides
9+
)
10+
from koi_net.core import FullNode
11+
from koi_net.processor.context import HandlerContext
12+
from koi_net.processor.handler import HandlerType, KnowledgeHandler
1013
from koi_net.processor.knowledge_object import KnowledgeObject
1114
from koi_net.protocol.event import Event, EventType
1215
from koi_net.protocol.edge import EdgeType, generate_edge_bundle
1316

14-
logging.basicConfig(
15-
level=logging.INFO,
16-
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
17-
datefmt="%Y-%m-%d %H:%M:%S",
18-
handlers=[RichHandler()]
19-
)
17+
log = structlog.stdlib.get_logger()
2018

21-
logging.getLogger("koi_net").setLevel(logging.DEBUG)
22-
logger = logging.getLogger(__name__)
2319

24-
class CoordinatorConfig(NodeConfig):
25-
koi_net: KoiNetConfig = Field(default_factory = lambda:
26-
KoiNetConfig(
27-
node_name="coordinator",
28-
node_profile=NodeProfile(
29-
node_type=NodeType.FULL,
30-
provides=NodeProvides(
31-
event=[KoiNetNode, KoiNetEdge],
32-
state=[KoiNetNode, KoiNetEdge]
33-
)
34-
),
35-
cache_directory_path=".coordinator_rid_cache",
36-
event_queues_path="coordinator_event_queues.json",
37-
private_key_pem_path="coordinator_priv_key.pem"
38-
)
20+
class CoordinatorConfig(FullNodeConfig):
21+
server: ServerConfig = ServerConfig(port=8080)
22+
koi_net: KoiNetConfig = KoiNetConfig(
23+
node_name="coordinator",
24+
node_profile=NodeProfile(
25+
provides=NodeProvides(
26+
event=[KoiNetNode, KoiNetEdge],
27+
state=[KoiNetNode, KoiNetEdge]
28+
)
29+
),
30+
rid_types_of_interest=[KoiNetNode, KoiNetEdge]
3931
)
40-
41-
node = NodeInterface(
42-
config=CoordinatorConfig.load_from_yaml("coordinator_config.yaml"),
43-
use_kobj_processor_thread=True
44-
)
4532

46-
@node.processor.pipeline.register_handler(HandlerType.Network, rid_types=[KoiNetNode])
33+
@KnowledgeHandler.create(
34+
HandlerType.Network,
35+
rid_types=[KoiNetNode])
4736
def handshake_handler(ctx: HandlerContext, kobj: KnowledgeObject):
48-
logger.info("Handling node handshake")
37+
log.info("Handling node handshake")
4938

5039
# only respond if node declares itself as NEW
5140
if kobj.event_type != EventType.NEW:
5241
return
5342

54-
logger.info("Sharing this node's bundle with peer")
55-
identity_bundle = ctx.effector.deref(ctx.identity.rid)
56-
ctx.event_queue.push_event_to(
43+
log.info("Sharing this node's bundle with peer")
44+
identity_bundle = ctx.cache.read(ctx.identity.rid)
45+
ctx.event_queue.push(
5746
event=Event.from_bundle(EventType.NEW, identity_bundle),
58-
node=kobj.rid,
59-
flush=True
47+
target=kobj.rid
6048
)
6149

62-
logger.info("Proposing new edge")
50+
log.info("Proposing new edge")
6351
# defer handling of proposed edge
6452

6553
edge_bundle = generate_edge_bundle(
@@ -69,8 +57,12 @@ def handshake_handler(ctx: HandlerContext, kobj: KnowledgeObject):
6957
rid_types=[KoiNetNode, KoiNetEdge]
7058
)
7159

72-
ctx.handle(rid=edge_bundle.rid, event_type=EventType.FORGET)
73-
ctx.handle(bundle=edge_bundle)
74-
60+
ctx.kobj_queue.push(rid=edge_bundle.rid, event_type=EventType.FORGET)
61+
ctx.kobj_queue.push(bundle=edge_bundle)
62+
63+
class CoordinatorNode(FullNode):
64+
config_schema = CoordinatorConfig
65+
knowledge_handlers = FullNode.knowledge_handlers + [handshake_handler]
66+
7567
if __name__ == "__main__":
76-
node.server.run()
68+
CoordinatorNode().run()

examples/partial.py

Lines changed: 9 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,15 @@
1-
import logging
2-
from pydantic import Field
3-
from rich.logging import RichHandler
4-
from koi_net import NodeInterface
5-
from koi_net.protocol.node import NodeProfile, NodeType
6-
from koi_net.config import NodeConfig, KoiNetConfig
1+
from koi_net.config.partial_node import PartialNodeConfig, KoiNetConfig, NodeProfile
2+
from koi_net.core import PartialNode
73

8-
logging.basicConfig(
9-
level=logging.INFO,
10-
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
11-
datefmt="%Y-%m-%d %H:%M:%S",
12-
handlers=[RichHandler()]
13-
)
144

15-
logging.getLogger("koi_net").setLevel(logging.DEBUG)
16-
logger = logging.getLogger(__name__)
17-
18-
19-
class PartialNodeConfig(NodeConfig):
20-
koi_net: KoiNetConfig = Field(default_factory = lambda:
21-
KoiNetConfig(
22-
node_name="partial",
23-
node_profile=NodeProfile(
24-
node_type=NodeType.PARTIAL
25-
),
26-
cache_directory_path=".partial_rid_cache",
27-
event_queues_path="partial_event_queues.json",
28-
private_key_pem_path="partial_priv_key.pem"
29-
)
5+
class MyPartialNodeConfig(PartialNodeConfig):
6+
koi_net: KoiNetConfig = KoiNetConfig(
7+
node_name="partial",
8+
node_profile=NodeProfile()
309
)
3110

32-
node = NodeInterface(
33-
config=PartialNodeConfig.load_from_yaml("partial_config.yaml")
34-
)
11+
class MyPartialNode(PartialNode):
12+
config_schema = MyPartialNodeConfig
3513

3614
if __name__ == "__main__":
37-
node.poller.run()
15+
MyPartialNode().run()

koi-net.config.json

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"$schema": "https://lnav.org/schemas/format-v1.schema.json",
3+
"koi_net_json_log": {
4+
"title": "KOI-net node logs",
5+
"description": "Detailed logs of node and network behavior",
6+
"file-type": "json",
7+
"body-field": "event",
8+
"level-field": "",
9+
"timestamp-field": "timestamp",
10+
"hide-extra": true,
11+
"line-format": [
12+
{
13+
"field": "timestamp",
14+
"auto-width": true,
15+
"timestamp-format": "%Y-%m-%d %H:%M:%S"
16+
},
17+
" ",
18+
{
19+
"field": "level",
20+
"auto-width": true,
21+
"prefix": "[",
22+
"suffix": "]"
23+
},
24+
" ",
25+
{
26+
"field": "module",
27+
"min-width": 15,
28+
"max-width": 15,
29+
"overflow": "dot-dot",
30+
"align": "right"
31+
},
32+
" - ",
33+
{
34+
"field": "event"
35+
}
36+
],
37+
"value": {
38+
"level": {
39+
"kind": "string"
40+
},
41+
"event": {
42+
"kind": "string"
43+
},
44+
"module": {
45+
"kind": "string"
46+
}
47+
},
48+
"highlights": {
49+
"debug": {
50+
"pattern": "\\[(debug) *\\]",
51+
"color": "Blue"
52+
},
53+
"info": {
54+
"pattern": "\\[(info) *\\]",
55+
"color": "Green"
56+
},
57+
"warning": {
58+
"pattern": "\\[(warning) *\\]",
59+
"color": "Yellow"
60+
},
61+
"error": {
62+
"pattern": "\\[(error|critical) *\\]",
63+
"color": "Red"
64+
},
65+
"timestamp": {
66+
"pattern": "(\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2})",
67+
"color": "Grey"
68+
},
69+
"obj_name": {
70+
"pattern": "<([a-zA-Z.]+)",
71+
"color": "Purple"
72+
},
73+
"quotations": {
74+
"pattern": "(['\"][^']*['\"])",
75+
"color": "Green"
76+
}
77+
}
78+
}
79+
}

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "koi-net"
7-
version = "1.1.0"
7+
version = "1.2.0"
88
description = "Implementation of KOI-net protocol in Python"
99
authors = [
1010
{name = "Luke Miller", email = "[email protected]"}
@@ -23,6 +23,7 @@ dependencies = [
2323
"fastapi>=0.115.12",
2424
"uvicorn>=0.34.2",
2525
"rich>=14.1.0",
26+
"structlog>=25.4.0",
2627
]
2728

2829
[project.optional-dependencies]

requirements.txt

Lines changed: 0 additions & 9 deletions
This file was deleted.

schemas/bundle.schema.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"title": "Bundle",
3+
"type": "object",
4+
"properties": {
5+
"manifest": {
6+
"$ref": "./manifest.schema.json"
7+
},
8+
"contents": {
9+
"type": "object"
10+
}
11+
},
12+
"required": [
13+
"manifest",
14+
"contents"
15+
]
16+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"title": "Bundles Payload",
3+
"type": "object",
4+
"properties": {
5+
"type": {
6+
"type": "string",
7+
"const": "bundles_payload"
8+
},
9+
"bundles": {
10+
"type": "array",
11+
"items": {
12+
"$ref": "./bundle.schema.json"
13+
}
14+
},
15+
"not_found": {
16+
"type": "array",
17+
"items": {
18+
"type": "string"
19+
}
20+
},
21+
"deferred": {
22+
"type": "array",
23+
"items": {
24+
"type": "string"
25+
}
26+
}
27+
},
28+
"required": [
29+
"type",
30+
"bundles"
31+
]
32+
}

schemas/edge_profile.schema.json

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"$defs": {
3+
"EdgeStatus": {
4+
"title": "Edge Status",
5+
"type": "string",
6+
"enum": [
7+
"PROPOSED",
8+
"APPROVED"
9+
]
10+
},
11+
"EdgeType": {
12+
"title": "Edge Type",
13+
"type": "string",
14+
"enum": [
15+
"WEBHOOK",
16+
"POLL"
17+
]
18+
}
19+
},
20+
"title": "Edge Profile",
21+
"type": "object",
22+
"properties": {
23+
"source": {
24+
"type": "string"
25+
},
26+
"target": {
27+
"type": "string"
28+
},
29+
"edge_type": {
30+
"$ref": "#/$defs/EdgeType"
31+
},
32+
"status": {
33+
"$ref": "#/$defs/EdgeStatus"
34+
},
35+
"rid_types": {
36+
"type": "array",
37+
"items": {
38+
"type": "string"
39+
}
40+
}
41+
},
42+
"required": [
43+
"source",
44+
"target",
45+
"edge_type",
46+
"status",
47+
"rid_types"
48+
]
49+
}

0 commit comments

Comments
 (0)