Skip to content
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

Passing a riverClient to a worker? #87

Closed
chrboe opened this issue Dec 1, 2023 · 2 comments · Fixed by #88
Closed

Passing a riverClient to a worker? #87

chrboe opened this issue Dec 1, 2023 · 2 comments · Fixed by #88

Comments

@chrboe
Copy link

chrboe commented Dec 1, 2023

I am trying to trigger a job from within another job (think: send a notification when a long-running job is complete). This requires that I have access to the riverClient in the worker context.

I could pass the client to the worker, like

river.AddWorker[action.SomeArgs](workers, &action.SomeWorker{DbPool: dbPool, RiverClient: riverClient})

but that creates a chicken-egg problem because I need an initialized Workers to create the riverClient.

Adding the worker after initialization does not work either because NewClient does not accept an empty Workers:

workers := river.NewWorkers()

riverClient, err := river.NewClient[pgx.Tx](riverpgxv5.New(dbPool.Pool), &river.Config{
    Workers: workers,
})
if err != nil {
    panic(err)
}

river.AddWorker[action.SomeArgs](workers, &action.SomeWorker{DbPool: dbPool, RiverClient: riverClient})

// panic: at least one Worker must be added to the Workers bundle

Adding some worker that does not depend on the client does actually work, but is kind of awkward:

workers := river.NewWorkers()
river.AddWorker[action.DummyArgs](workers, &action.DummyWorker{})

riverClient, err := river.NewClient[pgx.Tx](riverpgxv5.New(dbPool.Pool), &river.Config{
    Workers: workers,
})
if err != nil {
    panic(err)
}

river.AddWorker[action.SomeArgs](workers, &action.SomeWorker{DbPool: dbPool, RiverClient: riverClient})

// -> both workers work as expected

Is there any other "pattern" to achieve this? If not, I think the status quo should at least be documented somewhere.

brandur added a commit that referenced this issue Dec 2, 2023
This one's in pursuit of trying to solve #87, where it's difficult to
inject a River client into a worker because trying to initialize a
client with the workers bundle empty is an error, creating a chicken and
egg problem.

There's no real reason to disallow a zero worker bundle from the
constructor, and in fact a lot of our tests already add additional
workers after the client was originally initialized (although
`newTestClient` injects a default worker, which is why there's no
error). If it's a useful pattern for us, it's probably useful for other
users too.

Here, move the zero workers check from the constructor over to the
`Start` function instead. While it seems okay to initialize a client
without workers, starting it without any does seem like a potential
problem that we'd want to keep an eye out for.

Fixes #87.
@brandur
Copy link
Contributor

brandur commented Dec 2, 2023

Hey @chrboe, thanks for the detailed report.

Hm, this indeed seem like a problem. I talked it over with Blake and we think that there's not really that much good rationale behind ensuring that there's a non-zero worker bundle in NewClient — we in fact add workers all the time after NewClient in our test suite even.

I opened #88 proposing that we move the zero worker check from NewClient to Start instead, meaning that it should be easy for you to create a client, then add workers that depend on the client, then after doing to start the client.

@bgentry also proposed we provide an easy way to make a client available via a context key passed to each work function. We'll put that on the backburner for now, but it could be a nice improvement if this becomes an obviously common pattern that people are using.

brandur added a commit that referenced this issue Dec 2, 2023
This one's in pursuit of trying to solve #87, where it's difficult to
inject a River client into a worker because trying to initialize a
client with the workers bundle empty is an error, creating a chicken and
egg problem.

There's no real reason to disallow a zero worker bundle from the
constructor, and in fact a lot of our tests already add additional
workers after the client was originally initialized (although
`newTestClient` injects a default worker, which is why there's no
error). If it's a useful pattern for us, it's probably useful for other
users too.

Here, move the zero workers check from the constructor over to the
`Start` function instead. While it seems okay to initialize a client
without workers, starting it without any does seem like a potential
problem that we'd want to keep an eye out for.

Fixes #87.
brandur added a commit that referenced this issue Dec 2, 2023
This one's in pursuit of trying to solve #87, where it's difficult to
inject a River client into a worker because trying to initialize a
client with the workers bundle empty is an error, creating a chicken and
egg problem.

There's no real reason to disallow a zero worker bundle from the
constructor, and in fact a lot of our tests already add additional
workers after the client was originally initialized (although
`newTestClient` injects a default worker, which is why there's no
error). If it's a useful pattern for us, it's probably useful for other
users too.

Here, move the zero workers check from the constructor over to the
`Start` function instead. While it seems okay to initialize a client
without workers, starting it without any does seem like a potential
problem that we'd want to keep an eye out for.

Fixes #87.
@brandur
Copy link
Contributor

brandur commented Dec 2, 2023

We just cut a new release for 0.0.11 that includes the changes in #88.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants