forked from tangled.org/core
this repo has no description

spindle/{db,engine}: rework db to use rkey

Signed-off-by: Anirudh Oppiliappan <anirudh@tangled.sh>

anirudh.fi d643cad8 55bf8204

verified
Changed files
+86 -63
spindle
+1
spindle/config/config.go
···
DBPath string `env:"DB_PATH, default=spindle.db"`
Hostname string `env:"HOSTNAME, required"`
JetstreamEndpoint string `env:"JETSTREAM_ENDPOINT, default=wss://jetstream1.us-west.bsky.network/subscribe"`
+
Dev bool `env:"DEV, default=false"`
}
type Config struct {
+4 -3
spindle/db/db.go
···
did text primary key
);
-
create table if not exists pipelines (
-
at_uri text not null,
+
create table if not exists pipeline_status (
+
rkey text not null,
+
pipeline text not null,
status text not null,
-- only set if status is 'failed'
···
updated_at timestamp not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
finished_at timestamp,
-
primary key (at_uri)
+
primary key (rkey)
);
`)
if err != nil {
+48 -42
spindle/db/pipelines.go
···
"tangled.sh/tangled.sh/core/knotserver/notifier"
)
-
type PipelineStatus string
+
type PipelineRunStatus string
var (
-
PipelinePending PipelineStatus = "pending"
-
PipelineRunning PipelineStatus = "running"
-
PipelineFailed PipelineStatus = "failed"
-
PipelineTimeout PipelineStatus = "timeout"
-
PipelineCancelled PipelineStatus = "cancelled"
-
PipelineSuccess PipelineStatus = "success"
+
PipelinePending PipelineRunStatus = "pending"
+
PipelineRunning PipelineRunStatus = "running"
+
PipelineFailed PipelineRunStatus = "failed"
+
PipelineTimeout PipelineRunStatus = "timeout"
+
PipelineCancelled PipelineRunStatus = "cancelled"
+
PipelineSuccess PipelineRunStatus = "success"
)
-
type Pipeline struct {
-
Rkey string `json:"rkey"`
-
Knot string `json:"knot"`
-
Status PipelineStatus `json:"status"`
+
type PipelineStatus struct {
+
Rkey string `json:"rkey"`
+
Pipeline string `json:"pipeline"`
+
Status PipelineRunStatus `json:"status"`
// only if Failed
Error string `json:"error"`
···
FinishedAt time.Time `json:"finished_at"`
}
-
func (p Pipeline) AsRecord() *tangled.PipelineStatus {
+
func (p PipelineStatus) AsRecord() *tangled.PipelineStatus {
exitCode64 := int64(p.ExitCode)
finishedAt := p.FinishedAt.String()
return &tangled.PipelineStatus{
-
Pipeline: fmt.Sprintf("at://%s/%s", p.Knot, p.Rkey),
-
Status: string(p.Status),
+
LexiconTypeID: tangled.PipelineStatusNSID,
+
Pipeline: p.Pipeline,
+
Status: string(p.Status),
ExitCode: &exitCode64,
Error: &p.Error,
···
return fmt.Sprintf("at://%s/did:web:%s/%s", tangled.PipelineStatusNSID, knot, rkey)
}
-
func (db *DB) CreatePipeline(rkey, knot string, n *notifier.Notifier) error {
+
func (db *DB) CreatePipeline(rkey, pipeline string, n *notifier.Notifier) error {
_, err := db.Exec(`
-
insert into pipelines (at_uri, status)
-
values (?, ?)
-
`, pipelineAtUri(rkey, knot), PipelinePending)
+
insert into pipeline_status (rkey, status, pipeline)
+
values (?, ?, ?)
+
`, rkey, PipelinePending, pipeline)
if err != nil {
return err
···
return nil
}
-
func (db *DB) MarkPipelineRunning(rkey, knot string, n *notifier.Notifier) error {
+
func (db *DB) MarkPipelineRunning(rkey string, n *notifier.Notifier) error {
_, err := db.Exec(`
-
update pipelines
+
update pipeline_status
set status = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
-
where at_uri = ?
-
`, PipelineRunning, pipelineAtUri(rkey, knot))
+
where rkey = ?
+
`, PipelineRunning, rkey)
if err != nil {
return err
···
return nil
}
-
func (db *DB) MarkPipelineFailed(rkey, knot string, exitCode int, errorMsg string, n *notifier.Notifier) error {
+
func (db *DB) MarkPipelineFailed(rkey string, exitCode int, errorMsg string, n *notifier.Notifier) error {
_, err := db.Exec(`
-
update pipelines
+
update pipeline_status
set status = ?,
exit_code = ?,
error = ?,
updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
finished_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
-
where at_uri = ?
-
`, PipelineFailed, exitCode, errorMsg, pipelineAtUri(rkey, knot))
+
where rkey = ?
+
`, PipelineFailed, exitCode, errorMsg, rkey)
if err != nil {
return err
}
···
return nil
}
-
func (db *DB) MarkPipelineTimeout(rkey, knot string, n *notifier.Notifier) error {
+
func (db *DB) MarkPipelineTimeout(rkey string, n *notifier.Notifier) error {
_, err := db.Exec(`
-
update pipelines
+
update pipeline_status
set status = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
-
where at_uri = ?
-
`, PipelineTimeout, pipelineAtUri(rkey, knot))
+
where rkey = ?
+
`, PipelineTimeout, rkey)
if err != nil {
return err
}
···
return nil
}
-
func (db *DB) MarkPipelineSuccess(rkey, knot string, n *notifier.Notifier) error {
+
func (db *DB) MarkPipelineSuccess(rkey string, n *notifier.Notifier) error {
_, err := db.Exec(`
-
update pipelines
+
update pipeline_status
set status = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
finished_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
-
where at_uri = ?
-
`, PipelineSuccess, pipelineAtUri(rkey, knot))
+
where rkey = ?
+
`, PipelineSuccess, rkey)
if err != nil {
return err
···
return nil
}
-
func (db *DB) GetPipeline(rkey, knot string) (Pipeline, error) {
-
var p Pipeline
+
func (db *DB) GetPipelineStatus(rkey string) (PipelineStatus, error) {
+
var p PipelineStatus
err := db.QueryRow(`
select rkey, status, error, exit_code, started_at, updated_at, finished_at
from pipelines
-
where at_uri = ?
-
`, pipelineAtUri(rkey, knot)).Scan(&p.Rkey, &p.Status, &p.Error, &p.ExitCode, &p.StartedAt, &p.UpdatedAt, &p.FinishedAt)
+
where rkey = ?
+
`, rkey).Scan(&p.Rkey, &p.Status, &p.Error, &p.ExitCode, &p.StartedAt, &p.UpdatedAt, &p.FinishedAt)
return p, err
}
-
func (db *DB) GetPipelines(cursor string) ([]Pipeline, error) {
+
func (db *DB) GetPipelineStatusAsRecords(cursor string) ([]PipelineStatus, error) {
whereClause := ""
args := []any{}
if cursor != "" {
···
query := fmt.Sprintf(`
select rkey, status, error, exit_code, started_at, updated_at, finished_at
-
from pipelines
+
from pipeline_status
%s
order by rkey asc
limit 100
···
}
defer rows.Close()
-
var pipelines []Pipeline
+
var pipelines []PipelineStatus
for rows.Next() {
-
var p Pipeline
+
var p PipelineStatus
rows.Scan(&p.Rkey, &p.Status, &p.Error, &p.ExitCode, &p.StartedAt, &p.UpdatedAt, &p.FinishedAt)
pipelines = append(pipelines, p)
}
if err := rows.Err(); err != nil {
return nil, err
+
}
+
+
records := []*tangled.PipelineStatus{}
+
for _, p := range pipelines {
+
records = append(records, p.AsRecord())
}
return pipelines, nil
+2 -2
spindle/engine/engine.go
···
// SetupPipeline sets up a new network for the pipeline, and possibly volumes etc.
// in the future. In here also goes other setup steps.
-
func (e *Engine) SetupPipeline(ctx context.Context, pipeline *tangled.Pipeline, id string) error {
+
func (e *Engine) SetupPipeline(ctx context.Context, pipeline *tangled.Pipeline, atUri, id string) error {
e.l.Info("setting up pipeline", "pipeline", id)
_, err := e.docker.VolumeCreate(ctx, volume.CreateOptions{
···
return err
}
-
err = e.db.CreatePipeline(id, e.n)
+
err = e.db.CreatePipeline(id, atUri, e.n)
return err
}
+19 -14
spindle/server.go
···
go func() {
logger.Info("starting event consumer")
knotEventSource := knotclient.NewEventSource("localhost:5555")
-
ccfg := knotclient.ConsumerConfig{
-
Logger: logger,
-
ProcessFunc: spindle.exec,
-
}
+
+
ccfg := knotclient.NewConsumerConfig()
+
ccfg.Logger = logger
+
ccfg.Dev = cfg.Server.Dev
+
ccfg.ProcessFunc = spindle.exec
ccfg.AddEventSource(knotEventSource)
-
ec := knotclient.NewEventConsumer(ccfg)
+
ec := knotclient.NewEventConsumer(*ccfg)
ec.Start(ctx)
}()
···
}
func (s *Spindle) exec(ctx context.Context, src knotclient.EventSource, msg knotclient.Message) error {
-
pipeline := tangled.Pipeline{}
-
err := json.Unmarshal(msg.EventJson, &pipeline)
-
if err != nil {
-
fmt.Println("error unmarshalling", err)
-
return err
-
}
+
if msg.Nsid == tangled.PipelineNSID {
+
pipeline := tangled.Pipeline{}
+
err := json.Unmarshal(msg.EventJson, &pipeline)
+
if err != nil {
+
fmt.Println("error unmarshalling", err)
+
return err
+
}
-
if msg.Nsid == tangled.PipelineNSID {
-
err = s.eng.SetupPipeline(ctx, &pipeline, msg.Rkey)
+
// this is a "fake" at uri for now
+
pipelineAtUri := fmt.Sprintf("at://%s/did:web:%s/%s", tangled.PipelineNSID, pipeline.TriggerMetadata.Repo.Knot, msg.Rkey)
+
+
rkey := TID()
+
err = s.eng.SetupPipeline(ctx, &pipeline, pipelineAtUri, rkey)
if err != nil {
return err
}
-
err = s.eng.StartWorkflows(ctx, &pipeline, msg.Rkey)
+
err = s.eng.StartWorkflows(ctx, &pipeline, rkey)
if err != nil {
return err
}
+3 -2
spindle/stream.go
···
"net/http"
"time"
+
"context"
+
"github.com/gorilla/websocket"
-
"golang.org/x/net/context"
)
var upgrader = websocket.Upgrader{
···
}
func (s *Spindle) streamPipelines(conn *websocket.Conn, cursor *string) error {
-
ops, err := s.db.GetPipelines(*cursor)
+
ops, err := s.db.GetPipelineStatusAsRecords(*cursor)
if err != nil {
s.l.Debug("err", "err", err)
return err
+9
spindle/tid.go
···
+
package spindle
+
+
import "github.com/bluesky-social/indigo/atproto/syntax"
+
+
var TIDClock = syntax.NewTIDClock(0)
+
+
func TID() string {
+
return TIDClock.Next().String()
+
}