···4444 last_time_us integer not null
4545 );
46464747- create table if not exists oplog (
4848- tid text primary key,
4949- did text not null,
5050- repo text not null,
5151- old_sha text not null,
5252- new_sha text not null,
5353- ref text not null
4747+ create table if not exists events (
4848+ rkey text not null,
4949+ nsid text not null,
5050+ event text not null, -- json
5151+ primary key (rkey, nsid)
5452 );
5553 `)
5654 if err != nil {
-70
knotserver/db/oplog.go
···11-package db
22-33-import (
44- "fmt"
55-66- "tangled.sh/tangled.sh/core/knotserver/notifier"
77-)
88-99-type Op struct {
1010- Tid string // time based ID, easy to enumerate & monotonic
1111- Did string // did of pusher
1212- Repo string // <did/repo> fully qualified repo
1313- OldSha string // old sha of reference being updated
1414- NewSha string // new sha of reference being updated
1515- Ref string // the reference being updated
1616-}
1717-1818-func (d *DB) InsertOp(op Op, notifier *notifier.Notifier) error {
1919- _, err := d.db.Exec(
2020- `insert into oplog (tid, did, repo, old_sha, new_sha, ref) values (?, ?, ?, ?, ?, ?)`,
2121- op.Tid,
2222- op.Did,
2323- op.Repo,
2424- op.OldSha,
2525- op.NewSha,
2626- op.Ref,
2727- )
2828- if err != nil {
2929- return err
3030- }
3131-3232- notifier.NotifyAll()
3333- return nil
3434-}
3535-3636-func (d *DB) GetOps(cursor string) ([]Op, error) {
3737- whereClause := ""
3838- args := []any{}
3939- if cursor != "" {
4040- whereClause = "where tid > ?"
4141- args = append(args, cursor)
4242- }
4343-4444- query := fmt.Sprintf(`
4545- select tid, did, repo, old_sha, new_sha, ref
4646- from oplog
4747- %s
4848- order by tid asc
4949- limit 100
5050- `, whereClause)
5151-5252- rows, err := d.db.Query(query, args...)
5353- if err != nil {
5454- return nil, err
5555- }
5656- defer rows.Close()
5757-5858- var ops []Op
5959- for rows.Next() {
6060- var op Op
6161- rows.Scan(&op.Tid, &op.Did, &op.Repo, &op.OldSha, &op.NewSha, &op.Ref)
6262- ops = append(ops, op)
6363- }
6464-6565- if err := rows.Err(); err != nil {
6666- return nil, err
6767- }
6868-6969- return ops, nil
7070-}
+26-7
knotserver/events.go
···2233import (
44 "context"
55+ "encoding/json"
56 "net/http"
67 "time"
78···1314 WriteBufferSize: 1024,
1415}
15161616-func (h *Handle) OpLog(w http.ResponseWriter, r *http.Request) {
1717+func (h *Handle) Events(w http.ResponseWriter, r *http.Request) {
1718 l := h.l.With("handler", "OpLog")
1819 l.Info("received new connection")
1920···7475}
75767677func (h *Handle) streamOps(conn *websocket.Conn, cursor *string) error {
7777- ops, err := h.db.GetOps(*cursor)
7878+ events, err := h.db.GetEvents(*cursor)
7879 if err != nil {
7979- h.l.Debug("err", "err", err)
8080+ h.l.Error("failed to fetch events from db", "err", err, "cursor", cursor)
8081 return err
8182 }
8282- h.l.Debug("ops", "ops", ops)
8383+ h.l.Debug("ops", "ops", events)
83848484- for _, op := range ops {
8585- if err := conn.WriteJSON(op); err != nil {
8585+ for _, event := range events {
8686+ // first extract the inner json into a map
8787+ var eventJson map[string]any
8888+ err := json.Unmarshal([]byte(event.EventJson), &eventJson)
8989+ if err != nil {
9090+ h.l.Error("failed to unmarshal event", "err", err)
9191+ return err
9292+ }
9393+9494+ jsonMsg, err := json.Marshal(map[string]any{
9595+ "rkey": event.Rkey,
9696+ "nsid": event.Nsid,
9797+ "event": eventJson,
9898+ })
9999+ if err != nil {
100100+ h.l.Error("failed to marshal record", "err", err)
101101+ return err
102102+ }
103103+104104+ if err := conn.WriteMessage(websocket.TextMessage, jsonMsg); err != nil {
86105 h.l.Debug("err", "err", err)
87106 return err
88107 }
8989- *cursor = op.Tid
108108+ *cursor = event.Rkey
90109 }
9111092111 return nil
+1-1
knotserver/handler.go
···149149 })
150150151151 // Socket that streams git oplogs
152152- r.Get("/oplog", h.OpLog)
152152+ r.Get("/events", h.Events)
153153154154 // Initialize the knot with an owner and public key.
155155 r.With(h.VerifySignature).Post("/init", h.Init)