-
Notifications
You must be signed in to change notification settings - Fork 92
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
Make more client services into startstop.Service
#262
Conversation
// | ||
// Unlike other services, it's given a background context so that it doesn't | ||
// cancel on normal stops. | ||
if err := c.monitor.Start(context.Background()); err != nil { //nolint:contextcheck |
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.
Won't return an error, but like other services, it has the option to do so.
// In case of error, stop any services that might have started. This | ||
// is safe because even services that were never started will still | ||
// tolerate being stopped. | ||
startstop.StopAllParallel(c.services) |
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.
We now try and stop anything that started even in the event of a start error, which is kind of nice.
Here, we aim to move in a direction where the client can treat most of its subservices generically by starting/stopping the notifier as a generic service, along with converting three other smaller services over to use the `startstop.Service` interface: * Client monitor. (This ends up cleaning up its internal code significantly, and has a major improvement on its test coverage and robustness.) * The client's statistics logging loop. * The client's leadership change handling loop. Both the latter two are very small functions, so I implement the new function `startstop.StartStopFunc` which similar to `river.WorkFunc`, provides an easy way to get a small service using only a function, which keeps the code quite clean. It's going to take a few more changes to get our full simplification change, but you can already see the beginnings of it as many services can be started and stopped in ~one line: func (c *Client[TTx]) signalStopComplete(ctx context.Context) { // Wait for producers and elector to exit: c.wg.Wait() // Stop all mainline services where stop order isn't important. startstop.StopAllParallel(c.services) By the end of it, both the elector and producers will also become services, and we'll be able to fully eliminate the wait group, along with the stop channels and the roundabout stop functions like `signalStopComplete`. The idea is that the client itself will also become a start/stop service, and itself become protected against being started multiple times, or potential races where `Start`/`Stop` may be called by multiple goroutines.
} | ||
} | ||
}() |
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.
This all just moves down from above where it was previously in a closure.
|
||
shutdownOnce: &sync.Once{}, | ||
shutdownCh: make(chan struct{}), | ||
doneCh: make(chan struct{}), |
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.
Lets us get rid of a whole bunch of vars, which is nice. We add a StartStopStress
test case also, so we're now much more certain that this code works than before.
b1a01f5
to
69ef596
Compare
@bgentry I'm sure you're just going to love this one lol, but I promise it's for the greater good. |
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Actually wasn't too bad at all :) |
Hah, okay that's a relief :) Thanks! |
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
) Follow up changes like #253, #262, and #263 to make the producer a start/stop service, giving it a more predictable way to invoke start and stop, making it safer to run and cleaning up caller code where it's used in the client and test cases. With all these changes taken together we'll have every service in the client using the same unified service interface, which will clean up code and let us write some neat utilities to operate across all of them. Aside from that, we clean up the producer in ways to bring it more inline with other code, like making logging uniform and having the constructor return only a `*producer` instead of `(*producer, error)` that needs to be checked despite an error always being indicative of a bug in this context. We expand the test suite, adding tests like (1) verifying that workers are really stopped when `workCtx` is cancelled, (2) verifying that the max worker slots work as expected and that the producer limits its fetches, and (3) start/stop stress. Like with #263, we give the producer a poll only mode, which also gets the full test barrage using a shared test transaction instead of full database pool. Also like #263, this poll only mode is still prospective and not yet put to full use (although it will be soon).
Here, we aim to move in a direction where the client can treat most of
its subservices generically by starting/stopping the notifier as a
generic service, along with converting three other smaller services over
to use the
startstop.Service
interface:Client monitor. (This ends up cleaning up its internal code
significantly, and has a major improvement on its test coverage and
robustness.)
The client's statistics logging loop.
The client's leadership change handling loop.
Both the latter two are very small functions, so I implement the new
function
startstop.StartStopFunc
which similar toriver.WorkFunc
,provides an easy way to get a small service using only a function, which
keeps the code quite clean.
It's going to take a few more changes to get our full simplification
change, but you can already see the beginnings of it as many services
can be started and stopped in ~one line:
By the end of it, both the elector and producers will also become
services, and we'll be able to fully eliminate the wait group, along
with the stop channels and the roundabout stop functions like
signalStopComplete
. The idea is that the client itself will alsobecome a start/stop service, and itself become protected against being
started multiple times, or potential races where
Start
/Stop
may becalled by multiple goroutines.