📜 ⬆️ ⬇️

Saydkik-suicide

It so happened that there was a need to prematurely stop an already running side-turner . And, as everyone involved already knows, the running task cannot be stopped by regular means - this is simply not provided for by the architecture. And when the sidekick task began to be performed, then nothing would stop it. Of course, the Internet immediately found a solution with the killing of the ruby ​​process and with the cancellation of restarting it , but for obvious reasons neither the application developers, nor the developers of the sidebar can arrange this solution.


image


As a result, the decision came from no waiting and it turned out to be extremely simple and obvious. In general, the idea can be formulated very briefly: the sidekick process should kill itself, and we just have to tell it when to do it. All the code that was previously just run in the sidekick, we will run in a separate thread inside the sidekick process. And, in parallel to him, we will launch a trad that will follow the instructions from the outside so that the sidekick process will kill itself. Having received instructions to kill himself, the follow-up thread kills a neighbor and kills himself.


In general, this approach is not limited only when using sidekika and long-lasting garbage can be anywhere. So let's abstract from the sidekick and try to summarize our approach.


First, you need to decide how we will tell the newsgroup that we need to die. And in the case of Ruby, it is best to use an external message transfer mechanism and radishes in this case will fit perfectly. And the message transfer mechanism built into radishes is better not to use for several reasons, the main of which is the lack of deferred reading. If, for any reason, the trade killer misses the message, then our killing process may not take place at all. Suppose we ask the cedar process to die very quickly - right after we start it. There is a chance that the trade killer will not exist at all.


So, the process of checking a message is quite simple and straightforward:


until $redis.del("sidekiq:killer:#{self.identificator}") == 1 do sleep 0.1 end main_thread.kill 

And the identificator method will be responsible for the unique key component in the radish.


The main trad with the codename "victim" after his natural death should leave to make sure that the killer will not wait for him forever:


  begin self.perform_without_thread(*args) rescue $redis.set("sidekiq:killer:#{self.identificator}", 1) end 

Again, like a real killer, our trade killer must be sure that the victim is dead:


  until !!main_thread.status == false do sleep 0.1 end 

Well, in the end, our common saykik-process waits until the end of all two processes:


  [watcher_thread, main_thread].each(&:join) 

And now let's combine the above code together to get a complete module for direct addition to existing long-playing processes:


 module SidekiqKiller def perform_with_thread(*args) main_thread = Thread.new do begin self.perform_without_thread(*args) rescue $redis.set("sidekiq:killer:#{self.identificator}", 1) end end watcher_thread = Thread.new do until $redis.del("sidekiq:killer:#{self.identificator}") == 1 do sleep 0.1 end main_thread.kill until !!main_thread.status == false do sleep 0.1 end end [watcher_thread, main_thread].each(&:join) end alias_method_chain :perform, :thread end 

In our system, the mechanism of clerical suicide of workers was used to forcefully stop the worker from running a separate instance of the staging server. The mechanism, of course, trouble-free, but too expensive from memory. As a result, this part of the system was rewritten in pure Ruby, optimizing and getting rid of the sidekick and related libraries.


Which of these can be concluded? Yes, no, except that we are all mortal. Also, probably the fact that one should not do so, if there is no really urgent need.


image


')

Source: https://habr.com/ru/post/305824/


All Articles