diff --git a/NOTES.md b/NOTES.md index 4278c037b36430016f19f69a9e533c8699524e4b..89823c4d5612ba6ae688ddf05c59664541e7a700 100644 --- a/NOTES.md +++ b/NOTES.md @@ -32,8 +32,8 @@ repl.commands? * this.Folder should be a storage.Folder. * Implement batch jobs * ~~Have install populate the database with some test data.~~ - * reboot - * expire + * ~~reboot~~ + * ~~expire~~ * Implement each command. * Next: folder commands - ~~CREATE~~, ~~REMOVE~~, MODIFY, ~~INDEX~~, ~~SELECT~~ * Messages: ~~ADD~~, CURRENT, ~~DIRECTORY~~, BACK, CHANGE, diff --git a/batch/batch.go b/batch/batch.go index 564dfe98b8f9b82231a8d27541fcd687da5ec16d..d4c0d6d6d32b3fb02d09217c683bd0ee1ce55760 100644 --- a/batch/batch.go +++ b/batch/batch.go @@ -2,7 +2,6 @@ package batch import ( - "context" _ "embed" "errors" "fmt" @@ -26,18 +25,36 @@ var announce206 string // Reboot deletes all messages with `shutdown` set. func Reboot() int { - fmt.Println("TODO: Delete messages with shutdown != 0.") + ctx := storage.Context() + + store, err := storage.Open() + ask.CheckErr(err) + q := storage.New(store.DB) + + rows, err := q.DeleteAllShutdownMessages(ctx) + ask.CheckErr(err) + fmt.Printf("Removed %d shutdown messages\n", rows) return 0 } // Expire deletes all messages that have hit their expiration date. func Expire() int { - fmt.Println("TODO: expire messages.") + ctx := storage.Context() + + store, err := storage.Open() + ask.CheckErr(err) + q := storage.New(store.DB) + + rows, err := q.DeleteAllExpiredMessages(ctx) + ask.CheckErr(err) + fmt.Printf("Expired %d messages\n", rows) return 0 } // Install is an interactive command used to install the crontab. func Install() int { + ctx := storage.Context() + // Check if install has run before. touchfile := path.Join(xdg.Home, ".bulletin-installed") if _, err := os.Stat(touchfile); err == nil { @@ -64,7 +81,6 @@ func Install() int { ask.CheckErr(err) // Seed data. - ctx := context.TODO() ask.CheckErr(q.SeedUserSystem(ctx)) ask.CheckErr(q.SeedFolderGeneral(ctx)) ask.CheckErr(q.SeedGeneralOwner(ctx)) @@ -89,7 +105,7 @@ func Install() int { crontab := &strings.Builder{} template.Must(template.New("crontab").Parse(crontabTemplate)). Execute(crontab, map[string]string{"Bulletin": bulletin}) - fmt.Printf("Add this to crontab:\n\n%s\n", crontab.String()) + fmt.Printf("Adding this to crontab:\n\n%s\n", crontab.String()) err = installCrontab(crontab.String()) if err != nil { panic(err) // TODO: cleanup error handling. diff --git a/folders/folders.go b/folders/folders.go index bf10e978a18814d3e069ca10351d0a7f1297be30..d34bfefc2f8297be0f3af6c710fe258c06577f38 100644 --- a/folders/folders.go +++ b/folders/folders.go @@ -2,7 +2,6 @@ package folders import ( - "context" "errors" "strings" @@ -42,7 +41,7 @@ func CreateFolder(owner string, options storage.CreateFolderParams) error { } options.Name = strings.ToUpper(options.Name) - ctx := context.TODO() + ctx := storage.Context() tx, err := this.Store.Begin() if err != nil { return err @@ -68,7 +67,7 @@ func CreateFolder(owner string, options storage.CreateFolderParams) error { // ListFolder provides a list of folders that this.User has access to. func ListFolder() ([]storage.ListFolderRow, error) { // TODO: need to check access. - ctx := context.TODO() + ctx := storage.Context() rows, err := this.Q.ListFolder(ctx) if err != nil { // TODO: process this error a bit more to give a better error message. @@ -79,7 +78,7 @@ func ListFolder() ([]storage.ListFolderRow, error) { // FindFolder finds a folder based on the prefix. func FindFolder(name string) string { - ctx := context.TODO() + ctx := storage.Context() folder, _ := this.Q.FindFolderExact(ctx, name) if folder != "" { return folder @@ -90,7 +89,7 @@ func FindFolder(name string) string { // IsFolderAccess checks if a user can access a folder. func IsFolderAccess(name, login string) bool { - ctx := context.TODO() + ctx := storage.Context() found, _ := this.Q.IsFolderAccess(ctx, storage.IsFolderAccessParams{ Name: name, Login: login, @@ -100,7 +99,7 @@ func IsFolderAccess(name, login string) bool { // IsFolderOwner checks if a user is a folder owner. func IsFolderOwner(folder, login string) bool { - ctx := context.TODO() + ctx := storage.Context() found, _ := this.Q.IsFolderOwner(ctx, storage.IsFolderOwnerParams{ Folder: folder, Login: login, @@ -111,7 +110,7 @@ func IsFolderOwner(folder, login string) bool { // DeleteFolder deletes a folder. func DeleteFolder(name string) error { // TODO: make sure user can delete this table. - ctx := context.TODO() + ctx := storage.Context() err := this.Q.DeleteFolder(ctx, name) // TODO: process this error a bit more to give a better error message. if err != nil { diff --git a/folders/messages.go b/folders/messages.go index 96499917d55096380fc20f4ab75d55d8c57593eb..e59c2a9216734925f83697b47063f8f4f3e1bae9 100644 --- a/folders/messages.go +++ b/folders/messages.go @@ -1,7 +1,6 @@ package folders import ( - "context" "errors" "time" @@ -11,7 +10,7 @@ import ( // CreateMessage creates a new folder. func CreateMessage(author, subject, message, folder string, permanent, shutdown int, expiration *time.Time) error { - ctx := context.TODO() + ctx := storage.Context() if expiration == nil { days, err := this.Q.GetFolderExpire(ctx, folder) if err != nil { @@ -27,7 +26,6 @@ func CreateMessage(author, subject, message, folder string, permanent, shutdown // TODO: replace _ with rows and check. err := this.Q.CreateMessage(ctx, storage.CreateMessageParams{ Folder: folder, - Folder_2: folder, Author: author, Subject: subject, Message: message, @@ -41,7 +39,7 @@ func CreateMessage(author, subject, message, folder string, permanent, shutdown // ReadMessage reads a message for a user. func ReadMessage(login, folder string, msgid int64) (*storage.Message, error) { - ctx := context.TODO() + ctx := storage.Context() msg, err := this.Q.ReadMessage(ctx, storage.ReadMessageParams{ Folder: folder, ID: msgid, @@ -64,12 +62,11 @@ func ReadMessage(login, folder string, msgid int64) (*storage.Message, error) { // NextMsgid gets the next message id. func NextMsgid(login, folder string, msgid int64) int64 { - ctx := context.TODO() + ctx := storage.Context() newid, err := this.Q.NextMsgid(ctx, storage.NextMsgidParams{ - Folder: folder, - Folder_2: folder, - Login: login, - ID: msgid, + Folder: folder, + Login: login, + ID: msgid, }) if err != nil { return 0 @@ -79,7 +76,7 @@ func NextMsgid(login, folder string, msgid int64) int64 { // ListMessages lists messages. func ListMessages(folder string) ([]storage.Message, error) { - ctx := context.TODO() + ctx := storage.Context() // TODO: options aren't implemented - need to set them? rows, err := this.Q.ListMessages(ctx, folder) return rows, err diff --git a/folders/users.go b/folders/users.go index 1530913d28e023f30fae4ca90829b2c40bc690be..b685ccb9039c94b231524cb56da0d1efa8882f16 100644 --- a/folders/users.go +++ b/folders/users.go @@ -1,7 +1,6 @@ package folders import ( - "context" "strings" "git.lyda.ie/kevin/bulletin/storage" @@ -10,7 +9,7 @@ import ( // GetUser gets a user. func GetUser(login string) (*storage.User, error) { - ctx := context.TODO() + ctx := storage.Context() user, err := this.Q.GetUser(ctx, login) return &user, err @@ -18,7 +17,7 @@ func GetUser(login string) (*storage.User, error) { // AddUser adds a user. func AddUser(user storage.User) (*storage.User, error) { - ctx := context.TODO() + ctx := storage.Context() newuser, err := this.Q.AddUser(ctx, storage.AddUserParams{ Login: strings.ToUpper(user.Login), Name: user.Name, @@ -29,7 +28,7 @@ func AddUser(user storage.User) (*storage.User, error) { // IsUserAdmin checks if a user is an admin. func IsUserAdmin(login string) bool { - ctx := context.TODO() + ctx := storage.Context() found, _ := this.Q.IsUserAdmin(ctx, login) return found == 1 } diff --git a/go.mod b/go.mod index a8ad251f763411ca3a23312cc85555b32d21b293..eeb07dbaa7e6cf7c4d2f5f51bd5aadba633a6b0d 100644 --- a/go.mod +++ b/go.mod @@ -10,12 +10,12 @@ require ( github.com/golang-migrate/migrate/v4 v4.18.3 github.com/jmoiron/sqlx v1.4.0 github.com/rivo/tview v0.0.0-20250501113434-0c592cd31026 - github.com/urfave/cli/v3 v3.3.2 + github.com/urfave/cli/v3 v3.3.3 modernc.org/sqlite v1.37.0 ) require ( - cel.dev/expr v0.19.1 // indirect + cel.dev/expr v0.23.1 // indirect dario.cat/mergo v1.0.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/Masterminds/goutils v1.1.1 // indirect @@ -36,7 +36,7 @@ require ( github.com/go-sql-driver/mysql v1.9.2 // indirect github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect - github.com/google/cel-go v0.24.1 // indirect + github.com/google/cel-go v0.25.0 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -75,7 +75,7 @@ require ( github.com/spf13/cast v1.7.0 // indirect github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.6 // indirect - github.com/sqlc-dev/sqlc v1.29.0 // indirect + github.com/sqlc-dev/sqlc v1.29.1-0.20250428024728-34f8c1bad949 // indirect github.com/stephenafamo/bob v0.34.2 // indirect github.com/stephenafamo/scan v0.6.2 // indirect github.com/stephenafamo/sqlparser v0.0.0-20250408111851-b937299b5b7d // indirect @@ -101,19 +101,16 @@ require ( golang.org/x/term v0.32.0 // indirect golang.org/x/text v0.25.0 // indirect golang.org/x/tools v0.33.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect - google.golang.org/grpc v1.71.1 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect + google.golang.org/grpc v1.72.0 // indirect google.golang.org/protobuf v1.36.6 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.65.2 // indirect + modernc.org/libc v1.65.6 // indirect modernc.org/mathutil v1.7.1 // indirect modernc.org/memory v1.10.0 // indirect mvdan.cc/gofumpt v0.7.0 // indirect ) -tool ( - github.com/sqlc-dev/sqlc/cmd/sqlc - github.com/stephenafamo/bob/gen/bobgen-sql -) +tool github.com/sqlc-dev/sqlc/cmd/sqlc diff --git a/go.sum b/go.sum index 4b3c073d7d562fe1eec7bf9f669ddf8f8d89515f..583347202da6cfd6c3c291c6abe80bceb5925767 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4= cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw= +cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg= +cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= @@ -64,6 +66,8 @@ github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FW github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/cel-go v0.24.1 h1:jsBCtxG8mM5wiUJDSGUqU0K7Mtr3w7Eyv00rw4DiZxI= github.com/google/cel-go v0.24.1/go.mod h1:Hdf9TqOaTNSFQA1ybQaRqATVoK7m/zcf7IMhGXP5zI8= +github.com/google/cel-go v0.25.0 h1:jsFw9Fhn+3y2kBbltZR4VEz5xKkcIFRPDnuEzAGv5GY= +github.com/google/cel-go v0.25.0/go.mod h1:hjEb6r5SuOSlhCHmFoLzu8HGCERvIsDAbxDAyNU/MmI= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -162,6 +166,8 @@ github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/sqlc-dev/sqlc v1.29.0 h1:HQctoD7y/i29Bao53qXO7CZ/BV9NcvpGpsJWvz9nKWs= github.com/sqlc-dev/sqlc v1.29.0/go.mod h1:BavmYw11px5AdPOjAVHmb9fctP5A8GTziC38wBF9tp0= +github.com/sqlc-dev/sqlc v1.29.1-0.20250428024728-34f8c1bad949 h1:K6Vv8kT/DO8Sc8oxi6Ozw/ZSJHtsi8vu1lwgAKzmRuw= +github.com/sqlc-dev/sqlc v1.29.1-0.20250428024728-34f8c1bad949/go.mod h1:wkPfTV76Vj0283VNLNZ/EYqB5yYZd/RX5ZrfWYJ4vMY= github.com/stephenafamo/bob v0.34.2 h1:eXMmAE9YPKIyFKMXmI6wYI+dQxxuAnzulbmyHBctSGk= github.com/stephenafamo/bob v0.34.2/go.mod h1:EVqAHXIxKPppvrkVsy/+YiUyHDWueIh0srPENffFhNE= github.com/stephenafamo/scan v0.6.2 h1:mEjx1P1MuimqALCXfZEV8+KAiVcByrgngqKatgHag9I= @@ -185,6 +191,8 @@ github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY= github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/urfave/cli/v3 v3.3.2 h1:BYFVnhhZ8RqT38DxEYVFPPmGFTEf7tJwySTXsVRrS/o= github.com/urfave/cli/v3 v3.3.2/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +github.com/urfave/cli/v3 v3.3.3 h1:byCBaVdIXuLPIDm5CYZRVG6NvT7tv1ECqdU4YzlEa3I= +github.com/urfave/cli/v3 v3.3.3/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= github.com/volatiletech/inflect v0.0.1 h1:2a6FcMQyhmPZcLa+uet3VJ8gLn/9svWhJxJYwvE8KsU= github.com/volatiletech/inflect v0.0.1/go.mod h1:IBti31tG6phkHitLlr5j7shC5SOo//x0AjDzaJU1PLA= github.com/volatiletech/strmangle v0.0.6 h1:AdOYE3B2ygRDq4rXDij/MMwq6KVK/pWAYxpC7CLrkKQ= @@ -304,10 +312,16 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24= google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw= +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= +google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f h1:OxYkA3wjPsZyBylwymxSHa7ViiW1Sml4ToBrncvFehI= google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= +google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= @@ -329,12 +343,15 @@ modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s= modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/ccgo/v4 v4.27.1 h1:emhLB4uoOmkZUnTDFcMI3AbkmU/Evjuerit9Taqe6Ss= modernc.org/ccgo/v4 v4.27.1/go.mod h1:543Q0qQhJWekKVS5P6yL5fO6liNhla9Lbm2/B3rEKDE= +modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8= modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= modernc.org/libc v1.65.2 h1:drWL1QO9fKXr3kXDN8y+4lKyBr8bA3mtUBQpftq3IJw= modernc.org/libc v1.65.2/go.mod h1:VI3V2S5mNka4deJErQ0jsMXe7jgxojE2fOB/mWoHlbc= +modernc.org/libc v1.65.6 h1:OhJUhmuJ6MVZdqL5qmnd0/my46DKGFhSX4WOR7ijfyE= +modernc.org/libc v1.65.6/go.mod h1:MOiGAM9lrMBT9L8xT1nO41qYl5eg9gCp9/kWhz5L7WA= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4= diff --git a/storage/batch.sql.go b/storage/batch.sql.go new file mode 100644 index 0000000000000000000000000000000000000000..793f70d1af1f2f34fcbf60d8416a5eca7dfcba76 --- /dev/null +++ b/storage/batch.sql.go @@ -0,0 +1,36 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.29.0 +// source: batch.sql + +package storage + +import ( + "context" +) + +const deleteAllExpiredMessages = `-- name: DeleteAllExpiredMessages :execrows +DELETE FROM messages +WHERE permanent != 0 AND expiration < CURRENT_TIMESTAMP +` + +func (q *Queries) DeleteAllExpiredMessages(ctx context.Context) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteAllExpiredMessages) + if err != nil { + return 0, err + } + return result.RowsAffected() +} + +const deleteAllShutdownMessages = `-- name: DeleteAllShutdownMessages :execrows +DELETE FROM messages +WHERE permanent != 0 AND shutdown > 0 +` + +func (q *Queries) DeleteAllShutdownMessages(ctx context.Context) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteAllShutdownMessages) + if err != nil { + return 0, err + } + return result.RowsAffected() +} diff --git a/storage/connection.go b/storage/connection.go index ad10c3fccafb0ff54f209e3f1f75d5debdbde84b..616afd288fc680db3668b3bbe02b4b96adfa0893 100644 --- a/storage/connection.go +++ b/storage/connection.go @@ -1,6 +1,7 @@ package storage import ( + "context" "embed" "errors" "os" @@ -52,3 +53,8 @@ func Open() (*sqlx.DB, error) { } return db, nil } + +// Context the standard context for storage calls. +func Context() context.Context { + return context.TODO() +} diff --git a/storage/messages.sql.go b/storage/messages.sql.go index 5fd8d92b91983bd5465aeb8c327d9d5a5f7e2952..b922e096c630a132966c425741c4b56b250e9241 100644 --- a/storage/messages.sql.go +++ b/storage/messages.sql.go @@ -14,14 +14,13 @@ const createMessage = `-- name: CreateMessage :exec INSERT INTO messages ( id, folder, author, subject, message, permanent, shutdown, expiration ) VALUES ( - (SELECT COALESCE(MAX(id), 0) + 1 FROM messages AS m WHERE m.folder = ?), - ?, ?, ?, ?, ?, ?, ?) + (SELECT COALESCE(MAX(id), 0) + 1 FROM messages AS m WHERE m.folder = ?1), + ?2, ?1, ?3, ?4, ?5, ?6, ?7) ` type CreateMessageParams struct { - Folder string - Folder_2 string Author string + Folder string Subject string Message string Permanent int64 @@ -31,9 +30,8 @@ type CreateMessageParams struct { func (q *Queries) CreateMessage(ctx context.Context, arg CreateMessageParams) error { _, err := q.db.ExecContext(ctx, createMessage, - arg.Folder, - arg.Folder_2, arg.Author, + arg.Folder, arg.Subject, arg.Message, arg.Permanent, @@ -56,24 +54,18 @@ func (q *Queries) GetFirstMessageID(ctx context.Context, folder string) (int64, const nextMsgid = `-- name: NextMsgid :one SELECT CAST(COALESCE(MIN(id), 0) AS INT) FROM messages AS m - WHERE m.folder = ? AND m.id > ? - AND id NOT IN (SELECT id FROM seen AS s WHERE s.folder = ? AND s.login = ?) + WHERE m.folder = ?1 AND m.id > ?2 + AND id NOT IN (SELECT id FROM seen AS s WHERE s.folder = ?1 AND s.login = ?3) ` type NextMsgidParams struct { - Folder string - ID int64 - Folder_2 string - Login string + Folder string + ID int64 + Login string } func (q *Queries) NextMsgid(ctx context.Context, arg NextMsgidParams) (int64, error) { - row := q.db.QueryRowContext(ctx, nextMsgid, - arg.Folder, - arg.ID, - arg.Folder_2, - arg.Login, - ) + row := q.db.QueryRowContext(ctx, nextMsgid, arg.Folder, arg.ID, arg.Login) var column_1 int64 err := row.Scan(&column_1) return column_1, err diff --git a/storage/queries/batch.sql b/storage/queries/batch.sql new file mode 100644 index 0000000000000000000000000000000000000000..e78577f6830e956cf5526412fd9db5e06a280666 --- /dev/null +++ b/storage/queries/batch.sql @@ -0,0 +1,7 @@ +-- name: DeleteAllExpiredMessages :execrows +DELETE FROM messages +WHERE permanent != 0 AND expiration < CURRENT_TIMESTAMP; + +-- name: DeleteAllShutdownMessages :execrows +DELETE FROM messages +WHERE permanent != 0 AND shutdown > 0; diff --git a/storage/queries/messages.sql b/storage/queries/messages.sql index 62e04896ef8f2932930b782f1abc0f8d345d2022..0866f466296f44b7b71e3b9453cc22396f4d8657 100644 --- a/storage/queries/messages.sql +++ b/storage/queries/messages.sql @@ -2,8 +2,8 @@ INSERT INTO messages ( id, folder, author, subject, message, permanent, shutdown, expiration ) VALUES ( - (SELECT COALESCE(MAX(id), 0) + 1 FROM messages AS m WHERE m.folder = ?), - ?, ?, ?, ?, ?, ?, ?); + (SELECT COALESCE(MAX(id), 0) + 1 FROM messages AS m WHERE m.folder = ?1), + ?2, ?1, ?3, ?4, ?5, ?6, ?7); -- name: SetMessageSeen :exec INSERT INTO seen (login, folder, msgid) VALUES (?, ?, ?); @@ -16,5 +16,5 @@ SELECT * FROM messages WHERE folder = ? AND id = ?; -- name: NextMsgid :one SELECT CAST(COALESCE(MIN(id), 0) AS INT) FROM messages AS m - WHERE m.folder = ? AND m.id > ? - AND id NOT IN (SELECT id FROM seen AS s WHERE s.folder = ? AND s.login = ?); + WHERE m.folder = ?1 AND m.id > ?2 + AND id NOT IN (SELECT id FROM seen AS s WHERE s.folder = ?1 AND s.login = ?3); diff --git a/this/this.go b/this/this.go index 55ce0aabff924ade98b3f2d93670d3091bf56bdb..9ea7e69b1c7776eb2bcb8248c6cfaceee3feb2e4 100644 --- a/this/this.go +++ b/this/this.go @@ -10,7 +10,6 @@ TODO: Eventually `this` will need to handle broadcast messages. package this import ( - "context" "errors" "fmt" @@ -50,7 +49,7 @@ func StartThis(login, name string) error { } Q = storage.New(Store.DB) - ctx := context.TODO() + ctx := storage.Context() User, err = Q.GetUser(ctx, login) if User.Login != login {