From 1b123d65a27eae705e6e45550f72032e75412959 Mon Sep 17 00:00:00 2001 From: Brandur Date: Thu, 13 Aug 2026 02:51:59 -0500 Subject: [PATCH] Upgrade River + River Pro and support SQLite Bumps River to v0.44.1, River Pro to v0.27.1, and makes a couple tweaks to make sure that River Pro features are working in conjunction with SQLite. --- CHANGELOG.md | 2 + go.mod | 12 +-- go.sum | 24 ++--- riverproui/go.mod | 28 ++++-- riverproui/go.sum | 85 ++++++++++++++---- riverproui/pro_handler_test.go | 157 +++++++++++++++++++++++---------- 6 files changed, 216 insertions(+), 92 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6c2169..1bf95508 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,9 +10,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Job list: filter jobs matching any of the selected exact tags. [PR #548](https://github.com/riverqueue/riverui/pull/548). +- Add River Pro UI support for SQLite through the new `riverprosqlite` driver. [PR #657](https://github.com/riverqueue/riverui/pull/657). ### Fixed +- Job and workflow detail: serialize jobs without attempt errors as an empty array so SQLite-backed pages render correctly. [PR #657](https://github.com/riverqueue/riverui/pull/657). - Job args: preserve large numeric JSON values exactly when displaying and copying args, while keeping object keys sorted. [Fixes #593](https://github.com/riverqueue/riverui/issues/593). [PR #594](https://github.com/riverqueue/riverui/pull/594). - JSON viewer: render empty and escaped object property keys as valid JSON strings. [PR #632](https://github.com/riverqueue/riverui/pull/632). diff --git a/go.mod b/go.mod index d516304d..d474b2a2 100644 --- a/go.mod +++ b/go.mod @@ -8,11 +8,11 @@ require ( github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6 github.com/jackc/pgx/v5 v5.10.0 github.com/riverqueue/apiframe v0.0.0-20251229202423-2b52ce1c482e - github.com/riverqueue/river v0.43.0 - github.com/riverqueue/river/riverdriver v0.43.0 - github.com/riverqueue/river/riverdriver/riverpgxv5 v0.43.0 - github.com/riverqueue/river/rivershared v0.43.0 - github.com/riverqueue/river/rivertype v0.43.0 + github.com/riverqueue/river v0.44.1 + github.com/riverqueue/river/riverdriver v0.44.1 + github.com/riverqueue/river/riverdriver/riverpgxv5 v0.44.1 + github.com/riverqueue/river/rivershared v0.44.1 + github.com/riverqueue/river/rivertype v0.44.1 github.com/rs/cors v1.11.1 github.com/samber/slog-http v1.12.1 github.com/stretchr/testify v1.11.1 @@ -40,7 +40,7 @@ require ( golang.org/x/crypto v0.52.0 // indirect golang.org/x/sync v0.22.0 // indirect golang.org/x/sys v0.45.0 // indirect - golang.org/x/text v0.40.0 // indirect + golang.org/x/text v0.41.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 5086191b..05388700 100644 --- a/go.sum +++ b/go.sum @@ -35,16 +35,16 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/riverqueue/apiframe v0.0.0-20251229202423-2b52ce1c482e h1:OwOgxT3MRpOj5Mp6DhFdZP43FOQOf2hhywAuT5XZCR4= github.com/riverqueue/apiframe v0.0.0-20251229202423-2b52ce1c482e/go.mod h1:O7UmsAMjpMYuToN4au5GNXdmN1gli+5FTldgXqAfaD0= -github.com/riverqueue/river v0.43.0 h1:3Dx6D3s6x+LM64UXRNJ79LvHxbE7XHywQUbMJOKEkbg= -github.com/riverqueue/river v0.43.0/go.mod h1:cj0PdXI8jFTyNSAuVsItUhceQPYgRKdWLzBH5COLN4g= -github.com/riverqueue/river/riverdriver v0.43.0 h1:gZOXFrUO4eoltx1aS389qBcMnYu0/vHjwUiLRjhKAd0= -github.com/riverqueue/river/riverdriver v0.43.0/go.mod h1:ovNGHrKy+vhmnv973hNwEiz37d224fENQhS8mNr02eo= -github.com/riverqueue/river/riverdriver/riverpgxv5 v0.43.0 h1:bY54qI+QLzqj/89xgOWmDMxBQjoWOgG6K5G3SS4dYJo= -github.com/riverqueue/river/riverdriver/riverpgxv5 v0.43.0/go.mod h1:4TlYleXF/TcO4k7B5v1T8P/N4cznQBts2Z6/sf/X8zc= -github.com/riverqueue/river/rivershared v0.43.0 h1:MtXJCI1CFE/xs5+f6iijMwLaPufseatwd7PZBgvmb58= -github.com/riverqueue/river/rivershared v0.43.0/go.mod h1:gbL9ne9A8dtJuVzUrYvYxN9xji0UFDCcEbPPmZoi3qM= -github.com/riverqueue/river/rivertype v0.43.0 h1:zArGUikFO22poxU7MvJ4EXT/3OFKzkidyAumJrFepKI= -github.com/riverqueue/river/rivertype v0.43.0/go.mod h1:D1Ad+EaZiaXbQbJcJcfeicXJMBKno0n6UcfKI5Q7DIQ= +github.com/riverqueue/river v0.44.1 h1:RTSmxsfxMA2fWmNP5fjkMBQ89g55o0jZhJdXQkAuNXs= +github.com/riverqueue/river v0.44.1/go.mod h1:IXYp7GIbWfeW1F2q/8USppMRU8zduixLgDc69FpDNHg= +github.com/riverqueue/river/riverdriver v0.44.1 h1:ZDWC5YrWD38eAWPkwIbhNLWDrU+gqy5v7MA6hsFVQmY= +github.com/riverqueue/river/riverdriver v0.44.1/go.mod h1:oYT5b5KWczcf9qxX/tUZHy6eqAwPHpqSiDz/AQQw3hU= +github.com/riverqueue/river/riverdriver/riverpgxv5 v0.44.1 h1:C8oU/ca8MNmbxcUaA5MZfFBGm+zN1mtD3q0IQ5swQ/g= +github.com/riverqueue/river/riverdriver/riverpgxv5 v0.44.1/go.mod h1:GDDUOTTDfULearfjknVJ+bsMWwwC+1gb4WeyXM3k0xw= +github.com/riverqueue/river/rivershared v0.44.1 h1:QTFc7vCLmdy+6MN3Tkv5gGEdkLzzv/vBc60G4A35aWk= +github.com/riverqueue/river/rivershared v0.44.1/go.mod h1:NBD6huYureyKGK91eoIm5iDPngolm57YvHu06Ma4aeM= +github.com/riverqueue/river/rivertype v0.44.1 h1:G9UnsBJhlndreMPdjHSoY8wp+OTAsDTTzOpwvZQJv6M= +github.com/riverqueue/river/rivertype v0.44.1/go.mod h1:D1Ad+EaZiaXbQbJcJcfeicXJMBKno0n6UcfKI5Q7DIQ= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= @@ -81,8 +81,8 @@ golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= -golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/riverproui/go.mod b/riverproui/go.mod index 9ff3adba..d06c7e9d 100644 --- a/riverproui/go.mod +++ b/riverproui/go.mod @@ -8,14 +8,16 @@ require ( github.com/google/uuid v1.6.0 github.com/jackc/pgx/v5 v5.10.0 github.com/riverqueue/apiframe v0.0.0-20260728015158-808511b9e3ae - github.com/riverqueue/river v0.43.0 - github.com/riverqueue/river/riverdriver v0.43.0 - github.com/riverqueue/river/rivershared v0.43.0 - github.com/riverqueue/river/rivertype v0.43.0 + github.com/riverqueue/river v0.44.1 + github.com/riverqueue/river/riverdriver v0.44.1 + github.com/riverqueue/river/rivershared v0.44.1 + github.com/riverqueue/river/rivertype v0.44.1 github.com/stretchr/testify v1.11.1 - riverqueue.com/riverpro v0.26.1 - riverqueue.com/riverpro/driver v0.26.1 - riverqueue.com/riverpro/driver/riverpropgxv5 v0.26.1 + modernc.org/sqlite v1.54.0 + riverqueue.com/riverpro v0.27.1 + riverqueue.com/riverpro/driver v0.27.1 + riverqueue.com/riverpro/driver/riverpropgxv5 v0.27.1 + riverqueue.com/riverpro/driver/riverprosqlite v0.27.1 riverqueue.com/riverui v0.17.0 ) @@ -23,6 +25,7 @@ require ( cel.dev/expr v0.25.1 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect github.com/gabriel-vasile/mimetype v1.4.15 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -33,8 +36,12 @@ require ( github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/leodido/go-urn v1.5.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/ncruces/go-strftime v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/riverqueue/river/riverdriver/riverpgxv5 v0.43.0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/riverqueue/river/riverdriver/riverpgxv5 v0.44.1 // indirect + github.com/riverqueue/river/riverdriver/riversqlite v0.44.1 // indirect github.com/rs/cors v1.11.1 // indirect github.com/samber/slog-http v1.12.1 // indirect github.com/tidwall/gjson v1.19.0 // indirect @@ -49,11 +56,14 @@ require ( golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect golang.org/x/sync v0.22.0 // indirect golang.org/x/sys v0.47.0 // indirect - golang.org/x/text v0.40.0 // indirect + golang.org/x/text v0.41.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect google.golang.org/protobuf v1.36.11 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + modernc.org/libc v1.74.1 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect ) retract ( diff --git a/riverproui/go.sum b/riverproui/go.sum index 33ea1a2d..73ec2cce 100644 --- a/riverproui/go.sum +++ b/riverproui/go.sum @@ -5,6 +5,8 @@ github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmO github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI= github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -19,8 +21,12 @@ github.com/google/cel-go v0.30.0 h1:ll54AkzKunWkBn9wSoiUXbFZXYZTkdJGNXTBXUoolGo= github.com/google/cel-go v0.30.0/go.mod h1:X0bD6iVNR8pkROSOoHVdgTkzmRcosof7WQqCD6wcMc8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= +github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6 h1:D/V0gu4zQ3cL2WKeVNVM4r2gLxGGf6McLwgXzRTo2RQ= github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6/go.mod h1:a/s9Lp5W7n/DD0VrVoyJ00FbP2ytTPDVOivvn2bMlds= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -37,20 +43,28 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0= github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/riverqueue/apiframe v0.0.0-20260728015158-808511b9e3ae h1:12Jq8pKBhQ2aJ0RNfMPpb5NwBg/Iv5yunBsAxqJULrc= github.com/riverqueue/apiframe v0.0.0-20260728015158-808511b9e3ae/go.mod h1:Nu+Ehohzsxj7MklMt5WNM8XWHj/EM2EczlQ/CVQBlp8= -github.com/riverqueue/river v0.43.0 h1:3Dx6D3s6x+LM64UXRNJ79LvHxbE7XHywQUbMJOKEkbg= -github.com/riverqueue/river v0.43.0/go.mod h1:cj0PdXI8jFTyNSAuVsItUhceQPYgRKdWLzBH5COLN4g= -github.com/riverqueue/river/riverdriver v0.43.0 h1:gZOXFrUO4eoltx1aS389qBcMnYu0/vHjwUiLRjhKAd0= -github.com/riverqueue/river/riverdriver v0.43.0/go.mod h1:ovNGHrKy+vhmnv973hNwEiz37d224fENQhS8mNr02eo= -github.com/riverqueue/river/riverdriver/riverpgxv5 v0.43.0 h1:bY54qI+QLzqj/89xgOWmDMxBQjoWOgG6K5G3SS4dYJo= -github.com/riverqueue/river/riverdriver/riverpgxv5 v0.43.0/go.mod h1:4TlYleXF/TcO4k7B5v1T8P/N4cznQBts2Z6/sf/X8zc= -github.com/riverqueue/river/rivershared v0.43.0 h1:MtXJCI1CFE/xs5+f6iijMwLaPufseatwd7PZBgvmb58= -github.com/riverqueue/river/rivershared v0.43.0/go.mod h1:gbL9ne9A8dtJuVzUrYvYxN9xji0UFDCcEbPPmZoi3qM= -github.com/riverqueue/river/rivertype v0.43.0 h1:zArGUikFO22poxU7MvJ4EXT/3OFKzkidyAumJrFepKI= -github.com/riverqueue/river/rivertype v0.43.0/go.mod h1:D1Ad+EaZiaXbQbJcJcfeicXJMBKno0n6UcfKI5Q7DIQ= +github.com/riverqueue/river v0.44.1 h1:RTSmxsfxMA2fWmNP5fjkMBQ89g55o0jZhJdXQkAuNXs= +github.com/riverqueue/river v0.44.1/go.mod h1:IXYp7GIbWfeW1F2q/8USppMRU8zduixLgDc69FpDNHg= +github.com/riverqueue/river/riverdriver v0.44.1 h1:ZDWC5YrWD38eAWPkwIbhNLWDrU+gqy5v7MA6hsFVQmY= +github.com/riverqueue/river/riverdriver v0.44.1/go.mod h1:oYT5b5KWczcf9qxX/tUZHy6eqAwPHpqSiDz/AQQw3hU= +github.com/riverqueue/river/riverdriver/riverpgxv5 v0.44.1 h1:C8oU/ca8MNmbxcUaA5MZfFBGm+zN1mtD3q0IQ5swQ/g= +github.com/riverqueue/river/riverdriver/riverpgxv5 v0.44.1/go.mod h1:GDDUOTTDfULearfjknVJ+bsMWwwC+1gb4WeyXM3k0xw= +github.com/riverqueue/river/riverdriver/riversqlite v0.44.1 h1:t4+o/Xhxhvnh13XS7PNYn8jf39e13KNmIwo3E4iFQsY= +github.com/riverqueue/river/riverdriver/riversqlite v0.44.1/go.mod h1:Dv5tvswubq5jgqd8i/ZeA3X/+9xgYlUylqXVCkbHoWc= +github.com/riverqueue/river/rivershared v0.44.1 h1:QTFc7vCLmdy+6MN3Tkv5gGEdkLzzv/vBc60G4A35aWk= +github.com/riverqueue/river/rivershared v0.44.1/go.mod h1:NBD6huYureyKGK91eoIm5iDPngolm57YvHu06Ma4aeM= +github.com/riverqueue/river/rivertype v0.44.1 h1:G9UnsBJhlndreMPdjHSoY8wp+OTAsDTTzOpwvZQJv6M= +github.com/riverqueue/river/rivertype v0.44.1/go.mod h1:D1Ad+EaZiaXbQbJcJcfeicXJMBKno0n6UcfKI5Q7DIQ= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= @@ -87,12 +101,17 @@ golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw= golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk= golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA= golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ= +golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= +golang.org/x/mod v0.40.0/go.mod h1:0/weTWkPWGBikyTWAX3dkjVztMmBA5hM0DH6BElSupE= golang.org/x/sync v0.22.0 h1:SZjpbeLmrCk4xhRSZFNZW5gFUeCeFgjekvI/+gfScek= golang.org/x/sync v0.22.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs= golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs= -golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY= +golang.org/x/text v0.41.0 h1:vz/seA0lnX87Othu2f/0L24RcgrXD9/YFTSuGjj3rH8= +golang.org/x/text v0.41.0/go.mod h1:jvf1O8ajNzZqhSrQBPbutR/EB83Cc0CFrezNQIwbb5M= +golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE= +golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk= google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1:tu/dtnW1o3wfaxCOjSLn5IRX4YDcJrtlpzYkhHhGaC4= google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng= google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d h1:t/LOSXPJ9R0B6fnZNyALBRfZBH0Uy0gT+uR+SJ6syqQ= @@ -105,11 +124,41 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EV gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -riverqueue.com/riverpro v0.26.1 h1:HCrfSRlSQZfIz7+v9amfmiPDB412bf6vmB1K7llUXc0= -riverqueue.com/riverpro v0.26.1/go.mod h1:L/rt7mhtxroKS9l9ep9lN34NFfwRLztxKjJ19qJSOTY= -riverqueue.com/riverpro/driver v0.26.1 h1:t010KoWLFKgJJXDyLQtCKB+bvGy38e5CA3RPQLgC8Xc= -riverqueue.com/riverpro/driver v0.26.1/go.mod h1:ZakYxHE6KwOmH5bgMaQ2/A0PpQEd8fryIn5896PiL0k= -riverqueue.com/riverpro/driver/riverpropgxv5 v0.26.1 h1:2yAFETHRo5ApMAYa0n+3FMl0j8m7Q1FLXS2X5YiZf2c= -riverqueue.com/riverpro/driver/riverpropgxv5 v0.26.1/go.mod h1:vSSADuJu2Bs2rGtPqiJYt+lenlQyTLDslowA74uVJV8= +modernc.org/cc/v4 v4.29.0 h1:CXgwL8cvxmyzBQZzbSl/6xFtMCryb6u8IOqDci39cgc= +modernc.org/cc/v4 v4.29.0/go.mod h1:OnovgIhbbMXMu1aISnJ0wvVD1KnW+cAUJkIrAWh+kVI= +modernc.org/ccgo/v4 v4.34.6 h1:sBgfIwyN0TQ9C5hwIeuqyeAKyMWnbvj2fvpF4L11uzU= +modernc.org/ccgo/v4 v4.34.6/go.mod h1:SZ8YcN9NG7XVsQYdm6jYBvi8PQP1qi+kqB6OhjqI3Fk= +modernc.org/fileutil v1.4.0 h1:j6ZzNTftVS054gi281TyLjHPp6CPHr2KCxEXjEbD6SM= +modernc.org/fileutil v1.4.0/go.mod h1:EqdKFDxiByqxLk8ozOxObDSfcVOv/54xDs/DUHdvCUU= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/gc/v3 v3.1.4 h1:2g65LGVSmFQrXeITAw97x7hCRvZFcyE1uDP+7Vng7JI= +modernc.org/gc/v3 v3.1.4/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= +modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= +modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= +modernc.org/libc v1.74.1 h1:bdR4VTKFMC4966QSNZ05XLGI/VwzVa2kTUX51Dm0riQ= +modernc.org/libc v1.74.1/go.mod h1:uH4t5bOx3G3g9Xcmj10YKlTcVISlRDwv8VoQJG9n8Os= +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.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/opt v0.2.0 h1:tGyef5ApycA7FSEOMraay9SaTk5zmbx7Tu+cJs4QKZg= +modernc.org/opt v0.2.0/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= +modernc.org/sqlite v1.54.0 h1:JCxR4qwkJvOaqAoYcgDoO25Nc+ROg6EJ2LfBVzdrgog= +modernc.org/sqlite v1.54.0/go.mod h1:4ntCLuNmnH8+GNqjka1wNg7KJd5/Hi5FYp8K+XQ7GZw= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +riverqueue.com/riverpro v0.27.1 h1:jhP0N215u2E0ND46bR7ODZ1AwlCjPC+XSC1mt6SnYvk= +riverqueue.com/riverpro v0.27.1/go.mod h1:onPTgV5u50FC3Brrtkzungt9e6BHzGyuj0T32qIh3J0= +riverqueue.com/riverpro/driver v0.27.1 h1:OEq30qZjvh5g3tPaXApC/vaHrfJVQULERb905mdHdH8= +riverqueue.com/riverpro/driver v0.27.1/go.mod h1:mYlDDwJ8VZOL0kA6aBWBqmgJNHF2vm/yQU/4sqbFQjo= +riverqueue.com/riverpro/driver/riverpropgxv5 v0.27.1 h1:lQp6Zkztn2Kf0E3ng/oWbqw4fz2HDmoKfbxIQFonYWI= +riverqueue.com/riverpro/driver/riverpropgxv5 v0.27.1/go.mod h1:7QgCgfHmpQVekwQ0IXsn1/Zto8cGbD4wdYu9vlbvPKI= +riverqueue.com/riverpro/driver/riverprosqlite v0.27.1 h1:i0wbVijysnzH/kR7/QH7p3qWsgsAbYrwDG79Y7f89gw= +riverqueue.com/riverpro/driver/riverprosqlite v0.27.1/go.mod h1:oeqo26u1SFQDm1GMkb68ge4qbeELH4k6F1iCx4u5Cs0= riverqueue.com/riverui v0.17.0 h1:iUkQ2zoxrAjqTjk1R5WUK7/PMM/EseTkUgmwYEzsp6E= riverqueue.com/riverui v0.17.0/go.mod h1:5EsPg9ORURjHkeBkY+SYesppOnh9Nb+3AY+1cFcNKWM= diff --git a/riverproui/pro_handler_test.go b/riverproui/pro_handler_test.go index 5267f075..e0f55d64 100644 --- a/riverproui/pro_handler_test.go +++ b/riverproui/pro_handler_test.go @@ -1,9 +1,11 @@ package riverproui import ( + "bytes" "context" "encoding/json" "fmt" + "io" "log/slog" "net/http" "net/http/httptest" @@ -12,6 +14,7 @@ import ( "github.com/google/uuid" "github.com/jackc/pgx/v5" "github.com/stretchr/testify/require" + _ "modernc.org/sqlite" "github.com/riverqueue/river" "github.com/riverqueue/river/riverdbtest" @@ -21,6 +24,7 @@ import ( "riverqueue.com/riverpro" "riverqueue.com/riverpro/driver" "riverqueue.com/riverpro/driver/riverpropgxv5" + "riverqueue.com/riverpro/driver/riverprosqlite" "riverqueue.com/riverui" "riverqueue.com/riverui/internal/handlertest" @@ -61,59 +65,118 @@ func TestProHandlerIntegration(t *testing.T) { return client, driver, tx } - createHandler := func(t *testing.T, bundle uiendpoints.Bundle) http.Handler { - t.Helper() - - logger := riversharedtest.Logger(t) - opts := &riverui.HandlerOpts{ - DevMode: true, - Endpoints: bundle, - LiveFS: false, // Disable LiveFS to avoid needing projectRoot - Logger: logger, - } - handler, err := riverui.NewHandler(opts) - require.NoError(t, err) - return handler - } - testRunner := func(exec riverdriver.Executor, dbDriver riverdriver.Driver[pgx.Tx], makeAPICall handlertest.APICallFunc) { - ctx := context.Background() - - proExec, ok := exec.(driver.ProExecutor) - require.True(t, ok) proDriver, ok := dbDriver.(driver.ProDriver[pgx.Tx]) require.True(t, ok) + _ = runProHandlerRequests(t, schema, exec, proDriver.GetProExecutor(), makeAPICall) + } - _ = protestfactory.PeriodicJob(ctx, t, proExec, nil) - - queue := testfactory.Queue(ctx, t, exec, nil) - - workflowID := uuid.New() - require.NoError(t, proDriver.GetProExecutor().WorkflowInsertMany(ctx, &driver.WorkflowInsertManyParams{ - IDs: []string{workflowID.String()}, - Names: []string{workflowID.String()}, - Schema: schema, - })) - _ = testfactory.Job(ctx, t, exec, &testfactory.JobOpts{Metadata: uicommontest.MustMarshalJSON(t, map[string]uuid.UUID{"workflow_id": workflowID})}) - workflowID2 := uuid.New() - require.NoError(t, proDriver.GetProExecutor().WorkflowInsertMany(ctx, &driver.WorkflowInsertManyParams{ - IDs: []string{workflowID2.String()}, - Names: []string{workflowID2.String()}, - Schema: schema, - })) - _ = testfactory.Job(ctx, t, exec, &testfactory.JobOpts{Metadata: uicommontest.MustMarshalJSON(t, map[string]uuid.UUID{"workflow_id": workflowID2})}) - - // Verify OSS features endpoint is mounted and returns success even w/ Pro bundle: - makeAPICall(t, "FeaturesGet", http.MethodGet, "/api/features", nil) - - makeAPICall(t, "PeriodicJobList", http.MethodGet, "/api/pro/periodic-jobs", nil) - makeAPICall(t, "ProducerList", http.MethodGet, "/api/pro/producers?queue_name="+queue.Name, nil) - makeAPICall(t, "WorkflowCancel", http.MethodPost, fmt.Sprintf("/api/pro/workflows/%s/cancel", workflowID), nil) - makeAPICall(t, "WorkflowGet", http.MethodGet, fmt.Sprintf("/api/pro/workflows/%s", workflowID2), nil) - makeAPICall(t, "WorkflowList", http.MethodGet, "/api/pro/workflows", nil) + handlertest.RunIntegrationTest(t, createClient, createBundle, newProHandler, testRunner) +} + +func TestProHandlerIntegrationSQLite(t *testing.T) { + t.Parallel() + + var ( + ctx = t.Context() + logger = riversharedtest.Logger(t) + workers = river.NewWorkers() + driver = riverprosqlite.New(nil) + ) + river.AddWorker(workers, &uicommontest.NoOpWorker{}) + + schema := riverdbtest.TestSchema(ctx, t, driver, &riverdbtest.TestSchemaOpts{ + DisableReuse: true, + ProcurePool: func(ctx context.Context, schema string) (any, string) { + return riversharedtest.DBPoolSQLite(ctx, t, schema), "" + }, + }) + + client, err := riverpro.NewClient(driver, &riverpro.Config{ + Config: river.Config{ + Logger: logger, + Schema: schema, + Workers: workers, + }, + }) + require.NoError(t, err) + + handler := newProHandler(t, NewEndpoints(client, nil)) + makeAPICall := func(t *testing.T, testCaseName, method, path string, payload []byte) { + t.Helper() + + t.Run(testCaseName, func(t *testing.T) { + var body io.Reader + if len(payload) > 0 { + body = bytes.NewReader(payload) + } + + recorder := httptest.NewRecorder() + handler.ServeHTTP(recorder, httptest.NewRequestWithContext(ctx, method, path, body)) + require.GreaterOrEqual(t, recorder.Code, http.StatusOK) + require.Less(t, recorder.Code, http.StatusMultipleChoices, recorder.Body.String()) + }) } - handlertest.RunIntegrationTest(t, createClient, createBundle, createHandler, testRunner) + cancelledWorkflowID := runProHandlerRequests(t, schema, driver.GetProExecutor(), driver.GetProExecutor(), makeAPICall) + makeAPICall(t, "WorkflowRetry", http.MethodPost, fmt.Sprintf("/api/pro/workflows/%s/retry", cancelledWorkflowID), nil) +} + +func newProHandler(t *testing.T, bundle uiendpoints.Bundle) http.Handler { + t.Helper() + + handler, err := riverui.NewHandler(&riverui.HandlerOpts{ + DevMode: true, + Endpoints: bundle, + LiveFS: false, + Logger: riversharedtest.Logger(t), + }) + require.NoError(t, err) + return handler +} + +func runProHandlerRequests(t *testing.T, schema string, exec riverdriver.Executor, workflowExec driver.ProExecutor, makeAPICall handlertest.APICallFunc) string { + t.Helper() + + ctx := t.Context() + proExec, ok := exec.(driver.ProExecutor) + require.True(t, ok) + + _ = protestfactory.PeriodicJob(ctx, t, proExec, nil) + + queue := testfactory.Queue(ctx, t, exec, nil) + + workflowID := uuid.New() + require.NoError(t, workflowExec.WorkflowInsertMany(ctx, &driver.WorkflowInsertManyParams{ + IDs: []string{workflowID.String()}, + Names: []string{workflowID.String()}, + Schema: schema, + })) + _ = testfactory.Job(ctx, t, exec, &testfactory.JobOpts{Metadata: uicommontest.MustMarshalJSON(t, map[string]string{ + "task": "task_1", + "workflow_id": workflowID.String(), + })}) + workflowID2 := uuid.New() + require.NoError(t, workflowExec.WorkflowInsertMany(ctx, &driver.WorkflowInsertManyParams{ + IDs: []string{workflowID2.String()}, + Names: []string{workflowID2.String()}, + Schema: schema, + })) + _ = testfactory.Job(ctx, t, exec, &testfactory.JobOpts{Metadata: uicommontest.MustMarshalJSON(t, map[string]string{ + "task": "task_2", + "workflow_id": workflowID2.String(), + })}) + + // Verify OSS features endpoint is mounted and returns success even w/ Pro bundle: + makeAPICall(t, "FeaturesGet", http.MethodGet, "/api/features", nil) + + makeAPICall(t, "PeriodicJobList", http.MethodGet, "/api/pro/periodic-jobs", nil) + makeAPICall(t, "ProducerList", http.MethodGet, "/api/pro/producers?queue_name="+queue.Name, nil) + makeAPICall(t, "WorkflowCancel", http.MethodPost, fmt.Sprintf("/api/pro/workflows/%s/cancel", workflowID), nil) + makeAPICall(t, "WorkflowGet", http.MethodGet, fmt.Sprintf("/api/pro/workflows/%s", workflowID2), nil) + makeAPICall(t, "WorkflowList", http.MethodGet, "/api/pro/workflows", nil) + + return workflowID.String() } func TestProMountedEndpointResponses(t *testing.T) {