forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

spindle: ingest repo records in spindle

allows the spindle to dynamically configure the knots it is listening
to.

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li b2147be9 ad34da2a

verified
Changed files
+90 -2
spindle
+10
spindle/db/db.go
···
did text primary key
);
+
create table if not exists repos (
+
id integer primary key autoincrement,
+
knot text not null,
+
owner text not null,
+
name text not null,
+
addedAt text not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
+
+
unique(owner, name)
+
);
+
-- status event for a single workflow
create table if not exists events (
rkey text not null,
+28
spindle/db/repos.go
···
+
package db
+
+
func (d *DB) AddRepo(knot, owner, name string) error {
+
_, err := d.Exec(`insert or ignore into repos (knot, owner, name) values (?, ?, ?)`, knot, owner, name)
+
return err
+
}
+
+
func (d *DB) Knots() ([]string, error) {
+
rows, err := d.Query(`select knot from repos`)
+
if err != nil {
+
return nil, err
+
}
+
+
var knots []string
+
for rows.Next() {
+
var knot string
+
if err := rows.Scan(&knot); err != nil {
+
return nil, err
+
}
+
knots = append(knots, knot)
+
}
+
+
if err = rows.Err(); err != nil {
+
return nil, err
+
}
+
+
return knots, nil
+
}
+52 -2
spindle/ingester.go
···
"encoding/json"
"fmt"
-
"github.com/bluesky-social/jetstream/pkg/models"
"tangled.sh/tangled.sh/core/api/tangled"
+
"tangled.sh/tangled.sh/core/knotclient"
+
+
"github.com/bluesky-social/jetstream/pkg/models"
)
type Ingester func(ctx context.Context, e *models.Event) error
···
switch e.Commit.Collection {
case tangled.SpindleMemberNSID:
s.ingestMember(ctx, e)
+
case tangled.RepoNSID:
+
s.ingestRepo(ctx, e)
}
return err
···
return fmt.Errorf("failed to enforce permissions: %w", err)
}
-
if err := s.e.AddMember(rbacDomain, record.Subject); err != nil {
+
if err := s.e.AddKnotMember(rbacDomain, record.Subject); err != nil {
l.Error("failed to add member", "error", err)
return fmt.Errorf("failed to add member: %w", err)
}
···
}
return nil
}
+
+
func (s *Spindle) ingestRepo(_ context.Context, e *models.Event) error {
+
var err error
+
+
l := s.l.With("component", "ingester", "record", tangled.RepoNSID)
+
+
switch e.Commit.Operation {
+
case models.CommitOperationCreate, models.CommitOperationUpdate:
+
raw := e.Commit.Record
+
record := tangled.Repo{}
+
err = json.Unmarshal(raw, &record)
+
if err != nil {
+
l.Error("invalid record", "error", err)
+
return err
+
}
+
+
domain := s.cfg.Server.Hostname
+
if s.cfg.Server.Dev {
+
domain = s.cfg.Server.ListenAddr
+
}
+
+
// no spindle configured for this repo
+
if record.Spindle == nil {
+
return nil
+
}
+
+
// this repo did not want this spindle
+
if *record.Spindle != domain {
+
return nil
+
}
+
+
// add this repo to the watch list
+
if err := s.db.AddRepo(record.Knot, record.Owner, record.Name); err != nil {
+
l.Error("failed to add repo", "error", err)
+
return fmt.Errorf("failed to add repo: %w", err)
+
}
+
+
// add this knot to the event consumer
+
src := knotclient.NewEventSource(record.Knot)
+
s.ks.AddSource(context.Background(), src)
+
+
return nil
+
+
}
+
return nil
+
}