Module: RR::ConnectionExtenders

Defined in:
lib/rubyrep/connection_extenders/connection_extenders.rb,
lib/rubyrep/connection_extenders/mysql_extender.rb,
lib/rubyrep/connection_extenders/postgresql_extender.rb

Overview

Connection extenders provide additional database specific functionality not coming in the ActiveRecord library. This module itself only provides functionality to register and retrieve such connection extenders.

Defined Under Namespace

Modules: MysqlExtender, PostgreSQLExtender

Constant Summary collapse

@@use_cache =
true

Class Method Summary collapse

Class Method Details

.active_record_class_for_database_connectionClass

Creates a new ActiveRecord::Base descending class that can be used to create and manage database connections.

Returns:

  • (Class)

    the new ActiveRecord::Base descending class



33
34
35
36
37
38
39
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 33

def self.active_record_class_for_database_connection
  active_record_class = Class.new(ActiveRecord::Base)
  @active_record_class_counter ||= 0
  @active_record_class_counter += 1
  RR.const_set("DummyActiveRecord#{@active_record_class_counter}", active_record_class)
  active_record_class
end

.clear_db_connection_cacheObject

Free up all cached connections



147
148
149
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 147

def self.clear_db_connection_cache
  @@connection_cache = {}
end

.connection_cacheObject

Returns the connection cache hash.



86
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 86

def self.connection_cache; @@connection_cache; end

.connection_cache=(cache) ⇒ Object

Sets a new connection cache



89
90
91
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 89

def self.connection_cache=(cache)
  @@connection_cache = cache
end

.db_connect(config) ⇒ Object

Creates database connections by calling #db_connect_without_cache with the provided config configuration hash. A new database connection is created only if no according cached connection is available.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 120

def self.db_connect(config)
  if not use_cache?
    db_connection = db_connect_without_cache config
  else
    config_dump = Marshal.dump config.reject {|key, | [:proxy_host, :proxy_port, :logger].include? key}
    config_checksum = Digest::SHA1.hexdigest(config_dump)
    @@connection_cache ||= {}

    db_connection = connection_cache[config_checksum]
    unless db_connection and db_connection.active?
      db_connection = db_connect_without_cache config
      connection_cache[config_checksum] = db_connection
    end
  end

  install_logger db_connection, config
  db_connection
end

.db_connect_without_cache(config) ⇒ Object

Creates an ActiveRecord database connection according to the provided config connection hash. Possible values of this parameter are described in ActiveRecord::Base#establish_connection. The database connection is extended with the correct ConnectionExtenders module.

ActiveRecord only allows one database connection per class. (It disconnects the existing database connection if a new connection is established.) To go around this, we delete ActiveRecord’s memory of the existing database connection as soon as it is created.



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 49

def self.db_connect_without_cache(config)
  # active_record_class = active_record_class_for_connection(config)
  # active_record_class = DummyActiveRecord.dup
  active_record_class = active_record_class_for_database_connection
  active_record_class.establish_connection(config)


  # To suppress Postgres debug messages (which cannot be suppress in another way),
  # temporarily replace stdout.
  org_stdout = $stdout
  $stdout = StringIO.new
  begin
    connection = active_record_class.connection
  ensure
    puts $stdout.string
    $stdout = org_stdout
  end

  if ConnectionExtenders.extenders.include? config[:adapter].to_sym
    extender = config[:adapter].to_sym
  else
    raise "No ConnectionExtender available for :#{config[:adapter]}"
  end
  connection.extend ConnectionExtenders.extenders[extender]

  replication_module = ReplicationExtenders.extenders[config[:adapter].to_sym]
  connection.extend replication_module if replication_module
  
  connection
end

.extendersObject

Returns a Hash of currently registered connection extenders. (Empty Hash if no connection extenders were defined.)



15
16
17
18
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 15

def self.extenders
  @extenders ||= {}
  @extenders
end

.install_logger(db_connection, config) ⇒ Object

Installs the configured logger (if any) into the database connection.

  • db_connection: database connection (as produced by #db_connect)

  • config: database configuration (as provided to #db_connect)



96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 96

def self.install_logger(db_connection, config)
  if config[:logger]
    if config[:logger].respond_to?(:debug)
      logger = config[:logger]
    else
      logger = ActiveSupport::Logger.new(config[:logger])
    end
    db_connection.instance_variable_set :@logger, logger
    if ActiveSupport.const_defined?(:Notifications)
      connection_object_id = db_connection.object_id
      db_connection.log_subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |name, start, finish, id, payload|
        if payload[:connection_id] == connection_object_id and logger.debug?
          sql = payload[:sql].squeeze(" ") rescue payload[:sql]
          logger.debug sql
        end
      end
    end
  end
end

.register(extender) ⇒ Object

Registers one or multiple connection extender. extender is a Hash with

key::   The adapter symbol as used by ActiveRecord::Connection Adapters, e. g. :postgresql
value:: Name of the module implementing the connection extender


24
25
26
27
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 24

def self.register(extender)
  @extenders ||= {}
  @extenders.merge! extender
end

.use_cache?Boolean

Returns the current cache status (true if caching is used; false otherwise).

Returns:

  • (Boolean)


83
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 83

def self.use_cache?; @@use_cache; end

.use_db_connection_cache(status) ⇒ Object

If status == true: enable the cache. If status == false: don’ use cache Returns the old connection caching status



141
142
143
144
# File 'lib/rubyrep/connection_extenders/connection_extenders.rb', line 141

def self.use_db_connection_cache(status)
  old_status, @@use_cache = @@use_cache, status
  old_status
end