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

When manually switching the connection it resets the search path #27

Closed
rpbaltazar opened this issue Apr 2, 2020 · 2 comments
Closed
Labels
bug Something isn't working

Comments

@rpbaltazar
Copy link
Contributor

Steps to reproduce

Apartment::Tenant.switch!('existing_tenant')
puts Apartment::Tenant.current # prints 'existing_tenant'
ActiveRecord::Base.connected_to(role: :writing) do
  puts Apartment::Tenant.current # prints 'existing_tenant'
  puts Apartment.connection.schema_search_path # does not print 'existing_tenant'
end

Expected behavior

Apartment::Tenant.switch!('existing_tenant')
puts Apartment::Tenant.current # prints 'existing_tenant'
ActiveRecord::Base.connected_to(role: :writing) do
  puts Apartment::Tenant.current # prints 'existing_tenant'
  puts Apartment.connection.schema_search_path # prints 'existing_tenant'
end

Actual behavior

System configuration

  • Database: Postgresql 12.1

  • Apartment version: 2.3.0

  • Apartment config (in config/initializers/apartment.rb or so):

    • use_schemas: true
  • Rails (or ActiveRecord) version: 6.0.2.1

  • Ruby version: 2.6.5

@rpbaltazar rpbaltazar added the bug Something isn't working label Apr 2, 2020
@rpbaltazar
Copy link
Contributor Author

It also happens when switching the connection on a model level:

Apartment::Tenant.switch('existing_tenant')
User::Account.connected_to(role: :reading) do
  User::Account.first(10)
end

will return the first 10 user accounts under the default schema instead of the switched schema

@rpbaltazar
Copy link
Contributor Author

Resolved with #28

rpbaltazar added a commit that referenced this issue Apr 9, 2020
When monkeypatching the table name a series of other problems were showing up in our application due to Rails caching mechanism.

After digging in the internals of active record, and given that this is only for postgresql schemas, it made more sense to update the arel table visitor to include the schema in the table name when building the query. This way the tables will always be prepended with the schema.

This has been feature flagged to keep the default behaviour the same as before.
The find_by cache key has also been revisited. This way, the cached find_by statements will be cached with tenant information in the cache key, avoiding the colliding keys when switching tenants.

E.g.
Setting.find_by(key: 'something', string_value: 'amazing') would cache the query "SELECT \"settings\".* FROM \"public\".\"settings\" WHERE \"settings\".\"key\" = $1 AND \"settings\".\"string_value\" = $2 LIMIT $3" with the proper binds, but associated with the key [:key, :string_value].

This meant that when switching tenants and running the same query again, we would get the previous result.
Adding the tenant to the array of keys for the cache solves the issue.
rpbaltazar added a commit that referenced this issue Apr 15, 2020
…nant

- Monkeypatch `connected_to` rails active record method to try to ensure that whenever we switch connection we connect to the proper tenant

- Removed `allow_prepend_tenant_name` configuration because we ran into concurrency issues. When the connection goes back to the pool its attributes are set with the old values and we were getting queries being made to the wrong tenant. I still think that using this prepend_tenant seems like a good idea but I'll need further testing and investigation on how to make it safe. There is a bug reported in the original apartment gem that seems to report similar issues (influitive/apartment#186)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant