danielpclark / rutie

“The Tie Between Ruby and Rust.”
MIT License
939 stars 62 forks source link

Dealing with class reloading #151

Closed milgner closed 2 years ago

milgner commented 2 years ago

After integrating some Rutie-based code into our application, I observed frequent crashes of the MRI runtime. It quickly became clear, that these were related to Spring re-loading the classes because as long as DISABLE_SPRING was set to 1, everything ran smoothly.

Since it wasn't clear to me what could be done on the Rust-side of things, I built a work-around that explicitly unloads the classes defined from our Rust code and re-loads them afterwards. Not fully sure, how effective this is but preliminary tests are promising, so here's an example:

module MyGem
 class << self
    def load
      Rutie.new(:my_gem lib_path: "#{__dir__}/../../ext/rust")
           .init("init_my_gem", ".")
      nil
    end

    def unload
      MyGem.send(:remove_const, :RutieDefinedClass)
      nil
    end

   def shutdown
     # some code to shut down our special use-case
   end
end

used through a Rails initialiser:

# Don't initialise this stuff if we're running in the context of a Rake task
unless Rake.methods.include?(:application)
  Rails.application.reloader.before_class_unload do
    # shutdown doesn't do anything if lib wasn't started yet
    MyGem.shutdown
  end

  Rails.application.reloader.after_class_unload do
    MyGem.unload
  end

  Rails.application.reloader.to_prepare do
    MyGem.load
  end
end

Maybe someone with more insight into the Rutie code has an idea where the issue might originate from for a better mitigation or someone else has found a better work-around but I wanted to leave this here in case anyone else encounters the problem.

milgner commented 2 years ago

I'll close this one: after applying the changes outlined in #142, everything works as expected.