Skip to content

Commit 7e135b3

Browse files
authored
Merge pull request #580 from riverqueue/prerelease
Prepare v0.16.0
2 parents 7c15c35 + 82ce755 commit 7e135b3

55 files changed

Lines changed: 11051 additions & 621 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ src/routeTree.gen.ts
1111

1212
# Other files to ignore
1313
package-lock.json
14+
.claude/settings.local.json
1415
.npmrc

.storybook/preview.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { Decorator, Preview } from "@storybook/react-vite";
22

33
import { withThemeByClassName } from "@storybook/addon-themes";
44
import { ReactRenderer } from "@storybook/react-vite";
5+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
56
import {
67
createMemoryHistory,
78
createRootRoute,
@@ -82,6 +83,23 @@ export const withThemeProvider: Decorator = (StoryFn) => (
8283
</ThemeProvider>
8384
);
8485

86+
const storybookQueryClient = new QueryClient({
87+
defaultOptions: {
88+
queries: {
89+
retry: false,
90+
},
91+
},
92+
});
93+
94+
/**
95+
* Decorator that provides a React Query client for stories that use hooks.
96+
*/
97+
export const withQueryClient: Decorator = (StoryFn) => (
98+
<QueryClientProvider client={storybookQueryClient}>
99+
<StoryFn />
100+
</QueryClientProvider>
101+
);
102+
85103
/**
86104
* Decorator that sets user settings for stories
87105
* Can be overridden per story using parameters.settings
@@ -113,6 +131,7 @@ declare module "@storybook/react-vite" {
113131

114132
const preview: Preview = {
115133
decorators: [
134+
withQueryClient,
116135
withFeatures,
117136
withSettings,
118137
withRouter,

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [v0.16.0] - 2026-05-19
11+
12+
Version 0.16.0 includes support for the all new workflow engine in River Pro v0.24.0, including signals, timers, and greater introspection capabilities.
13+
14+
⚠️ Workflow features in v0.16.0 rely on new workflow-related tables that are part of the riverpro v0.24.0 release. River UI's workflow queries may be disabled or poorly performing until the River Pro migration v006 has been applied in your database.
15+
16+
### Added
17+
18+
- Workflow detail: add support for new River Pro workflow features, including signals and timers. [PR #567](https://github.com/riverqueue/riverui/pull/567).
19+
1020
### Fixed
1121

1222
- 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).
@@ -17,6 +27,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1727
- 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).
1828
- 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).
1929
- 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).
30+
- 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).
31+
- 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).
32+
- 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).
33+
- 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).
34+
- 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).
35+
- Workflow detail: remove the not-started wait preview from dependency progress milestones. [PR #567](https://github.com/riverqueue/riverui/pull/567).
2036

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

handler_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func TestNewHandlerIntegration(t *testing.T) {
6262
return server
6363
}
6464

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

6868
makeURL := fmt.Sprintf

internal/handlertest/handlertest.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import (
2020

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

23-
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)) {
23+
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)) {
2424
t.Helper()
2525

2626
var (
@@ -70,5 +70,5 @@ func RunIntegrationTest[TClient any](t *testing.T, createClient func(ctx context
7070
})
7171
}
7272

73-
testRunner(exec, makeAPICall)
73+
testRunner(exec, driver, makeAPICall)
7474
}

riverproui/endpoints.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -122,27 +122,18 @@ func (e *endpoints[TTx]) Extensions(ctx context.Context) (map[string]bool, error
122122
return nil, err
123123
}
124124

125-
indexResults, err := execTx.IndexesExist(ctx, &riverdriver.IndexesExistParams{
126-
IndexNames: []string{
127-
"river_job_workflow_list_active",
128-
"river_job_workflow_scheduling",
129-
},
130-
Schema: schema,
131-
})
125+
hasWorkflowV2Tables, err := prohandler.HasWorkflowV2Tables(ctx, execTx, schema)
132126
if err != nil {
133127
return nil, err
134128
}
135129

136-
hasWorkflows := indexResults["river_job_workflow_list_active"] || indexResults["river_job_workflow_scheduling"]
137-
138130
return map[string]bool{
139131
"durable_periodic_jobs": hasPeriodicJobTable,
140132
"producer_queries": true,
141-
"workflow_queries": true,
133+
"workflow_queries": hasWorkflowV2Tables,
142134
"has_client_table": hasClientTable,
143135
"has_producer_table": hasProducerTable,
144136
"has_sequence_table": hasSequenceTable,
145-
"has_workflows": hasWorkflows,
146137
}, nil
147138
}
148139

@@ -181,6 +172,8 @@ func (e *endpoints[TTx]) MountEndpoints(archetype *baseservice.Archetype, logger
181172
apiendpoint.Mount(mux, prohandler.NewWorkflowGetEndpoint(bundle), mountOpts),
182173
apiendpoint.Mount(mux, prohandler.NewWorkflowListEndpoint(bundle), mountOpts),
183174
apiendpoint.Mount(mux, prohandler.NewWorkflowRetryEndpoint(bundle), mountOpts),
175+
apiendpoint.Mount(mux, prohandler.NewWorkflowTaskSignalsEndpoint(bundle), mountOpts),
176+
apiendpoint.Mount(mux, prohandler.NewWorkflowTaskWaitDiagnosticsEndpoint(bundle), mountOpts),
184177
)
185178

186179
return endpoints

riverproui/endpoints_test.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"riverqueue.com/riverpro/driver/riverpropgxv5"
1717

1818
"riverqueue.com/riverui/internal/uicommontest"
19+
"riverqueue.com/riverui/riverproui/internal/prohandler"
1920
)
2021

2122
func TestProEndpointsExtensions(t *testing.T) {
@@ -184,26 +185,64 @@ func TestProEndpointsExtensions(t *testing.T) {
184185
})
185186
})
186187

187-
t.Run("WorkflowsDetection", func(t *testing.T) {
188+
t.Run("WorkflowQueryDetection", func(t *testing.T) {
188189
t.Parallel()
189190

190-
t.Run("NoWorkflowIndexes", func(t *testing.T) {
191+
t.Run("WorkflowV2TablesPresent", func(t *testing.T) {
191192
t.Parallel()
192193

193194
bundle := setup(ctx, t)
194195

195-
_, err := bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_list_active;`)
196+
ext, err := bundle.endpoint.Extensions(ctx)
197+
require.NoError(t, err)
198+
require.True(t, ext["workflow_queries"])
199+
})
200+
201+
t.Run("LegacyIndexesWithoutV2Tables", func(t *testing.T) {
202+
t.Parallel()
203+
204+
bundle := setup(ctx, t)
205+
206+
for _, table := range prohandler.WorkflowV2TableNames {
207+
_, err := bundle.tx.Exec(ctx, `DROP TABLE IF EXISTS `+table+` CASCADE;`)
208+
require.NoError(t, err)
209+
}
210+
_, err := bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_active_idx;`)
211+
require.NoError(t, err)
212+
_, err = bundle.tx.Exec(ctx, `CREATE INDEX river_job_workflow_active_idx ON river_job (workflow_id) WHERE workflow_id IS NOT NULL;`)
213+
require.NoError(t, err)
214+
215+
ext, err := bundle.endpoint.Extensions(ctx)
216+
require.NoError(t, err)
217+
require.False(t, ext["workflow_queries"])
218+
})
219+
220+
t.Run("NoWorkflowV2Tables", func(t *testing.T) {
221+
t.Parallel()
222+
223+
bundle := setup(ctx, t)
224+
225+
var err error
226+
for _, table := range prohandler.WorkflowV2TableNames {
227+
_, err = bundle.tx.Exec(ctx, `DROP TABLE IF EXISTS `+table+` CASCADE;`)
228+
require.NoError(t, err)
229+
}
230+
_, err = bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_list_active;`)
196231
require.NoError(t, err)
197232
_, err = bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_scheduling;`)
198233
require.NoError(t, err)
234+
_, err = bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_active_idx;`)
235+
require.NoError(t, err)
236+
_, err = bundle.tx.Exec(ctx, `DROP INDEX IF EXISTS river_job_workflow_inactive_idx;`)
237+
require.NoError(t, err)
199238

200239
ext, err := bundle.endpoint.Extensions(ctx)
201240
require.NoError(t, err)
202-
require.False(t, ext["has_workflows"])
241+
require.False(t, ext["workflow_queries"])
203242
})
204243
})
205244

206-
t.Run("StaticAttributesAlwaysTrue", func(t *testing.T) {
245+
t.Run("QueryAttributes", func(t *testing.T) {
207246
t.Parallel()
208247

209248
bundle := setup(ctx, t)

riverproui/go.mod

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,44 +7,51 @@ toolchain go1.25.7
77
require (
88
github.com/google/uuid v1.6.0
99
github.com/jackc/pgx/v5 v5.9.2
10-
github.com/riverqueue/apiframe v0.0.0-20260203020001-b4fe7e4d61bc
11-
github.com/riverqueue/river v0.35.1
12-
github.com/riverqueue/river/riverdriver v0.35.1
13-
github.com/riverqueue/river/rivershared v0.35.1
14-
github.com/riverqueue/river/rivertype v0.35.1
10+
github.com/riverqueue/apiframe v0.0.0-20260428012848-22cd8d31a740
11+
github.com/riverqueue/river v0.37.1
12+
github.com/riverqueue/river/riverdriver v0.37.1
13+
github.com/riverqueue/river/rivershared v0.37.1
14+
github.com/riverqueue/river/rivertype v0.37.1
1515
github.com/stretchr/testify v1.11.1
16-
riverqueue.com/riverpro v0.23.2
17-
riverqueue.com/riverpro/driver v0.23.2
18-
riverqueue.com/riverpro/driver/riverpropgxv5 v0.23.2
19-
riverqueue.com/riverui v0.15.0
16+
riverqueue.com/riverpro v0.24.0
17+
riverqueue.com/riverpro/driver v0.24.0
18+
riverqueue.com/riverpro/driver/riverpropgxv5 v0.24.0
19+
riverqueue.com/riverui v0.16.0-rc.1
2020
)
2121

2222
require (
23+
cel.dev/expr v0.25.1 // indirect
24+
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
2325
github.com/davecgh/go-spew v1.1.1 // indirect
2426
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
2527
github.com/go-playground/locales v0.14.1 // indirect
2628
github.com/go-playground/universal-translator v0.18.1 // indirect
27-
github.com/go-playground/validator/v10 v10.30.1 // indirect
29+
github.com/go-playground/validator/v10 v10.30.2 // indirect
30+
github.com/google/cel-go v0.27.0 // indirect
2831
github.com/jackc/pgerrcode v0.0.0-20250907135507-afb5586c32a6 // indirect
2932
github.com/jackc/pgpassfile v1.0.0 // indirect
3033
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
3134
github.com/jackc/puddle/v2 v2.2.2 // indirect
3235
github.com/leodido/go-urn v1.4.0 // indirect
3336
github.com/pmezard/go-difflib v1.0.0 // indirect
34-
github.com/riverqueue/river/riverdriver/riverpgxv5 v0.35.1 // indirect
37+
github.com/riverqueue/river/riverdriver/riverpgxv5 v0.37.1 // indirect
3538
github.com/rs/cors v1.11.1 // indirect
3639
github.com/samber/slog-http v1.12.1 // indirect
37-
github.com/tidwall/gjson v1.18.0 // indirect
40+
github.com/tidwall/gjson v1.19.0 // indirect
3841
github.com/tidwall/match v1.2.0 // indirect
3942
github.com/tidwall/pretty v1.2.1 // indirect
4043
github.com/tidwall/sjson v1.2.5 // indirect
4144
go.opentelemetry.io/otel v1.29.0 // indirect
4245
go.opentelemetry.io/otel/trace v1.29.0 // indirect
4346
go.uber.org/goleak v1.3.0 // indirect
44-
golang.org/x/crypto v0.48.0 // indirect
47+
golang.org/x/crypto v0.51.0 // indirect
48+
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 // indirect
4549
golang.org/x/sync v0.20.0 // indirect
46-
golang.org/x/sys v0.41.0 // indirect
47-
golang.org/x/text v0.36.0 // indirect
50+
golang.org/x/sys v0.44.0 // indirect
51+
golang.org/x/text v0.37.0 // indirect
52+
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 // indirect
53+
google.golang.org/genproto/googleapis/rpc v0.0.0-20260217215200-42d3e9bedb6d // indirect
54+
google.golang.org/protobuf v1.36.11 // indirect
4855
gopkg.in/yaml.v3 v3.0.1 // indirect
4956
)
5057

@@ -53,10 +60,10 @@ retract (
5360
v0.12.0 // Improper release process, not fully usable
5461
)
5562

56-
// replace riverqueue.com/riverui => ../
57-
5863
// replace riverqueue.com/riverpro => ../../riverpro
5964

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

6267
// replace riverqueue.com/riverpro/driver/riverpropgxv5 => ../../riverpro/driver/riverpropgxv5
68+
69+
// replace riverqueue.com/riverui => ../

0 commit comments

Comments
 (0)