Skip to content

Commit 4c5579e

Browse files
committed
Code review feedback to allow legacy hooks/middlewares to work unchanged
1 parent 50adaf0 commit 4c5579e

2 files changed

Lines changed: 160 additions & 7 deletions

File tree

internal/pluginlookup/plugin_lookup.go

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package pluginlookup
22

33
import (
4+
"context"
45
"sync"
56

67
"github.com/riverqueue/river/rivertype"
@@ -86,26 +87,28 @@ func NewPluginLookup(plugins []rivertype.Plugin) PluginLookupInterface {
8687
}
8788

8889
// NormalizePlugins converts hook, middleware, and plugin registrations into a
89-
// single plugin slice. Hook and middleware registrations must already satisfy
90-
// rivertype.Plugin to participate.
90+
// single plugin slice while preserving legacy hook and middleware registrations
91+
// that don't yet opt into Plugin.
9192
func NormalizePlugins(hooks []rivertype.Hook, middlewares []rivertype.Middleware, plugins []rivertype.Plugin) []rivertype.Plugin {
9293
normalizedPlugins := make([]rivertype.Plugin, 0, len(hooks)+len(middlewares)+len(plugins))
9394

9495
for _, hook := range hooks {
9596
if plugin, ok := hook.(rivertype.Plugin); ok {
9697
normalizedPlugins = append(normalizedPlugins, plugin)
98+
continue
9799
}
100+
101+
normalizedPlugins = append(normalizedPlugins, newHookPlugin(hook))
98102
}
99103
for _, middleware := range middlewares {
100104
if plugin, ok := middleware.(rivertype.Plugin); ok {
101105
normalizedPlugins = append(normalizedPlugins, plugin)
106+
continue
102107
}
108+
109+
normalizedPlugins = append(normalizedPlugins, newMiddlewarePlugin(middleware))
103110
}
104-
for _, plugin := range plugins {
105-
if plugin != nil {
106-
normalizedPlugins = append(normalizedPlugins, plugin)
107-
}
108-
}
111+
normalizedPlugins = append(normalizedPlugins, plugins...)
109112

110113
return normalizedPlugins
111114
}
@@ -141,6 +144,89 @@ func (c *emptyPluginLookup) ByKind(kind PluginKind) []rivertype.Plugin {
141144
return nil
142145
}
143146

147+
//
148+
// hookPlugin
149+
//
150+
151+
// hookPlugin wraps a legacy hook so it can participate in plugin lookup.
152+
type hookPlugin struct {
153+
hook rivertype.Hook
154+
}
155+
156+
func newHookPlugin(hook rivertype.Hook) rivertype.Plugin {
157+
return &hookPlugin{hook: hook}
158+
}
159+
160+
func (p *hookPlugin) IsPlugin() bool { return true }
161+
func (p *hookPlugin) IsHook() bool { return true }
162+
163+
func (p *hookPlugin) InsertBegin(ctx context.Context, params *rivertype.JobInsertParams) error {
164+
hook, ok := p.hook.(rivertype.HookInsertBegin)
165+
if !ok {
166+
return nil
167+
}
168+
return hook.InsertBegin(ctx, params)
169+
}
170+
171+
func (p *hookPlugin) Start(ctx context.Context, params *rivertype.HookPeriodicJobsStartParams) error {
172+
hook, ok := p.hook.(rivertype.HookPeriodicJobsStart)
173+
if !ok {
174+
return nil
175+
}
176+
return hook.Start(ctx, params)
177+
}
178+
179+
func (p *hookPlugin) WorkBegin(ctx context.Context, job *rivertype.JobRow) error {
180+
hook, ok := p.hook.(rivertype.HookWorkBegin)
181+
if !ok {
182+
return nil
183+
}
184+
return hook.WorkBegin(ctx, job)
185+
}
186+
187+
func (p *hookPlugin) WorkEnd(ctx context.Context, job *rivertype.JobRow, err error) error {
188+
hook, ok := p.hook.(rivertype.HookWorkEnd)
189+
if !ok {
190+
return err
191+
}
192+
return hook.WorkEnd(ctx, job, err)
193+
}
194+
195+
//
196+
// middlewarePlugin
197+
//
198+
199+
// middlewarePlugin wraps a legacy middleware so it can participate in plugin
200+
// lookup.
201+
type middlewarePlugin struct {
202+
middleware rivertype.Middleware
203+
}
204+
205+
func newMiddlewarePlugin(middleware rivertype.Middleware) rivertype.Plugin {
206+
return &middlewarePlugin{middleware: middleware}
207+
}
208+
209+
func (p *middlewarePlugin) IsPlugin() bool { return true }
210+
func (p *middlewarePlugin) IsMiddleware() bool {
211+
return true
212+
}
213+
214+
func (p *middlewarePlugin) InsertMany(ctx context.Context, manyParams []*rivertype.JobInsertParams, doInner func(context.Context) ([]*rivertype.JobInsertResult, error)) ([]*rivertype.JobInsertResult, error) {
215+
middleware, ok := p.middleware.(rivertype.JobInsertMiddleware)
216+
if !ok {
217+
return doInner(ctx)
218+
}
219+
return middleware.InsertMany(ctx, manyParams, doInner)
220+
}
221+
222+
func (p *middlewarePlugin) Work(ctx context.Context, job *rivertype.JobRow, doInner func(context.Context) error) error {
223+
middleware, ok := p.middleware.(rivertype.WorkerMiddleware)
224+
if !ok {
225+
return doInner(ctx)
226+
}
227+
return middleware.Work(ctx, job, doInner)
228+
}
229+
144230
//
145231
// JobPluginLookup
146232
//

internal/pluginlookup/plugin_lookup_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,40 @@ func TestPluginLookup(t *testing.T) {
204204

205205
wg.Wait()
206206
})
207+
208+
t.Run("LooksUpLegacyHooksAndMiddleware", func(t *testing.T) {
209+
t.Parallel()
210+
211+
legacyHook := &testLegacyHookInsertBegin{}
212+
legacyMiddleware := &testLegacyMiddlewareJobInsert{}
213+
214+
lookup, isPluginLookup := NewPluginLookup(NormalizePlugins(
215+
[]rivertype.Hook{legacyHook},
216+
[]rivertype.Middleware{legacyMiddleware},
217+
nil,
218+
)).(*pluginLookup)
219+
require.True(t, isPluginLookup)
220+
221+
hookPlugins := lookup.ByKind(HookKindInsertBegin)
222+
require.Len(t, hookPlugins, 1)
223+
224+
hook, isHookInsertBegin := hookPlugins[0].(rivertype.HookInsertBegin)
225+
require.True(t, isHookInsertBegin)
226+
require.NoError(t, hook.InsertBegin(context.Background(), &rivertype.JobInsertParams{}))
227+
require.True(t, legacyHook.insertBeginCalled)
228+
229+
middlewarePlugins := lookup.ByKind(MiddlewareKindJobInsert)
230+
require.Len(t, middlewarePlugins, 1)
231+
232+
middleware, isJobInsertMiddleware := middlewarePlugins[0].(rivertype.JobInsertMiddleware)
233+
require.True(t, isJobInsertMiddleware)
234+
_, err := middleware.InsertMany(context.Background(), []*rivertype.JobInsertParams{{}}, func(context.Context) ([]*rivertype.JobInsertResult, error) {
235+
legacyMiddleware.doInnerCalled = true
236+
return nil, nil
237+
})
238+
require.NoError(t, err)
239+
require.True(t, legacyMiddleware.doInnerCalled)
240+
})
207241
}
208242

209243
//
@@ -349,3 +383,36 @@ func (t *testMiddlewareWorker) IsPlugin() bool { return true }
349383
func (t *testMiddlewareWorker) Work(ctx context.Context, job *rivertype.JobRow, doInner func(context.Context) error) error {
350384
return doInner(ctx)
351385
}
386+
387+
//
388+
// testLegacyHookInsertBegin
389+
//
390+
391+
var _ rivertype.HookInsertBegin = &testLegacyHookInsertBegin{}
392+
393+
type testLegacyHookInsertBegin struct {
394+
insertBeginCalled bool
395+
}
396+
397+
func (t *testLegacyHookInsertBegin) IsHook() bool { return true }
398+
399+
func (t *testLegacyHookInsertBegin) InsertBegin(ctx context.Context, params *rivertype.JobInsertParams) error {
400+
t.insertBeginCalled = true
401+
return nil
402+
}
403+
404+
//
405+
// testLegacyMiddlewareJobInsert
406+
//
407+
408+
var _ rivertype.JobInsertMiddleware = &testLegacyMiddlewareJobInsert{}
409+
410+
type testLegacyMiddlewareJobInsert struct {
411+
doInnerCalled bool
412+
}
413+
414+
func (t *testLegacyMiddlewareJobInsert) IsMiddleware() bool { return true }
415+
416+
func (t *testLegacyMiddlewareJobInsert) InsertMany(ctx context.Context, manyParams []*rivertype.JobInsertParams, doInner func(context.Context) ([]*rivertype.JobInsertResult, error)) ([]*rivertype.JobInsertResult, error) {
417+
return doInner(ctx)
418+
}

0 commit comments

Comments
 (0)