Class: OCI8EnhancedAutoRecover

Inherits:
OCI8
  • Object
show all
Defined in:
lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb

Overview

The OCI8AutoRecover class enhances the OCI8 driver with auto-recover and reset functionality. If a call to #exec fails, and autocommit is turned on (ie., we’re not in the middle of a longer transaction), it will automatically reconnect and try again. If autocommit is turned off, this would be dangerous (as the earlier part of the implied transaction may have failed silently if the connection died) – so instead the connection is marked as dead, to be reconnected on it’s next use.

Constant Summary collapse

LOST_CONNECTION_ERROR_CODES =

ORA-00028: your session has been killed ORA-01012: not logged on ORA-03113: end-of-file on communication channel ORA-03114: not connected to ORACLE ORA-03135: connection lost contact

[ 28, 1012, 3113, 3114, 3135 ]
@@auto_retry =
false

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config, factory) ⇒ OCI8EnhancedAutoRecover

Returns a new instance of OCI8EnhancedAutoRecover.



287
288
289
290
291
292
293
# File 'lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb', line 287

def initialize(config, factory)
  @active = true
  @config = config
  @factory = factory
  @connection  = @factory.new_connection @config
  super @connection
end

Instance Attribute Details

#activeObject Also known as: active?

Returns the value of attribute active.



278
279
280
# File 'lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb', line 278

def active
  @active
end

Instance Method Details

#describe(name) ⇒ Object



346
347
348
# File 'lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb', line 346

def describe(name)
  @connection.describe(name)
end

#exec(sql, *bindvars, &block) ⇒ Object

Adds auto-recovery functionality.

See: www.jiubao.org/ruby-oci8/api.en.html#label-11



329
330
331
332
333
334
335
336
337
338
339
340
341
342
# File 'lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb', line 329

def exec(sql, *bindvars, &block)
  should_retry = self.class.auto_retry? && autocommit?

  begin
    @connection.exec(sql, *bindvars, &block)
  rescue OCIException => e
    raise unless LOST_CONNECTION_ERROR_CODES.include?(e.code)
    @active = false
    raise unless should_retry
    should_retry = false
    reset! rescue nil
    retry
  end
end

#pingObject

Checks connection, returns true if active. Note that ping actively checks the connection, while #active? simply returns the last known state.



298
299
300
301
302
303
304
# File 'lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb', line 298

def ping
  @connection.exec("select 1 from dual") { |r| nil }
  @active = true
rescue
  @active = false
  raise
end

#reset!Object

Resets connection, by logging off and creating a new connection.



307
308
309
310
311
312
313
314
315
316
317
# File 'lib/active_record/connection_adapters/oracle_enhanced_oci_connection.rb', line 307

def reset!
  logoff rescue nil
  begin
    @connection = @factory.new_connection @config
    __setobj__ @connection
    @active = true
  rescue
    @active = false
    raise
  end
end