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
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ src/routeTree.gen.ts

# Other files to ignore
package-lock.json
.claude/settings.local.json
19 changes: 19 additions & 0 deletions .storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Decorator, Preview } from "@storybook/react-vite";

import { withThemeByClassName } from "@storybook/addon-themes";
import { ReactRenderer } from "@storybook/react-vite";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import {
createMemoryHistory,
createRootRoute,
Expand Down Expand Up @@ -82,6 +83,23 @@ export const withThemeProvider: Decorator = (StoryFn) => (
</ThemeProvider>
);

const storybookQueryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
},
},
});

/**
* Decorator that provides a React Query client for stories that use hooks.
*/
export const withQueryClient: Decorator = (StoryFn) => (
<QueryClientProvider client={storybookQueryClient}>
<StoryFn />
</QueryClientProvider>
);

/**
* Decorator that sets user settings for stories
* Can be overridden per story using parameters.settings
Expand Down Expand Up @@ -113,6 +131,7 @@ declare module "@storybook/react-vite" {

const preview: Preview = {
decorators: [
withQueryClient,
withFeatures,
withSettings,
withRouter,
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Workflow detail: add support for new River Pro workflow features, including signals and timers. [PR #567](https://github.com/riverqueue/riverui/pull/567).

### Fixed

- Workflow detail: add on-canvas zoom controls for click/touch navigation and improve controls styling for dark mode. [PR #524](https://github.com/riverqueue/riverui/pull/524).
Expand All @@ -17,6 +21,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Job delete actions: require confirmation before deleting a single job or selected jobs in bulk. [Fixes #545](https://github.com/riverqueue/riverui/issues/545). [PR #546](https://github.com/riverqueue/riverui/pull/546).
- Workflow detail: show the backend's not-found message instead of crashing when a workflow ID does not exist. [PR #564](https://github.com/riverqueue/riverui/pull/564).
- Job detail: render a dedicated `Snoozed` timeline step for scheduled jobs with prior attempts so snoozed jobs no longer show negative wait durations. [PR #565](https://github.com/riverqueue/riverui/pull/565).
- Workflow detail: source wait phases, timers, signal evidence, and task wait reasons from backend workflow wait metadata instead of frontend-derived placeholders. [PR #567](https://github.com/riverqueue/riverui/pull/567).
- Workflow detail: redesign wait inspection around a denser task-side summary, structured term/timer/signal cards, reliable full-node selection, Storybook workflow detail coverage below the diagram, and a tighter details layout that keeps job metadata with the main job card. [PR #567](https://github.com/riverqueue/riverui/pull/567).
- Workflow detail: add a task-signal debugger backed by task-scoped River Pro signal reads while keeping workflow detail wait data summary-only. [PR #567](https://github.com/riverqueue/riverui/pull/567).
- Workflow detail: clarify wait inspection with a compact condition matrix, phase-aware match summaries, explicit signal scopes, condition-type icons, per-term CEL definitions, and denser timer/dependency/signal evidence. [PR #567](https://github.com/riverqueue/riverui/pull/567).
- Workflow detail: replace the flat narrative event list with a task timeline that keeps dependencies in one place, emphasizes wait evidence and durations, avoids showing staged events before a task is actually runnable, and uses a lower-noise milestone hierarchy. [PR #567](https://github.com/riverqueue/riverui/pull/567).
- Workflow detail: remove the not-started wait preview from dependency progress milestones. [PR #567](https://github.com/riverqueue/riverui/pull/567).

## [v0.15.0] - 2026-02-26

Expand Down
2 changes: 1 addition & 1 deletion handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func TestNewHandlerIntegration(t *testing.T) {
return server
}

testRunner := func(exec riverdriver.Executor, makeAPICall handlertest.APICallFunc) {
testRunner := func(exec riverdriver.Executor, _ riverdriver.Driver[pgx.Tx], makeAPICall handlertest.APICallFunc) {
ctx := context.Background()

makeURL := fmt.Sprintf
Expand Down
4 changes: 2 additions & 2 deletions internal/handlertest/handlertest.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

type APICallFunc = func(t *testing.T, testCaseName, method, path string, payload []byte)

func RunIntegrationTest[TClient any](t *testing.T, createClient func(ctx context.Context, tb testing.TB, logger *slog.Logger) (TClient, riverdriver.Driver[pgx.Tx], pgx.Tx), createBundle func(client TClient, tx pgx.Tx) uiendpoints.Bundle, createHandler func(t *testing.T, bundle uiendpoints.Bundle) http.Handler, testRunner func(exec riverdriver.Executor, makeAPICall APICallFunc)) {
func RunIntegrationTest[TClient any](t *testing.T, createClient func(ctx context.Context, tb testing.TB, logger *slog.Logger) (TClient, riverdriver.Driver[pgx.Tx], pgx.Tx), createBundle func(client TClient, tx pgx.Tx) uiendpoints.Bundle, createHandler func(t *testing.T, bundle uiendpoints.Bundle) http.Handler, testRunner func(exec riverdriver.Executor, dbDriver riverdriver.Driver[pgx.Tx], makeAPICall APICallFunc)) {
t.Helper()

var (
Expand Down Expand Up @@ -70,5 +70,5 @@ func RunIntegrationTest[TClient any](t *testing.T, createClient func(ctx context
})
}

testRunner(exec, makeAPICall)
testRunner(exec, driver, makeAPICall)
}
15 changes: 4 additions & 11 deletions riverproui/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,18 @@ func (e *endpoints[TTx]) Extensions(ctx context.Context) (map[string]bool, error
return nil, err
}

indexResults, err := execTx.IndexesExist(ctx, &riverdriver.IndexesExistParams{
IndexNames: []string{
"river_job_workflow_list_active",
"river_job_workflow_scheduling",
},
Schema: schema,
})
hasWorkflowV2Tables, err := prohandler.HasWorkflowV2Tables(ctx, execTx, schema)
if err != nil {
return nil, err
}

hasWorkflows := indexResults["river_job_workflow_list_active"] || indexResults["river_job_workflow_scheduling"]

return map[string]bool{
"durable_periodic_jobs": hasPeriodicJobTable,
"producer_queries": true,
"workflow_queries": true,
"workflow_queries": hasWorkflowV2Tables,
"has_client_table": hasClientTable,
"has_producer_table": hasProducerTable,
"has_sequence_table": hasSequenceTable,
"has_workflows": hasWorkflows,
}, nil
}

Expand Down Expand Up @@ -181,6 +172,8 @@ func (e *endpoints[TTx]) MountEndpoints(archetype *baseservice.Archetype, logger
apiendpoint.Mount(mux, prohandler.NewWorkflowGetEndpoint(bundle), mountOpts),
apiendpoint.Mount(mux, prohandler.NewWorkflowListEndpoint(bundle), mountOpts),
apiendpoint.Mount(mux, prohandler.NewWorkflowRetryEndpoint(bundle), mountOpts),
apiendpoint.Mount(mux, prohandler.NewWorkflowTaskSignalsEndpoint(bundle), mountOpts),
apiendpoint.Mount(mux, prohandler.NewWorkflowTaskWaitDiagnosticsEndpoint(bundle), mountOpts),
)

return endpoints
Expand Down
49 changes: 44 additions & 5 deletions riverproui/endpoints_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"riverqueue.com/riverpro/driver/riverpropgxv5"

"riverqueue.com/riverui/internal/uicommontest"
"riverqueue.com/riverui/riverproui/internal/prohandler"
)

func TestProEndpointsExtensions(t *testing.T) {
Expand Down Expand Up @@ -184,26 +185,64 @@ func TestProEndpointsExtensions(t *testing.T) {
})
})

t.Run("WorkflowsDetection", func(t *testing.T) {
t.Run("WorkflowQueryDetection", func(t *testing.T) {
t.Parallel()

t.Run("NoWorkflowIndexes", func(t *testing.T) {
t.Run("WorkflowV2TablesPresent", func(t *testing.T) {
t.Parallel()

bundle := setup(ctx, t)

_, err := bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_list_active;`)
ext, err := bundle.endpoint.Extensions(ctx)
require.NoError(t, err)
require.True(t, ext["workflow_queries"])
})

t.Run("LegacyIndexesWithoutV2Tables", func(t *testing.T) {
t.Parallel()

bundle := setup(ctx, t)

for _, table := range prohandler.WorkflowV2TableNames {
_, err := bundle.tx.Exec(ctx, `DROP TABLE IF EXISTS `+table+` CASCADE;`)
require.NoError(t, err)
}
_, err := bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_active_idx;`)
require.NoError(t, err)
_, err = bundle.tx.Exec(ctx, `CREATE INDEX river_job_workflow_active_idx ON river_job (workflow_id) WHERE workflow_id IS NOT NULL;`)
require.NoError(t, err)

ext, err := bundle.endpoint.Extensions(ctx)
require.NoError(t, err)
require.False(t, ext["workflow_queries"])
})

t.Run("NoWorkflowV2Tables", func(t *testing.T) {
t.Parallel()

bundle := setup(ctx, t)

var err error
for _, table := range prohandler.WorkflowV2TableNames {
_, err = bundle.tx.Exec(ctx, `DROP TABLE IF EXISTS `+table+` CASCADE;`)
require.NoError(t, err)
}
_, err = bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_list_active;`)
require.NoError(t, err)
_, err = bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_scheduling;`)
require.NoError(t, err)
_, err = bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_active_idx;`)
require.NoError(t, err)
_, err = bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_inactive_idx;`)
require.NoError(t, err)

ext, err := bundle.endpoint.Extensions(ctx)
require.NoError(t, err)
require.False(t, ext["has_workflows"])
require.False(t, ext["workflow_queries"])
})
})

t.Run("StaticAttributesAlwaysTrue", func(t *testing.T) {
t.Run("QueryAttributes", func(t *testing.T) {
t.Parallel()

bundle := setup(ctx, t)
Expand Down
21 changes: 11 additions & 10 deletions riverproui/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,21 @@ require (
github.com/riverqueue/river/rivershared v0.35.1
github.com/riverqueue/river/rivertype v0.35.1
github.com/stretchr/testify v1.11.1
riverqueue.com/riverpro v0.23.2
riverqueue.com/riverpro/driver v0.23.2
riverqueue.com/riverpro/driver/riverpropgxv5 v0.23.2
riverqueue.com/riverpro v0.24.0-rc.1
riverqueue.com/riverpro/driver v0.24.0-rc.1
riverqueue.com/riverpro/driver/riverpropgxv5 v0.24.0-rc.1
riverqueue.com/riverui v0.15.0
)

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/gabriel-vasile/mimetype v1.4.13 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.30.1 // indirect
github.com/google/cel-go v0.27.0 // indirect
github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
Expand All @@ -42,9 +45,13 @@ require (
go.opentelemetry.io/otel/trace v1.29.0 // indirect
go.uber.org/goleak v1.3.0 // indirect
golang.org/x/crypto v0.48.0 // indirect
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.41.0 // indirect
golang.org/x/text v0.36.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
)

Expand All @@ -53,10 +60,4 @@ retract (
v0.12.0 // Improper release process, not fully usable
)

// replace riverqueue.com/riverui => ../

// replace riverqueue.com/riverpro => ../../riverpro

// replace riverqueue.com/riverpro/driver => ../../riverpro/driver

// replace riverqueue.com/riverpro/driver/riverpropgxv5 => ../../riverpro/driver/riverpropgxv5
replace riverqueue.com/riverui => ../
34 changes: 24 additions & 10 deletions riverproui/go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
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=
Expand All @@ -11,8 +15,10 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w=
github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo=
github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw=
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/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6 h1:D/V0gu4zQ3cL2WKeVNVM4r2gLxGGf6McLwgXzRTo2RQ=
Expand Down Expand Up @@ -75,25 +81,33 @@ go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt3
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
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/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
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=
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
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=
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.23.2 h1:sLa3yu4X+Pp4CCs3qqjsTpjbpppe6CPs+UoE6oXaRHI=
riverqueue.com/riverpro v0.23.2/go.mod h1:GB/taad40wxHlLegaKV6kr/4h99HPUaJkWqADJKsp7M=
riverqueue.com/riverpro/driver v0.23.2 h1:tg0gvR+R4M3HzET358FwuSdv5TnBFrJXHzPPtS3CSpQ=
riverqueue.com/riverpro/driver v0.23.2/go.mod h1:d9s4bU6SeNl76KUp+io4k/EpJi0dvAO6NCcoXeo5q7k=
riverqueue.com/riverpro/driver/riverpropgxv5 v0.23.2 h1:Uceq9aDer9xuZCPlwj4Y+GP7lYpKCbyJtWBp+igNrUs=
riverqueue.com/riverpro/driver/riverpropgxv5 v0.23.2/go.mod h1:aYZgQfQ3DSEsJEKLVZ3cKj1BhpWZZWDsxl3AP1N3bUw=
riverqueue.com/riverui v0.15.0 h1:7Xm/tqv63jZrGSv4X2u4zpAvbtXSs835Qk4RFonBDdk=
riverqueue.com/riverui v0.15.0/go.mod h1:J4fH8+zPe1cqmYWuMWVJdDdMmq1U2UPVofyOczGZNnw=
riverqueue.com/riverpro v0.24.0-rc.1 h1:4f4hlA9rb8RmtmvKlSudCXZgIv03ypFazIkqjwUOlyQ=
riverqueue.com/riverpro v0.24.0-rc.1/go.mod h1:jINiXsyxuMRNrf21KLLfO2JpDqRPjZWl98cO7Acb8jg=
riverqueue.com/riverpro/driver v0.24.0-rc.1 h1:G4hC22saVptb81bK/Ggj1QSA7COGI7lTAjz0GVgKR48=
riverqueue.com/riverpro/driver v0.24.0-rc.1/go.mod h1:d9s4bU6SeNl76KUp+io4k/EpJi0dvAO6NCcoXeo5q7k=
riverqueue.com/riverpro/driver/riverpropgxv5 v0.24.0-rc.1 h1:JHb3u57fnbG0hjuPStrPZw+sCg6b3TpHpRnl0PlBA/Q=
riverqueue.com/riverpro/driver/riverpropgxv5 v0.24.0-rc.1/go.mod h1:7W60TU/5AAuCbU/XaRnxbmGyDZu84SA5XVQBwgYKEW0=
Loading
Loading