Skip to content

Commit df8e686

Browse files
authored
enhance: use workspace file revisions to avoid clobbering the database (#437)
Signed-off-by: Nick Hale <[email protected]>
1 parent c5f9ad8 commit df8e686

File tree

3 files changed

+66
-32
lines changed

3 files changed

+66
-32
lines changed

database/go.mod

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,20 @@ module obot-platform/database
33
go 1.23.3
44

55
require (
6-
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
7-
github.com/gptscript-ai/go-gptscript v0.9.6-0.20250204133419-744b25b84a61
6+
github.com/gptscript-ai/go-gptscript v0.9.6-0.20250222170845-eee4337500a6
87
github.com/ncruces/go-sqlite3 v0.20.3
98
)
109

1110
require (
12-
github.com/getkin/kin-openapi v0.124.0 // indirect
13-
github.com/go-openapi/jsonpointer v0.20.2 // indirect
14-
github.com/go-openapi/swag v0.22.8 // indirect
15-
github.com/invopop/yaml v0.2.0 // indirect
11+
github.com/getkin/kin-openapi v0.129.0 // indirect
12+
github.com/go-openapi/jsonpointer v0.21.0 // indirect
13+
github.com/go-openapi/swag v0.23.0 // indirect
1614
github.com/josharian/intern v1.0.0 // indirect
17-
github.com/mailru/easyjson v0.7.7 // indirect
15+
github.com/mailru/easyjson v0.9.0 // indirect
1816
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
1917
github.com/ncruces/julianday v1.0.0 // indirect
18+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 // indirect
19+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 // indirect
2020
github.com/perimeterx/marshmallow v1.1.5 // indirect
2121
github.com/tetratelabs/wazero v1.8.2 // indirect
2222
golang.org/x/sys v0.27.0 // indirect

database/go.sum

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,41 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3-
github.com/getkin/kin-openapi v0.124.0 h1:VSFNMB9C9rTKBnQ/fpyDU8ytMTr4dWI9QovSKj9kz/M=
4-
github.com/getkin/kin-openapi v0.124.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM=
5-
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
6-
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
7-
github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw=
8-
github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI=
3+
github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30=
4+
github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI=
5+
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
6+
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
7+
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
8+
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
99
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
1010
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
11-
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
12-
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
13-
github.com/gptscript-ai/go-gptscript v0.9.6-0.20250204133419-744b25b84a61 h1:QxLjsLOYlsVLPwuRkP0Q8EcAoZT1s8vU2ZBSX0+R6CI=
14-
github.com/gptscript-ai/go-gptscript v0.9.6-0.20250204133419-744b25b84a61/go.mod h1:/FVuLwhz+sIfsWUgUHWKi32qT0i6+IXlUlzs70KKt/Q=
15-
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
16-
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
11+
github.com/gptscript-ai/go-gptscript v0.9.6-0.20250222170845-eee4337500a6 h1:vsZ09cWfNWUXT6AOVQc1GpfEdIxcLusUs6Hgo9IgAKs=
12+
github.com/gptscript-ai/go-gptscript v0.9.6-0.20250222170845-eee4337500a6/go.mod h1:QvGPZoRuAiA8P5EzPI05kTrs+LZ0ipHywUGsKruSknw=
1713
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
1814
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
1915
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
2016
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
2117
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
2218
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
23-
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
24-
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
19+
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
20+
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
2521
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
2622
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
2723
github.com/ncruces/go-sqlite3 v0.20.3 h1:+4G4uEqOeusF0yRuQVUl9fuoEebUolwQSnBUjYBLYIw=
2824
github.com/ncruces/go-sqlite3 v0.20.3/go.mod h1:ojLIAB243gtz68Eo283Ps+k9PyR3dvzS+9/RgId4+AA=
2925
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
3026
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
27+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 h1:nZspmSkneBbtxU9TopEAE0CY+SBJLxO8LPUlw2vG4pU=
28+
github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8=
29+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 h1:t05Ww3DxZutOqbMN+7OIuqDwXbhl32HiZGpLy26BAPc=
30+
github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
3131
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
3232
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
3333
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
3434
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
3535
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
3636
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
37-
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
38-
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
37+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
38+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
3939
github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4=
4040
github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
4141
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
@@ -47,6 +47,5 @@ golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
4747
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
4848
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
4949
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
50-
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
5150
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
5251
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

database/main.go

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"errors"
88
"fmt"
99
"os"
10+
"slices"
1011

1112
"obot-platform/database/pkg/cmd"
1213

@@ -32,15 +33,17 @@ func main() {
3233
defer g.Close()
3334

3435
var (
35-
ctx = context.Background()
36-
dbFileName = "acorn.db"
37-
dbWorkspacePath = "/databases/" + dbFileName
36+
ctx = context.Background()
37+
dbFileName = "acorn.db"
38+
dbWorkspacePath = "/databases/" + dbFileName
39+
revisionID string = "-1"
40+
initialDBData []byte
3841
)
3942

40-
// Read the database file from the workspace
41-
initialDBData, err := g.ReadFileInWorkspace(ctx, dbWorkspacePath, gptscript.ReadFileInWorkspaceOptions{
43+
workspaceDB, err := g.ReadFileWithRevisionInWorkspace(ctx, dbWorkspacePath, gptscript.ReadFileInWorkspaceOptions{
4244
WorkspaceID: workspaceID,
4345
})
46+
4447
var notFoundErr *gptscript.NotFoundInWorkspaceError
4548
if err != nil && !errors.As(err, &notFoundErr) {
4649
fmt.Printf("Error reading DB file: %v\n", err)
@@ -57,11 +60,15 @@ func main() {
5760
defer os.Remove(dbFile.Name())
5861

5962
// Write the data to the temporary file
60-
if initialDBData != nil {
63+
if workspaceDB != nil && workspaceDB.Content != nil {
64+
initialDBData = workspaceDB.Content
6165
if err := os.WriteFile(dbFile.Name(), initialDBData, 0644); err != nil {
6266
fmt.Printf("Error writing to temp file: %v\n", err)
6367
os.Exit(1)
6468
}
69+
if workspaceDB.RevisionID != "" {
70+
revisionID = workspaceDB.RevisionID
71+
}
6572
}
6673

6774
// Run the requested command
@@ -74,7 +81,7 @@ func main() {
7481
case "runDatabaseSQL":
7582
result, err = cmd.RunDatabaseCommand(ctx, dbFile, os.Getenv("SQL"), "-header")
7683
if err == nil {
77-
err = saveWorkspaceDB(ctx, g, dbWorkspacePath, dbFile, initialDBData)
84+
err = saveWorkspaceDB(ctx, g, dbWorkspacePath, revisionID, dbFile, initialDBData)
7885
}
7986
case "databaseContext":
8087
result, err = cmd.DatabaseContext(ctx, dbFile)
@@ -95,6 +102,7 @@ func saveWorkspaceDB(
95102
ctx context.Context,
96103
g *gptscript.GPTScript,
97104
dbWorkspacePath string,
105+
revisionID string,
98106
dbFile *os.File,
99107
initialDBData []byte,
100108
) error {
@@ -108,11 +116,38 @@ func saveWorkspaceDB(
108116
}
109117

110118
if err := g.WriteFileInWorkspace(ctx, dbWorkspacePath, updatedDBData, gptscript.WriteFileInWorkspaceOptions{
111-
WorkspaceID: workspaceID,
119+
WorkspaceID: workspaceID,
120+
CreateRevision: &([]bool{true}[0]),
121+
LatestRevisionID: revisionID,
112122
}); err != nil {
113123
return fmt.Errorf("Error writing updated DB file to workspace: %v", err)
114124
}
115125

126+
// Delete old revisions after successfully writing the new revision
127+
revisions, err := g.ListRevisionsForFileInWorkspace(ctx, dbWorkspacePath, gptscript.ListRevisionsForFileInWorkspaceOptions{
128+
WorkspaceID: workspaceID,
129+
})
130+
if err != nil {
131+
fmt.Fprintf(os.Stderr, "Error listing revisions: %v\n", err)
132+
return nil
133+
}
134+
135+
lastRevisionIndex := slices.IndexFunc(revisions, func(rev gptscript.FileInfo) bool {
136+
return rev.RevisionID == revisionID
137+
})
138+
139+
if lastRevisionIndex < 0 {
140+
return nil
141+
}
142+
143+
for _, rev := range revisions[:lastRevisionIndex+1] {
144+
if err := g.DeleteRevisionForFileInWorkspace(ctx, dbWorkspacePath, rev.RevisionID, gptscript.DeleteRevisionForFileInWorkspaceOptions{
145+
WorkspaceID: workspaceID,
146+
}); err != nil {
147+
fmt.Fprintf(os.Stderr, "Error deleting revision %s: %v\n", rev.RevisionID, err)
148+
}
149+
}
150+
116151
return nil
117152
}
118153

0 commit comments

Comments
 (0)