Live video on the AT Protocol

iroh replicator: extremely rough PoC

+78 -14
+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" 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" 5 "fmt" 6 "sync" 7 ··· 50 } 51 52 func (d *Director) Start(ctx context.Context) error { 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)) 95 if err != nil { 96 log.Error(ctx, "could not put segment to swarm", "error", err) 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" 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 16 } 17 18 func StartKV(ctx context.Context, tickets []string, secret []byte) (*SwarmKV, error) { 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 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()) 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) 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) 144 }