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. :stopdoc:

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

:nodoc:



393
394
395
396
397
398
399
# File 'lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb', line 393

def initialize(config, factory) # :nodoc:
  @active = true
  @config = config
  @factory = factory
  @raw_connection = @factory.new_connection @config
  super @raw_connection
end

Instance Attribute Details

#activeObject Also known as: active?

:nodoc:



384
385
386
# File 'lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb', line 384

def active
  @active
end

Instance Method Details

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

:nodoc:



453
454
455
# File 'lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb', line 453

def exec(sql, *bindvars, &block) # :nodoc:
  with_retry { @raw_connection.exec(sql, *bindvars, &block) }
end

#pingObject

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



404
405
406
407
408
409
410
# File 'lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb', line 404

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

#resetObject



412
413
414
415
# File 'lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb', line 412

def reset
  # tentative
  reset!
end

#reset!Object

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



418
419
420
421
422
423
424
425
426
427
428
# File 'lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb', line 418

def reset! # :nodoc:
  logoff rescue nil
  begin
    @raw_connection = @factory.new_connection @config
    __setobj__ @raw_connection
    @active = true
  rescue
    @active = false
    raise
  end
end

#with_retry(allow_retry: false) ⇒ Object

Adds auto-recovery functionality.



438
439
440
441
442
443
444
445
446
447
448
449
450
451
# File 'lib/active_record/connection_adapters/oracle_enhanced/oci_connection.rb', line 438

def with_retry(allow_retry: false) # :nodoc:
  should_retry = (allow_retry || self.class.auto_retry?) && autocommit?

  begin
    yield
  rescue OCIException => e
    raise unless e.is_a?(OCIError) && LOST_CONNECTION_ERROR_CODES.include?(e.code)
    @active = false
    raise unless should_retry
    should_retry = false
    reset! rescue nil
    retry
  end
end