-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
[Design] plugins shutdown sequence refactor proposal #3210
Comments
I'll get you some feedback on this soon. |
I might be misreading a bit, but if we consider the public interfaces, is 'stop' the only public interface of these three? Seems like 'stop?' would only be invoked inside a plugin to inquire if it should stop, and 'close' would only be invoked by the plugin as part of of the 'run' method (for inputs) completing. What we have today is a kind of in-band signalling (the LogStash::ShutdownEvent), and you propose an out-of-band signal (plugin.stop). I think this is good, but I wonder if in-band is even needed anymore once we have a way to interrupt with persistence of in-flight state. Thoughts? |
The public interfaces would be
Only One more detail: since only inputs need an out of band signal (they don't receive events, they generate them), filters and outputs can still use the shutdown event. This is good to ensure data safety, changing filters and outputs to use [EDIT] I now think stop? should also be public, since the pipeline needs it to know when to ignore exceptions when plugins are shutting down |
I've created PR #3812 (now #3895) that implements @colinsurprenant original idea with a couple of modifications:
This PR then changes the Plugin API to:
I've opened a meta issue to track which plugins need to be refactored: #3813 |
I've also added a PR against logstash-devutils to add a test most input plugins can use to test that |
Just asking, is there any reason not to have a def running?; !stop?; end it make writing code in plugin a bit more positive.. while running?
end instead of while !stop?
end |
+2 on being positive :-) On Tue, 1 Sep 2015 18:42 Pier-Hugues Pellerin notifications@github.com
|
Note: another common pattern will be Nothing against |
I prefer positive predicates, but in this case |
When persistence lands, won't we want out-of-band signalling to terminate a filter/output? |
Yes they'll need something similar, but I'm not sure if writing that code in advance is the "right thing". Whenever persistence is introduced, this api could move the LogStash::Plugin class, it shouldn't require another huge refactoring since it's just adding new stuff (stop, stop?) |
Votes? :) # stop?
break if stop?
next unless stop?
while !stop?
# ..
end
# stopping?
break if stopping?
next unless stopping?
while !stopping?
# ..
end
# stop_called?
break if stop_called?
next unless stop_called?
while !stop_called?
# ..
end
# stop_requested?
break if stop_requested?
next unless stop_requested?
while !stop_requested?
# ..
end
# should_stop?
break if should_stop?
next unless should_stop?
while !should_stop?
# ..
end
# terminating?
# potentially also renaming plugin.stop to plugin.terminate
break if terminating?
next unless terminating?
while !terminating?
# ..
end
# running?
break unless running?
next if running?
while running?
# ..
end [EDIT] added |
From your examples @jsvd I would avoid the should option, I feels strange to me. On the other side, what is the problem of having only |
I am okay with |
yeah! @ph like being positive! and one can be just the negation of the other. |
I don't like I don't dislike double non-positives ;) |
since we are introducing braking API changes, I would bite the bullet and include the OOB signalling for filters and outputs too. if we postpone we'll have to do another major version bump. also, we'll be ready for persistence when it lands without necessarily doing a major version bump. |
as I commented in #3812 - if we are to break the API and must go through all plugins, any reason to keep |
yep we had this discussion before, I've provided the example of test suites as use of the As for including the OOB signalling for filters/outputs, it will not break the existing API, just increase it (unless we rename |
Refactor work needed on the pluginsInput pluginsInput plugins are now shutdown by an external call to In some plugins extra work must be done in Refactoring an input plugin involves:
Then for testing you can use the shared example provided in elastic/logstash-devutils#32 in the following manner: describe LogStash::Inputs::Http do
let(:port) { rand(5000) + 1025 }
it_behaves_like "an interruptible input plugin" do
let(:config) { { "port" => port } }
end
end Filters and OutputsBoth will still shutdown using the ShutdownEvent sent by the pipeline so no major changes necessary.
|
We need to refactor the shutdown sequence involving the input plugins and establish a clear shutdown semantic.
Current Design
Currently the base plugin class exposes the following methods related to shutdown:
shutdown
finished
teardown
finished?
running?
terminating?
Current input plugin shutdown sequence description:
There are basically 3 situations:
1- all input plugins have exited normally, they have somehow reached the end of their input:
run
method, the plugin thread will exitteardown
method2- a
SIGINT
orSIGTERM
is received and the pipeline needs to terminate the input plugins and the pipeline:Pipeline#shutdown
is called from the signal handler:all input plugins threads are injected an exception + wakeup like this:
thread.raise(LogStash::ShutdownSignal)
thread.wakeup
all input plugins
teardown
methods are called in sequence(b) normally the plugins exit their
run
method and threads at which point the pipeline thread will again call the inputteardown
methods3- an uncatched exception in the input plugin
teardown
method is called from the pipeline threadrun
method again in abegin/retry
Problems
LogStash::ShutdownSignal
exception can happen virtually anywhere, event in theteardown
methodteardown
is called twice on the input plugins in aSIGINT
/SIGTERM
situationSuggested Refactor
Here's my suggestion for a first iteration cleanup. Once cleaned up, we will be able to more easily build upon it and start thinking about decoupling further the plugin execution/lifecycle from the pipeline in further iterations.
We basically need 2 things for the input plugins:
1- signal the plugin it need to stop
2- ask the plugin to do its bookkeeping once it is stopped
For this I suggest that the plugins exposes only 3 methods:
stop
,stop?
andclose
.stop
is called from outside the plugin thread (from the pipeline thread) and is to ask the plugin to stop. this method must be thread-safe bacause it will be called from outside the plugin thread.stop?
returns true if the stop method was called and can be used within the plugin to verify if a stop was requested.close
is called once when the plugin is stopped to perform any final bookkeeping.The way to know a plugin is stopped is simply by waiting the return of the plugin
run
method. When the run method exits and the plugin thread exits, this is only when theclose
method should be called, once.The same semantic can be applied to the filter and output plugins which would support 2 shutdown modes:
1- the current mode of inserting a
SHUTDOWN
event in the queue so that all inflight events will be processed before the filter and output plugins are closed2- a new mode using the
stop
method for an immediate shutdown in which case the inflight events will be lost when not using queue persistence, in other words, with queue persistence, we will be able to do an immediate shutdown without loosing inflight events.The text was updated successfully, but these errors were encountered: