Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ jobs:
name: Go lint
runs-on: ubuntu-latest
env:
GOLANGCI_LINT_VERSION: v1.64.6
GOLANGCI_LINT_VERSION: v2.0.0
permissions:
contents: read
# allow read access to pull request. Use with `only-new-issues` option.
Expand All @@ -102,7 +102,7 @@ jobs:
run: make fake_assets

- name: Lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v7
with:
# golangci-lint needs to be run separately for every Go module, and
# its GitHub Action doesn't provide any way to do that. Have it fetch
Expand Down
158 changes: 87 additions & 71 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
issues:
exclude:
- 'Error return value of .(\w+\.Rollback(.*)). is not checked'
version: "2"

linters:
presets:
- bugs
- comment
- format
- performance
- style
- test
- unused
default: all

disable:
- intrange # encourages for loops to range over integers like `for i := range(5)` instead of a C-style for

# disabled, but which we should enable with discussion
- wrapcheck # checks that errors are wrapped; currently not done anywhere

Expand All @@ -23,76 +12,103 @@ linters:
- testpackage # requires tests in test packages like `river_test`

# disabled because they're annoying/bad
- err113 # wants all errors to be defined as variables at the package level; quite obnoxious
- cyclop # screams into the void at "cyclomatic complexity"
- funlen # screams when functions are more than 60 lines long; what are we even doing here guys
- interfacebloat # we do in fact want >10 methods on the Adapter interface or wherever we see fit.
- gocognit # yells that "cognitive complexity" is too high; why
- gocyclo # ANOTHER "cyclomatic complexity" checker (see also "cyclop" and "gocyclo")
- godox # bans TODO statements; total non-starter at the moment
- err113 # wants all errors to be defined as variables at the package level; quite obnoxious
- maintidx # ANOTHER ANOTHER "cyclomatic complexity" lint (see also "cyclop" and "gocyclo")
- mnd # detects "magic numbers", which it defines as any number; annoying
- nestif # yells when if blocks are nested; what planet do these people come from?
- ireturn # bans returning interfaces; questionable as is, but also buggy as hell; very, very annoying
- lll # restricts maximum line length; annoying
- mnd # detects "magic numbers", which it defines as any number; annoying
- nlreturn # requires a blank line before returns; annoying
- wsl # a bunch of style/whitespace stuff; annoying

linters-settings:
depguard:
rules:
all:
files: ["$all"]
allow:
deny:
- desc: "Use `github.com/google/uuid` package for UUIDs instead."
pkg: "github.com/xtgo/uuid"
settings:
depguard:
rules:
all:
files: ["$all"]
deny:
- desc: Use `github.com/google/uuid` package for UUIDs instead.
pkg: github.com/xtgo/uuid

exhaustive:
default-signifies-exhaustive: true
forbidigo:
forbid:
- msg: Use `require` variants instead.
pattern: ^assert\.
- msg: Use `Func` suffix for function variables instead.
pattern: Fn\b
- msg: Use built-in `max` function instead.
pattern: \bmath\.Max\b
- msg: Use built-in `min` function instead.
pattern: \bmath\.Min\b

forbidigo:
forbid:
- msg: "Use `require` variants instead."
p: '^assert\.'
- msg: "Use `Func` suffix for function variables instead."
p: 'Fn\b'
- msg: "Use built-in `max` function instead."
p: '\bmath\.Max\b'
- msg: "Use built-in `min` function instead."
p: '\bmath\.Min\b'
gomoddirectives:
replace-local: true

gci:
sections:
- Standard
- Default
- Prefix(github.com/riverqueue)
- Prefix(riverqueue.com/riverui)
gosec:
excludes:
- G404 # use of non-crypto random; overly broad for our use case

gomoddirectives:
replace-local: true
revive:
rules:
- name: unused-parameter
disabled: true

revive:
rules:
tagliatelle:
case:
rules:
json: snake

tagliatelle:
case:
rules:
json: snake
testifylint:
enable-all: true
disable:
- go-require

varnamelen:
ignore-names:
- db
- eg
- f
- i
- id
- j
- mu
- r
- rw # common convention for http.ResponseWriter
- sb # common convention for string builder
- t
- tt # common convention for table tests
- tx
- w
- wg

exclusions:
generated: lax
presets:
- comments
- common-false-positives
- legacy
- std-error-handling
rules:
- path: (.+)\.go$
text: Error return value of .(\w+\.Rollback(.*)). is not checked

testifylint:
enable-all: true
disable:
- go-require
formatters:
enable:
- gci
- gofmt
- gofumpt
- goimports

varnamelen:
ignore-names:
- db
- eg
- f
- i
- id
- j
- mu
- r # common for http.Request
- rw # common for http.ResponseWriter
- sb # common convention for string builder
- t
- tt # common convention for table tests
- tx
- w # common for http.ResponseWriter
- wg
settings:
gci:
sections:
- Standard
- Default
- Prefix(github.com/riverqueue)
- Prefix(riverqueue.com/riverpro)
3 changes: 1 addition & 2 deletions cmd/riverui/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ import (
"github.com/jackc/pgx/v5/pgxpool"
"github.com/rs/cors"
sloghttp "github.com/samber/slog-http"
"riverqueue.com/riverui"

"github.com/riverqueue/apiframe/apimiddleware"
"github.com/riverqueue/river"
"github.com/riverqueue/river/riverdriver/riverpgxv5"

"riverqueue.com/riverui"
)

func main() {
Expand Down
9 changes: 4 additions & 5 deletions handler_api_endpoint.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import (

"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgtype"
"riverqueue.com/riverui/internal/dbsqlc"
"riverqueue.com/riverui/internal/querycacher"
"riverqueue.com/riverui/internal/util/pgxutil"

"github.com/riverqueue/apiframe/apiendpoint"
"github.com/riverqueue/apiframe/apierror"
Expand All @@ -23,10 +26,6 @@ import (
"github.com/riverqueue/river/rivershared/util/ptrutil"
"github.com/riverqueue/river/rivershared/util/sliceutil"
"github.com/riverqueue/river/rivertype"

"riverqueue.com/riverui/internal/dbsqlc"
"riverqueue.com/riverui/internal/querycacher"
"riverqueue.com/riverui/internal/util/pgxutil"
)

// A bundle of common utilities needed for many API endpoints.
Expand Down Expand Up @@ -663,7 +662,7 @@ func (*queueUpdateEndpoint) Meta() *apiendpoint.EndpointMeta {

type queueUpdateRequest struct {
Concurrency apitype.ExplicitNullable[ConcurrencyConfig] `json:"concurrency"`
Name string `json:"-" validate:"required"` // from ExtractRaw
Name string `json:"-" validate:"required"` // from ExtractRaw
}

func (req *queueUpdateRequest) ExtractRaw(r *http.Request) error {
Expand Down
29 changes: 14 additions & 15 deletions handler_api_endpoint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"github.com/google/uuid"
"github.com/jackc/pgx/v5"
"github.com/stretchr/testify/require"
"riverqueue.com/riverui/internal/riverinternaltest"
"riverqueue.com/riverui/internal/riverinternaltest/testfactory"

"github.com/riverqueue/apiframe/apiendpoint"
"github.com/riverqueue/apiframe/apierror"
Expand All @@ -20,9 +22,6 @@ import (
"github.com/riverqueue/river/rivershared/startstop"
"github.com/riverqueue/river/rivershared/util/ptrutil"
"github.com/riverqueue/river/rivertype"

"riverqueue.com/riverui/internal/riverinternaltest"
"riverqueue.com/riverui/internal/riverinternaltest/testfactory"
)

type setupEndpointTestBundle struct {
Expand Down Expand Up @@ -412,7 +411,7 @@ func TestAPIHandlerProducerList(t *testing.T) {

resp, err := apitest.InvokeHandler(ctx, endpoint.Execute, testMountOpts(t), &producerListRequest{QueueName: "queue1"})
require.NoError(t, err)
require.Equal(t, 2, len(resp.Data))
require.Len(t, resp.Data, 2)
require.Equal(t, "client1", resp.Data[0].ClientID)
require.Equal(t, 1, resp.Data[0].MaxWorkers)
require.Equal(t, int32(0), resp.Data[0].Running)
Expand All @@ -422,14 +421,14 @@ func TestAPIHandlerProducerList(t *testing.T) {

resp, err = apitest.InvokeHandler(ctx, endpoint.Execute, testMountOpts(t), &producerListRequest{QueueName: "queue2"})
require.NoError(t, err)
require.Equal(t, 1, len(resp.Data))
require.Len(t, resp.Data, 1)
require.Equal(t, "client2", resp.Data[0].ClientID)
require.Equal(t, 3, resp.Data[0].MaxWorkers)
require.Equal(t, int32(5), resp.Data[0].Running)

resp, err = apitest.InvokeHandler(ctx, endpoint.Execute, testMountOpts(t), &producerListRequest{QueueName: "queue3"})
require.NoError(t, err)
require.Equal(t, 0, len(resp.Data))
require.Empty(t, resp.Data)
})
}

Expand Down Expand Up @@ -644,31 +643,31 @@ func TestStateAndCountGetEndpoint(t *testing.T) {

_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateAvailable)})

for i := 0; i < 2; i++ {
for range 2 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateCancelled), FinalizedAt: ptrutil.Ptr(time.Now())})
}

for i := 0; i < 3; i++ {
for range 3 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateCompleted), FinalizedAt: ptrutil.Ptr(time.Now())})
}

for i := 0; i < 4; i++ {
for range 4 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateDiscarded), FinalizedAt: ptrutil.Ptr(time.Now())})
}

for i := 0; i < 5; i++ {
for range 5 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStatePending)})
}

for i := 0; i < 6; i++ {
for range 6 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateRetryable)})
}

for i := 0; i < 7; i++ {
for range 7 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateRunning)})
}

for i := 0; i < 8; i++ {
for range 8 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateScheduled)})
}

Expand All @@ -692,7 +691,7 @@ func TestStateAndCountGetEndpoint(t *testing.T) {
endpoint, bundle := setupEndpoint(ctx, t, newStateAndCountGetEndpoint)

const queryCacheSkipThreshold = 3
for i := 0; i < queryCacheSkipThreshold+1; i++ {
for range queryCacheSkipThreshold + 1 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateAvailable)})
}

Expand All @@ -712,7 +711,7 @@ func TestStateAndCountGetEndpoint(t *testing.T) {
endpoint, bundle := setupEndpoint(ctx, t, newStateAndCountGetEndpoint)

const queryCacheSkipThreshold = 3
for i := 0; i < queryCacheSkipThreshold-1; i++ {
for range queryCacheSkipThreshold - 1 {
_ = testfactory.Job(ctx, t, bundle.exec, &testfactory.JobOpts{State: ptrutil.Ptr(rivertype.JobStateAvailable)})
}

Expand Down
8 changes: 4 additions & 4 deletions handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ import (

"github.com/google/uuid"
"github.com/stretchr/testify/require"
"riverqueue.com/riverui/internal/riverinternaltest"
"riverqueue.com/riverui/internal/riverinternaltest/testfactory"

"github.com/riverqueue/apiframe/apitype"
"github.com/riverqueue/river/rivershared/util/ptrutil"

"riverqueue.com/riverui/internal/riverinternaltest"
"riverqueue.com/riverui/internal/riverinternaltest/testfactory"
)

func TestNewHandlerIntegration(t *testing.T) {
Expand Down Expand Up @@ -128,7 +127,8 @@ func TestNewHandlerIntegration(t *testing.T) {
ByKind: true,
},
},
}}))
},
}))
makeAPICall(t, "QueueResume", http.MethodPut, makeURL("/api/queues/%s/resume", queuePaused.Name), nil)
makeAPICall(t, "StateAndCountGet", http.MethodGet, makeURL("/api/states"), nil)
makeAPICall(t, "WorkflowGet", http.MethodGet, makeURL("/api/workflows/%s", workflowID), nil)
Expand Down
6 changes: 3 additions & 3 deletions internal/querycacher/query_cacher.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import (
"sync"
"time"

"riverqueue.com/riverui/internal/dbsqlc"

"github.com/riverqueue/river/rivershared/baseservice"
"github.com/riverqueue/river/rivershared/startstop"

"riverqueue.com/riverui/internal/dbsqlc"
)

// QueryCacher executes a database query periodically and caches the result. The
Expand All @@ -35,7 +35,7 @@ func NewQueryCacher[TRes any](archetype *baseservice.Archetype, db dbsqlc.DBTX,
// +/- 1s random variance to ticker interval. Makes sure that given multiple
// query caches running simultaneously, they all start and are scheduled a
// little differently to make a thundering herd problem less likely.
randomTickVariance := time.Duration(rand.Float64()*float64(2*time.Second)) - 1*time.Second //nolint:gosec
randomTickVariance := time.Duration(rand.Float64()*float64(2*time.Second)) - 1*time.Second

queryCacher := baseservice.Init(archetype, &QueryCacher[TRes]{
db: db,
Expand Down
Loading
Loading