+17
-4
spindle/db/db.go
+17
-4
spindle/db/db.go
···
1
package db
2
3
+
import (
4
+
"database/sql"
5
+
6
+
_ "github.com/mattn/go-sqlite3"
7
+
)
8
9
type DB struct {
10
*sql.DB
···
31
);
32
33
create table if not exists pipelines (
34
+
at_uri text not null,
35
+
status text not null,
36
+
37
+
-- only set if status is 'failed'
38
+
error text,
39
+
exit_code integer,
40
+
41
+
started_at timestamp not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
42
+
updated_at timestamp not null default (strftime('%Y-%m-%dT%H:%M:%SZ', 'now')),
43
+
finished_at timestamp,
44
+
45
+
primary key (at_uri)
46
);
47
`)
48
if err != nil {
+124
-34
spindle/db/pipelines.go
+124
-34
spindle/db/pipelines.go
···
2
3
import (
4
"fmt"
5
)
6
7
type Pipeline struct {
8
-
Rkey string
9
-
PipelineJson string
10
}
11
12
-
func (d *DB) InsertPipeline(pipeline Pipeline) error {
13
-
_, err := d.Exec(
14
-
`insert into pipelines (rkey, nsid, event) values (?, ?, ?)`,
15
-
pipeline.Rkey,
16
-
pipeline.PipelineJson,
17
-
)
18
19
-
return err
20
}
21
22
-
func (d *DB) GetPipeline(rkey, cursor string) (Pipeline, error) {
23
-
whereClause := "where rkey = ?"
24
-
args := []any{rkey}
25
26
-
if cursor != "" {
27
-
whereClause += " and rkey > ?"
28
-
args = append(args, cursor)
29
}
30
31
-
query := fmt.Sprintf(`
32
-
select rkey, pipeline
33
-
from pipelines
34
-
%s
35
-
limit 1
36
-
`, whereClause)
37
38
-
row := d.QueryRow(query, args...)
39
40
-
var p Pipeline
41
-
err := row.Scan(&p.Rkey, &p.PipelineJson)
42
if err != nil {
43
-
return Pipeline{}, err
44
}
45
46
-
return p, nil
47
}
48
49
-
func (d *DB) GetPipelines(cursor string) ([]Pipeline, error) {
50
whereClause := ""
51
args := []any{}
52
if cursor != "" {
···
55
}
56
57
query := fmt.Sprintf(`
58
-
select rkey, nsid, pipeline
59
from pipelines
60
%s
61
order by rkey asc
62
limit 100
63
`, whereClause)
64
65
-
rows, err := d.Query(query, args...)
66
if err != nil {
67
return nil, err
68
}
69
defer rows.Close()
70
71
-
var evts []Pipeline
72
for rows.Next() {
73
-
var ev Pipeline
74
-
rows.Scan(&ev.Rkey, &ev.PipelineJson)
75
-
evts = append(evts, ev)
76
}
77
78
if err := rows.Err(); err != nil {
79
return nil, err
80
}
81
82
-
return evts, nil
83
}
···
2
3
import (
4
"fmt"
5
+
"time"
6
+
7
+
"tangled.sh/tangled.sh/core/api/tangled"
8
+
"tangled.sh/tangled.sh/core/knotserver/notifier"
9
+
)
10
+
11
+
type PipelineStatus string
12
+
13
+
var (
14
+
PipelinePending PipelineStatus = "pending"
15
+
PipelineRunning PipelineStatus = "running"
16
+
PipelineFailed PipelineStatus = "failed"
17
+
PipelineTimeout PipelineStatus = "timeout"
18
+
PipelineCancelled PipelineStatus = "cancelled"
19
+
PipelineSuccess PipelineStatus = "success"
20
)
21
22
type Pipeline struct {
23
+
Rkey string `json:"rkey"`
24
+
Knot string `json:"knot"`
25
+
Status PipelineStatus `json:"status"`
26
+
27
+
// only if Failed
28
+
Error string `json:"error"`
29
+
ExitCode int `json:"exit_code"`
30
+
31
+
StartedAt time.Time `json:"started_at"`
32
+
UpdatedAt time.Time `json:"updated_at"`
33
+
FinishedAt time.Time `json:"finished_at"`
34
}
35
36
+
func (p Pipeline) AsRecord() *tangled.PipelineStatus {
37
+
exitCode64 := int64(p.ExitCode)
38
+
finishedAt := p.FinishedAt.String()
39
+
40
+
return &tangled.PipelineStatus{
41
+
Pipeline: fmt.Sprintf("at://%s/%s", p.Knot, p.Rkey),
42
+
Status: string(p.Status),
43
+
44
+
ExitCode: &exitCode64,
45
+
Error: &p.Error,
46
+
47
+
StartedAt: p.StartedAt.String(),
48
+
UpdatedAt: p.UpdatedAt.String(),
49
+
FinishedAt: &finishedAt,
50
+
}
51
+
}
52
53
+
func pipelineAtUri(rkey, knot string) string {
54
+
return fmt.Sprintf("at://%s/did:web:%s/%s", tangled.PipelineStatusNSID, knot, rkey)
55
}
56
57
+
func (db *DB) CreatePipeline(rkey, knot string, n *notifier.Notifier) error {
58
+
_, err := db.Exec(`
59
+
insert into pipelines (at_uri, status)
60
+
values (?, ?)
61
+
`, pipelineAtUri(rkey, knot), PipelinePending)
62
63
+
if err != nil {
64
+
return err
65
}
66
+
n.NotifyAll()
67
+
return nil
68
+
}
69
70
+
func (db *DB) MarkPipelineRunning(rkey, knot string, n *notifier.Notifier) error {
71
+
_, err := db.Exec(`
72
+
update pipelines
73
+
set status = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
74
+
where at_uri = ?
75
+
`, PipelineRunning, pipelineAtUri(rkey, knot))
76
77
+
if err != nil {
78
+
return err
79
+
}
80
+
n.NotifyAll()
81
+
return nil
82
+
}
83
+
84
+
func (db *DB) MarkPipelineFailed(rkey, knot string, exitCode int, errorMsg string, n *notifier.Notifier) error {
85
+
_, err := db.Exec(`
86
+
update pipelines
87
+
set status = ?,
88
+
exit_code = ?,
89
+
error = ?,
90
+
updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
91
+
finished_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
92
+
where at_uri = ?
93
+
`, PipelineFailed, exitCode, errorMsg, pipelineAtUri(rkey, knot))
94
+
if err != nil {
95
+
return err
96
+
}
97
+
n.NotifyAll()
98
+
return nil
99
+
}
100
+
101
+
func (db *DB) MarkPipelineTimeout(rkey, knot string, n *notifier.Notifier) error {
102
+
_, err := db.Exec(`
103
+
update pipelines
104
+
set status = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
105
+
where at_uri = ?
106
+
`, PipelineTimeout, pipelineAtUri(rkey, knot))
107
+
if err != nil {
108
+
return err
109
+
}
110
+
n.NotifyAll()
111
+
return nil
112
+
}
113
+
114
+
func (db *DB) MarkPipelineSuccess(rkey, knot string, n *notifier.Notifier) error {
115
+
_, err := db.Exec(`
116
+
update pipelines
117
+
set status = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now'),
118
+
finished_at = strftime('%Y-%m-%dT%H:%M:%SZ', 'now')
119
+
where at_uri = ?
120
+
`, PipelineSuccess, pipelineAtUri(rkey, knot))
121
122
if err != nil {
123
+
return err
124
}
125
+
n.NotifyAll()
126
+
return nil
127
+
}
128
129
+
func (db *DB) GetPipeline(rkey, knot string) (Pipeline, error) {
130
+
var p Pipeline
131
+
err := db.QueryRow(`
132
+
select rkey, status, error, exit_code, started_at, updated_at, finished_at
133
+
from pipelines
134
+
where at_uri = ?
135
+
`, pipelineAtUri(rkey, knot)).Scan(&p.Rkey, &p.Status, &p.Error, &p.ExitCode, &p.StartedAt, &p.UpdatedAt, &p.FinishedAt)
136
+
return p, err
137
}
138
139
+
func (db *DB) GetPipelines(cursor string) ([]Pipeline, error) {
140
whereClause := ""
141
args := []any{}
142
if cursor != "" {
···
145
}
146
147
query := fmt.Sprintf(`
148
+
select rkey, status, error, exit_code, started_at, updated_at, finished_at
149
from pipelines
150
%s
151
order by rkey asc
152
limit 100
153
`, whereClause)
154
155
+
rows, err := db.Query(query, args...)
156
if err != nil {
157
return nil, err
158
}
159
defer rows.Close()
160
161
+
var pipelines []Pipeline
162
for rows.Next() {
163
+
var p Pipeline
164
+
rows.Scan(&p.Rkey, &p.Status, &p.Error, &p.ExitCode, &p.StartedAt, &p.UpdatedAt, &p.FinishedAt)
165
+
pipelines = append(pipelines, p)
166
}
167
168
if err := rows.Err(); err != nil {
169
return nil, err
170
}
171
172
+
return pipelines, nil
173
}