Skip to content
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

Apartment doesn't work with ActionController::Live #304

Open
jordan-brough opened this issue Dec 16, 2024 · 7 comments
Open

Apartment doesn't work with ActionController::Live #304

jordan-brough opened this issue Dec 16, 2024 · 7 comments

Comments

@jordan-brough
Copy link
Contributor

jordan-brough commented Dec 16, 2024

When you add ActionController::Live to a controller, the controller code doesn't run in the correct tenant.

This appears to be because ActionController::Live uses a separate thread:

The final caveat is that your actions are executed in a separate thread than the main thread.

(See https://github.com/rails/rails/blob/v7.1.5.1/actionpack/lib/action_controller/metal/live.rb#L36-L38)

In order to get ActionController::Live to work, I had to override new_controller_thread in my controller in my app:

def new_controller_thread
  # using the elevator directly because it doesn't seem to get triggered with ActionController::Live
  tenant = CustomElevator.new(nil).parse_tenant_name(request)
  super { Apartment::Tenant.switch(tenant) { yield } }
end
@mnovelo
Copy link
Collaborator

mnovelo commented Jan 3, 2025

Ok, good to know. Sounds like you're able to handle this without any changes to Apartment?

@jordan-brough
Copy link
Contributor Author

Yes but it would be great if Apartment wired that up automatically. I can take a pass at putting together a PR if that sounds ok.

@mnovelo
Copy link
Collaborator

mnovelo commented Jan 9, 2025

This wasn't included in v3.2.0, but I hope to add such support in v4.0.0. Your help would be greatly appreciated! #312

@macfanatic
Copy link

I wonder if we can introduce support easily enough with something like the following as an included initializer in the engine, that wouldn't require any app changes and automatically modify this required method when spawning the new thread.

# support defined in engine
module Apartment
  # to be included in an ActionController::Live controller
  module Live
    def new_controller_thread
      tenant = CustomElevator.new(nil).parse_tenant_name(request)
      super { Apartment::Tenant.switch(tenant) { yield } }
    end
  end
end

# initializer in engine
ActiveSupport.on_load(:action_controller) do
  module Live
    include ::Apartment::Live
  end
end

Ignore the naming, and I didn't test this out. But perhaps not a huge amount of work to support.

@mnovelo
Copy link
Collaborator

mnovelo commented Jan 14, 2025

I'm not very familiar with ActionController::Live, but I do think something like that would work!

@AlessandroTolomio
Copy link

Hello everyone!

I'm implementing a stream solution for an AI feature in my multi-tenant application, and luckily, I found this thread. Everything seemed to be working with the proposed solution, but occasionally, the database schema doesn’t stay set correctly.

I’m trying to figure it out, but since it's an intermittent issue, debugging isn't easy.

I'm using Puma with the following configuration:

  • Min threads: 5
  • Max threads: 5
  • Workers: 6

It can run smoothly 10-15 times in a row, and then fail 5 times in a row.

Has anyone experienced something similar or has any suggestions?

@mnovelo
Copy link
Collaborator

mnovelo commented Feb 10, 2025

@AlessandroTolomio, the current version of the Apartment gem does not handle multithreading very well. We have not used Pumas multi-threading because of it and instead use a single Puma thread for each instance of our application. I don't recall how the database pooling from Rails works across Puma threads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants