Module: ActiveSupport

Defined in:
lib/quilt_rails/monkey_patches/active_support_reloader.rb

Overview

The default ActiveSupport::Reloader memoizes ‘@should_reload` for the lifetime of each request. This is a problem for quilt_rails apps because:

  • QuiltRails::ReactRenderable#render holds an exclusive lock until the Node server returns a result

  • Any controller calls during Node rendering (e.g., GraphQL fetches) will hang if they try to obtain a lock

  • Class unloading needs a lock, and so nested controller calls risk deadlocking whenever @should_reload is true

Forcing ‘@should_reload` evaluation at the start of each thread prevents nested controller calls from attempting class unloading. This eliminates one source of lock contention.

The affected flow is:

  • A developer saves a change to a Ruby file

  • The developer refreshes their browser

Rails processes the request:

  • Thread0 - ActiveSupport::Reloader is called by middleware

  • Thread0 - An exclusive class unloader lock is obtained, classes are

    unloaded, and the lock is released
    
  • Thread0 - ‘Quilt::ReactRenderable#render_react` calls `reverse_proxy`,

    which grabs a general exclusive lock
    
  • Node - starts rendering, and calls out to a Rails controller for data

  • Thread1 - ActiveSupport::Reloader is called by the second controller’s

    middleware
    
  • Thread1 - ‘@should_reload` is still true, so an attempt is made to grab an

    exclusive class unloader lock
    
  • Thread1 - waits for Thread0 to release its lock; Thread0 never unlocks

    because it needs Thread1's result
    

Defined Under Namespace

Classes: Reloader