-
Notifications
You must be signed in to change notification settings - Fork 93
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add middleware system for jobs #584
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package river | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/riverqueue/river/rivertype" | ||
) | ||
|
||
// JobMiddlewareDefaults is an embeddable struct that provides default | ||
// implementations for the rivertype.JobMiddleware. Use of this struct is | ||
// recommended in case rivertype.JobMiddleware is expanded in the future so that | ||
// existing code isn't unexpectedly broken during an upgrade. | ||
type JobMiddlewareDefaults struct{} | ||
|
||
func (l *JobMiddlewareDefaults) Insert(ctx context.Context, params *rivertype.JobInsertParams, doInner func(ctx context.Context) (*rivertype.JobInsertResult, error)) (*rivertype.JobInsertResult, error) { | ||
return doInner(ctx) | ||
} | ||
|
||
func (l *JobMiddlewareDefaults) InsertMany(ctx context.Context, manyParams []*rivertype.JobInsertParams, doInner func(ctx context.Context) (int, error)) (int, error) { | ||
return doInner(ctx) | ||
} | ||
|
||
func (l *JobMiddlewareDefaults) Work(ctx context.Context, job *rivertype.JobRow, doInner func(ctx context.Context) error) error { | ||
return doInner(ctx) | ||
} | ||
Comment on lines
+15
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think for this to be the most useful it would need to be customizable on a per-job basis. I'm wondering what that looks like in practice with this design. Like what if I wanted to add a middleware that uses some aspect of the worker or args to dynamically determine what to do? (maybe some optional interface gets fulfilled by either of those types to indicate to the middleware what it should do). The problem with trying to do that here is the args have already been encoded, so there's no longer any access to the underlying Additionally, this might be further exposing the somewhat confusing split between There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I ended up putting |
||
|
||
// func (l *JobLifecycleDefaults) InsertBegin(ctx context.Context, params *rivertype.JobLifecycleInsertParams) (context.Context, error) { | ||
// return ctx, nil | ||
// } | ||
|
||
// func (l *JobLifecycleDefaults) InsertEnd(ctx context.Context, res *rivertype.JobInsertResult) error { | ||
// return nil | ||
// } | ||
|
||
// func (l *JobLifecycleDefaults) InsertManyBegin(ctx context.Context, manyParams []*rivertype.JobLifecycleInsertParams) (context.Context, error) { | ||
// return ctx, nil | ||
// } | ||
|
||
// func (l *JobLifecycleDefaults) InsertManyEnd(ctx context.Context, manyParams []*rivertype.JobLifecycleInsertParams) error { | ||
// return nil | ||
// } | ||
|
||
// func (l *JobLifecycleDefaults) WorkBegin(ctx context.Context, job *rivertype.JobRow) (context.Context, error) { | ||
// return ctx, nil | ||
// } | ||
|
||
// func (l *JobLifecycleDefaults) WorkEnd(ctx context.Context, job *rivertype.JobRow) error { return nil } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package river | ||
|
||
import "github.com/riverqueue/river/rivertype" | ||
|
||
var _ rivertype.JobMiddleware = &JobMiddlewareDefaults{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So not 100% sure on this one yet, but the "insert" part of the middleware needs to receive a type that's not a
JobRow
because we don't have a job row yet. I basically tookJobInsertParams
, duplicated it, and promoted it torivertype
. The types are different for now, but they can be type converted to one another because they have the same fields. I basically did this because I like the naming ofJobInsertParams
, but they could also be the same type or even slightly different types with a couple fields dropped (CreatedAt
for example, which is only needed for time injection).Either way,
JobInsertParams
stays internal for now, so it should leave refactoring flexibility ...There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about pulling arg encoding out of this helper and passing the middleware functions a type that includes raw unencoded
JobArgs
? My thought is that this unlocks more dynamic behavior, because middleware then have the ability to do type assertions againstJobArgs
including to assert interface implementations.The downside is they lose the ability to directly access the encoded json bytes, but then I'm not sure I know of any cases where that's desirable. For metadata, sure, but not for args.