tangled
alpha
login
or
join now
stream.place
/
streamplace
Live video on the AT Protocol
74
fork
atom
overview
issues
1
pulls
pipelines
iroh replicator: extremely rough PoC
Eli Mallon
4 months ago
3e9693dc
53530d48
+78
-14
3 changed files
expand all
collapse all
unified
split
pkg
cmd
streamplace.go
director
director.go
replication
iroh_replicator
kv.go
+1
-3
pkg/cmd/streamplace.go
···
32
"stream.place/streamplace/pkg/log"
33
"stream.place/streamplace/pkg/media"
34
"stream.place/streamplace/pkg/notifications"
35
-
"stream.place/streamplace/pkg/replication"
36
-
"stream.place/streamplace/pkg/replication/boring"
37
"stream.place/streamplace/pkg/replication/iroh_replicator"
38
"stream.place/streamplace/pkg/rtmps"
39
v0 "stream.place/streamplace/pkg/schema/v0"
···
307
log.Log(ctx, "successfully initialized hardware signer", "address", addr)
308
signer = hwsigner
309
}
310
-
var rep replication.Replicator = &boring.BoringReplicator{Peers: cli.Peers}
311
312
mod, err := model.MakeDB(cli.DataFilePath([]string{"index"}))
313
if err != nil {
···
32
"stream.place/streamplace/pkg/log"
33
"stream.place/streamplace/pkg/media"
34
"stream.place/streamplace/pkg/notifications"
0
0
35
"stream.place/streamplace/pkg/replication/iroh_replicator"
36
"stream.place/streamplace/pkg/rtmps"
37
v0 "stream.place/streamplace/pkg/schema/v0"
···
305
log.Log(ctx, "successfully initialized hardware signer", "address", addr)
306
signer = hwsigner
307
}
308
+
// var rep replication.Replicator = &boring.BoringReplicator{Peers: cli.Peers}
309
310
mod, err := model.MakeDB(cli.DataFilePath([]string{"index"}))
311
if err != nil {
+22
-1
pkg/director/director.go
···
2
3
import (
4
"context"
0
5
"fmt"
6
"sync"
7
···
50
}
51
52
func (d *Director) Start(ctx context.Context) error {
0
0
0
0
0
53
newSeg := d.mm.NewSegment()
54
ctx, cancel := context.WithCancel(ctx)
55
defer cancel()
···
91
}
92
d.streamSessionsMu.Unlock()
93
go func() {
94
-
err := d.swarm.Put(ctx, not.Segment.RepoDID, not.Segment.StartTime.Format(util.ISO8601))
0
0
0
0
0
0
0
0
0
95
if err != nil {
96
log.Error(ctx, "could not put segment to swarm", "error", err)
0
0
0
0
0
0
97
}
98
}()
99
err := ss.NewSegment(ctx, not)
···
2
3
import (
4
"context"
5
+
"encoding/json"
6
"fmt"
7
"sync"
8
···
51
}
52
53
func (d *Director) Start(ctx context.Context) error {
54
+
nodeId, err := d.swarm.Node.NodeId()
55
+
if err != nil {
56
+
return fmt.Errorf("failed to get node id: %w", err)
57
+
}
58
+
59
newSeg := d.mm.NewSegment()
60
ctx, cancel := context.WithCancel(ctx)
61
defer cancel()
···
97
}
98
d.streamSessionsMu.Unlock()
99
go func() {
100
+
originInfo := iroh_replicator.OriginInfo{
101
+
NodeID: nodeId.String(),
102
+
Time: not.Segment.StartTime.Format(util.ISO8601),
103
+
}
104
+
bs, err := json.Marshal(originInfo)
105
+
if err != nil {
106
+
log.Error(ctx, "could not marshal origin info", "error", err)
107
+
return
108
+
}
109
+
err = d.swarm.Put(ctx, not.Segment.RepoDID, bs)
110
if err != nil {
111
log.Error(ctx, "could not put segment to swarm", "error", err)
112
+
return
113
+
}
114
+
err = d.swarm.Node.SendSegment(not.Segment.RepoDID, not.Data)
115
+
if err != nil {
116
+
log.Error(ctx, "could not send segment to swarm", "error", err)
117
+
return
118
}
119
}()
120
err := ss.NewSegment(ctx, not)
+55
-10
pkg/replication/iroh_replicator/kv.go
···
2
3
import (
4
"context"
0
5
"fmt"
6
"time"
7
···
10
)
11
12
type SwarmKV struct {
13
-
node *iroh_streamplace.Node
14
-
db *iroh_streamplace.Db
15
w *iroh_streamplace.WriteScope
0
0
0
0
0
0
0
0
0
0
0
0
16
}
17
18
func StartKV(ctx context.Context, tickets []string, secret []byte) (*SwarmKV, error) {
0
19
ctx = log.WithLogValues(ctx, "func", "StartKV")
20
21
log.Log(ctx, "Starting with tickets", "tickets", tickets)
···
25
MaxSendDuration: 1000_000_000, // 1s
26
}
27
log.Log(ctx, "Config created", "config", config)
28
-
node, err := iroh_streamplace.NodeSender(config)
29
if err != nil {
30
return nil, fmt.Errorf("failed to create NodeSender: %w", err)
31
}
···
46
log.Log(ctx, "Ticket:", "ticket", ticket)
47
48
swarm := SwarmKV{
49
-
node: node,
50
-
db: db,
51
w: w,
52
}
53
return &swarm, nil
54
}
55
0
0
56
func (swarm *SwarmKV) Start(ctx context.Context, tickets []string) error {
57
if len(tickets) > 0 {
58
-
err := swarm.node.JoinPeers(tickets)
59
if err != nil {
60
return fmt.Errorf("failed to join peers: %w", err)
61
}
62
}
63
64
-
sub := swarm.db.Subscribe(iroh_streamplace.NewFilter())
0
0
0
0
0
0
0
65
for {
66
if ctx.Err() != nil {
67
return ctx.Err()
···
80
keyStr := string(item.Key)
81
valueStr := string(item.Value)
82
log.Log(ctx, "SubscribeItemEntry", "key", keyStr, "value", valueStr)
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
83
84
case iroh_streamplace.SubscribeItemCurrentDone:
85
log.Log(ctx, "SubscribeItemCurrentDone", "currentDone", item)
···
91
}
92
}
93
94
-
func (swarm *SwarmKV) Put(ctx context.Context, key, value string) error {
95
// streamerBs := []byte(streamer)
96
keyBs := []byte(key)
97
-
valueBs := []byte(value)
98
-
return swarm.w.Put(nil, keyBs, valueBs)
99
}
···
2
3
import (
4
"context"
5
+
"encoding/json"
6
"fmt"
7
"time"
8
···
11
)
12
13
type SwarmKV struct {
14
+
Node *iroh_streamplace.Node
15
+
DB *iroh_streamplace.Db
16
w *iroh_streamplace.WriteScope
17
+
}
18
+
19
+
// A message saying "hey I ingested node data at this time"
20
+
type OriginInfo struct {
21
+
NodeID string `json:"node_id"`
22
+
Time string `json:"time"`
23
+
}
24
+
25
+
type DataHandler struct{}
26
+
27
+
func (handler *DataHandler) HandleData(topic string, data []byte) {
28
+
log.Log(context.Background(), "HandleData", "topic", topic, "data", len(data))
29
}
30
31
func StartKV(ctx context.Context, tickets []string, secret []byte) (*SwarmKV, error) {
32
+
handler := &DataHandler{}
33
ctx = log.WithLogValues(ctx, "func", "StartKV")
34
35
log.Log(ctx, "Starting with tickets", "tickets", tickets)
···
39
MaxSendDuration: 1000_000_000, // 1s
40
}
41
log.Log(ctx, "Config created", "config", config)
42
+
node, err := iroh_streamplace.NodeReceiver(config, handler)
43
if err != nil {
44
return nil, fmt.Errorf("failed to create NodeSender: %w", err)
45
}
···
60
log.Log(ctx, "Ticket:", "ticket", ticket)
61
62
swarm := SwarmKV{
63
+
Node: node,
64
+
DB: db,
65
w: w,
66
}
67
return &swarm, nil
68
}
69
70
+
var activeSubs = make(map[string]bool)
71
+
72
func (swarm *SwarmKV) Start(ctx context.Context, tickets []string) error {
73
if len(tickets) > 0 {
74
+
err := swarm.Node.JoinPeers(tickets)
75
if err != nil {
76
return fmt.Errorf("failed to join peers: %w", err)
77
}
78
}
79
80
+
nodeId, err := swarm.Node.NodeId()
81
+
if err != nil {
82
+
return fmt.Errorf("failed to get node id: %w", err)
83
+
}
84
+
nodeIdStr := nodeId.String()
85
+
log.Log(ctx, "Node ID:", "node_id", nodeIdStr)
86
+
87
+
sub := swarm.DB.Subscribe(iroh_streamplace.NewFilter())
88
for {
89
if ctx.Err() != nil {
90
return ctx.Err()
···
103
keyStr := string(item.Key)
104
valueStr := string(item.Value)
105
log.Log(ctx, "SubscribeItemEntry", "key", keyStr, "value", valueStr)
106
+
var info OriginInfo
107
+
err := json.Unmarshal(item.Value, &info)
108
+
if err != nil {
109
+
log.Error(ctx, "could not unmarshal origin info", "error", err)
110
+
continue
111
+
}
112
+
if !activeSubs[keyStr] {
113
+
if info.NodeID == nodeIdStr {
114
+
activeSubs[keyStr] = true
115
+
continue
116
+
}
117
+
pubKey, err := iroh_streamplace.PublicKeyFromString(info.NodeID)
118
+
if err != nil {
119
+
log.Error(ctx, "could not create public key", "error", err)
120
+
continue
121
+
}
122
+
activeSubs[keyStr] = true
123
+
err = swarm.Node.Subscribe(keyStr, pubKey)
124
+
if err != nil {
125
+
log.Error(ctx, "could not subscribe to key", "error", err)
126
+
continue
127
+
}
128
+
}
129
130
case iroh_streamplace.SubscribeItemCurrentDone:
131
log.Log(ctx, "SubscribeItemCurrentDone", "currentDone", item)
···
137
}
138
}
139
140
+
func (swarm *SwarmKV) Put(ctx context.Context, key string, value []byte) error {
141
// streamerBs := []byte(streamer)
142
keyBs := []byte(key)
143
+
return swarm.w.Put(nil, keyBs, value)
0
144
}