Module: EnhancedSQLite3::Adapter
- Defined in:
- lib/enhanced_sqlite3/adapter.rb
Instance Method Summary collapse
-
#configure_connection ⇒ Object
Perform any necessary initialization upon the newly-established connection settings, run queries to configure any application-global “session” variables, etc.
-
#initialize ⇒ Object
Setup the Rails SQLite3 adapter instance.
-
#log ⇒ Object
Patch the #log method to ensure that all log messages are tagged with the database connection name.
-
#transaction ⇒ Object
Patch the #transaction method to ensure that all transactions are sent to the writing role database connection pool.
Instance Method Details
#configure_connection ⇒ Object
Perform any necessary initialization upon the newly-established connection settings, run queries to configure any application-global “session” variables, etc.
Implementations may assume this method will only be called while holding @lock (or from #initialize).
43 44 45 46 47 48 49 50 51 52 |
# File 'lib/enhanced_sqlite3/adapter.rb', line 43 def configure_connection configure_busy_handler_timeout check_version configure_pragmas configure_extensions EnhancedSQLite3::SupportsVirtualColumns.apply! unless try(:supports_virtual_columns?) EnhancedSQLite3::SupportsDeferrableConstraints.apply! unless try(:supports_deferrable_constraints?) EnhancedSQLite3::SupportsInsertReturning.apply! unless try(:supports_insert_returning?) end |
#initialize ⇒ Object
Setup the Rails SQLite3 adapter instance.
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/enhanced_sqlite3/adapter.rb', line 16 def initialize(...) super # Ensure that all connections default to immediate transaction mode. # This is necessary to prevent SQLite from deadlocking when concurrent processes open write transactions. # By default, SQLite opens transactions in deferred mode, which means that a transactions acquire # a shared lock on the database, but will attempt to upgrade that lock to an exclusive lock if/when # a write is attempted. Because SQLite is in the middle of a transaction, it cannot retry the transaction # if a BUSY exception is raised, and so it will immediately raise a SQLITE_BUSY exception without calling # the `busy_handler`. Because Rails only wraps writes in transactions, this means that all transactions # will attempt to acquire an exclusive lock on the database. Thus, under any concurrent load, you are very # likely to encounter a SQLITE_BUSY exception. # By setting the default transaction mode to immediate, SQLite will instead attempt to acquire # an exclusive lock as soon as the transaction is opened. If the lock cannot be acquired, it will # immediately call the `busy_handler` to retry the transaction. This allows concurrent processes to # coordinate and linearize their transactions, avoiding deadlocks. @connection_parameters.merge!(default_transaction_mode: :immediate) end |
#log ⇒ Object
Patch the #log method to ensure that all log messages are tagged with the database connection name.
62 63 64 65 66 67 68 69 |
# File 'lib/enhanced_sqlite3/adapter.rb', line 62 def log(...) db_connection_name = ActiveRecord::Base.connection_db_config.name if Rails.logger.formatter..include? db_connection_name super else Rails.logger.tagged(db_connection_name) { super } end end |
#transaction ⇒ Object
Patch the #transaction method to ensure that all transactions are sent to the writing role database connection pool.
55 56 57 58 59 |
# File 'lib/enhanced_sqlite3/adapter.rb', line 55 def transaction(...) ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role, prevent_writes: false) do super(...) end end |