Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 19 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
# ActiveRecord::AllowConnectionFailure

Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/active_record/allow_connection_failure`. To experiment with that code, run `bin/console` for an interactive prompt.
This gem monkeypatches methods inside of `ActiveRecord::QueryCache` and
`ActiveRecord::Migration::CheckPending`.

TODO: Delete this and the text above, and describe your gem
The intention is to allow a Rails application to boot without first establishing
a database connection, enabling AR's query caching mechanism, and checking for
any pending migrations.

## Installation
In practice, this is useful for situations in which you want to boot your app
and check e.g. a `/status` endpoint which does not have a database/ORM
(read: `ActiveRecord`) dependency.

Add this line to your application's Gemfile:
## Associated `Rails` PR

```ruby
gem 'active_record-allow_connection_failure'
```

And then execute:

$ bundle

Or install it yourself as:

$ gem install active_record-allow_connection_failure
For additional context, see the associated Rails
[pull request](https://github.com/rails/rails/issues/22154).

## Usage

TODO: Write usage instructions here
Add this gem to your `Gemfile`:

## Development

After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
```ruby
gem 'active_record-allow_connection_failure'
```

## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/active_record-allow_connection_failure. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.

Bug reports and pull requests are welcome on GitHub at
https://github.com/zipmark/active_record-allow_connection_failure. This project
is intended to be a safe, welcoming space for collaboration, and contributors
are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.

## License

The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).

6 changes: 3 additions & 3 deletions active_record-allow_connection_failure.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ Gem::Specification.new do |spec|
spec.require_paths = ["lib"]

spec.add_development_dependency "bundler", "~> 1.11"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0"

spec.add_runtime_dependency "rails", ">= 4.2"
spec.add_runtime_dependency "rails", ">= 3.2"
end
112 changes: 78 additions & 34 deletions lib/active_record/allow_connection_failure.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,95 @@
module ActiveRecord
module AllowConnectionFailure
# monkeypatches activerecord/lib/active_record/query_cache.rb
ActiveRecord::QueryCache.class_eval do
def self.run
if ActiveRecord::Base.connected?
connection = ActiveRecord::Base.connection
enabled = connection.query_cache_enabled
connection_id = ActiveRecord::Base.connection_id
connection.enable_query_cache!

[enabled, connection_id]
if Rails::VERSION::MAJOR == 3
ActiveRecord::QueryCache::BodyProxy.class_eval do
def close
@target.close if @target.respond_to?(:close)
ensure
ActiveRecord::Base.connection_id = @connection_id
if ActiveRecord::Base.connected?
ActiveRecord::Base.connection.clear_query_cache
unless @original_cache_value
ActiveRecord::Base.connection.disable_query_cache!
end
end
end
end

def self.complete(state)
if ActiveRecord::Base.connected?
enabled, connection_id = state

ActiveRecord::Base.connection_id = connection_id
ActiveRecord::Base.connection.clear_query_cache
ActiveRecord::Base.connection.disable_query_cache! unless enabled
ActiveRecord::QueryCache.class_eval do
def call(env)
begin
if ActiveRecord::Base.connected?
old = ActiveRecord::Base.connection.query_cache_enabled
ActiveRecord::Base.connection.enable_query_cache!
end

status, headers, body = @app.call(env)
[status, headers, ActiveRecord::QueryCache::BodyProxy.new(old, body, ActiveRecord::Base.connection_id)]
rescue Exception => e
raise e.inspect
ActiveRecord::Base.connection.clear_query_cache
unless old
ActiveRecord::Base.connection.disable_query_cache!
end
raise e
end
end
end

ActiveRecord::ModelSchema::ClassMethods.module_eval do
def clear_cache! # :nodoc:
connection.schema_cache.clear! if connected?
end
end
end

if Rails::VERSION::MAJOR >= 4
ActiveRecord::QueryCache.class_eval do
def self.run
if ActiveRecord::Base.connected?
connection = ActiveRecord::Base.connection
enabled = connection.query_cache_enabled
connection_id = ActiveRecord::Base.connection_id
connection.enable_query_cache!

def self.install_executor_hooks(executor = ActiveSupport::Executor)
executor.register_hook(self)
[enabled, connection_id]
end
end

def self.complete(state)
if ActiveRecord::Base.connected?
enabled, connection_id = state

executor.to_complete do
unless ActiveRecord::Base.connected? && ActiveRecord::Base.connection.transaction_open?
ActiveRecord::Base.clear_active_connections!
ActiveRecord::Base.connection_id = connection_id
ActiveRecord::Base.connection.clear_query_cache
ActiveRecord::Base.connection.disable_query_cache! unless enabled
end
end
end
end

# monkeypatches activerecord/lib/active_record/migration.rb
ActiveRecord::Migration::CheckPending.class_eval do
def call(env)
if ActiveRecord::Base.connected? && connection.supports_migrations?
mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
if @last_check < mtime
ActiveRecord::Migration.check_pending!(connection)
@last_check = mtime
def self.install_executor_hooks(executor = ActiveSupport::Executor)
executor.register_hook(self)

executor.to_complete do
unless ActiveRecord::Base.connected? && ActiveRecord::Base.connection.transaction_open?
ActiveRecord::Base.clear_active_connections!
end
end
end
@app.call(env)
end
end
end

ActiveRecord::Migration::CheckPending.class_eval do
def call(env)
if ActiveRecord::Base.connected? && connection.supports_migrations?
mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
if @last_check < mtime
ActiveRecord::Migration.check_pending!(connection)
@last_check = mtime
end
end
@app.call(env)
end
end
end
end
end