Module: Switchman::ActiveRecord::ConnectionPool

Defined in:
lib/switchman/active_record/connection_pool.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#shardObject



14
15
16
# File 'lib/switchman/active_record/connection_pool.rb', line 14

def shard
  @shard || Shard.default
end

Class Method Details

.included(klass) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/switchman/active_record/connection_pool.rb', line 4

def self.included(klass)
  klass.alias_method_chain(:checkout_new_connection, :sharding)
  klass.send(:remove_method, :connection)
  klass.send(:remove_method, :active_connection?)
  klass.send(:remove_method, :release_connection)
  klass.send(:remove_method, :clear_stale_cached_connections!)
end

Instance Method Details

#active_connection?Boolean

Is there an open connection that is being used for the current thread?

Returns:

  • (Boolean)


48
49
50
51
52
53
54
# File 'lib/switchman/active_record/connection_pool.rb', line 48

def active_connection?
  synchronize do
    @reserved_connections.fetch(current_connection_id) {
      return false
    }.any? { |conn| conn.in_use? }
  end
end

#checkout_new_connection_with_shardingObject



26
27
28
29
30
31
32
33
# File 'lib/switchman/active_record/connection_pool.rb', line 26

def checkout_new_connection_with_sharding
  # TODO: this might be a threading issue
  spec.config[:shard_name] = self.shard.name

  conn = checkout_new_connection_without_sharding
  conn.shard = self.shard
  conn
end

#clear_stale_cached_connections!Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/switchman/active_record/connection_pool.rb', line 61

def clear_stale_cached_connections!
  keys = @reserved_connections.keys - Thread.list.find_all { |t|
    t.alive?
  }.map { |thread| thread.object_id }
  keys.each do |key|
    conns = @reserved_connections[key]
    ActiveSupport::Deprecation.warn(<<-eowarn) if conn.in_use?
Database connections will not be closed automatically, please close your
database connection at the end of the thread by calling `close` on your
connection.  For example: ActiveRecord::Base.connection.close
    eowarn
    conns.each { |conn| checkin conn }
    @reserved_connections.delete(key)
  end
end

#connectionObject



35
36
37
38
39
40
41
42
43
44
45
# File 'lib/switchman/active_record/connection_pool.rb', line 35

def connection
  conns = synchronize { @reserved_connections[current_connection_id] ||= [] }
  conn = conns.find { |conn| !conn.open_transactions || conn.shard == self.shard || conn.adapter_name == 'PostgreSQL' }
  unless conn
    conn = checkout
    yield conn if block_given?
    conns << conn
  end
  switch_database(conn) if conn.shard != self.shard
  conn
end

#default_schemaObject



18
19
20
21
22
23
24
# File 'lib/switchman/active_record/connection_pool.rb', line 18

def default_schema
  raise "Not postgres!" unless self.spec.config[:adapter] == 'postgresql'
  connection unless @schemas
  # default shard will not switch databases immediately, so it won't be set yet
  @schemas ||= connection.schemas
  @schemas.first
end

#release(conn) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/switchman/active_record/connection_pool.rb', line 77

def release(conn)
  synchronize do
    thread_id = nil

    if @reserved_connections[current_connection_id].include?(conn)
      thread_id = current_connection_id
      @reserved_connections[thread_id].delete(conn)
    else
      thread_id = @reserved_connections.keys.find { |k|
        @reserved_connections[k].include?(conn)
      }
      if thread_id
        @reserved_connections[thread_id].delete(conn)
      end
    end

    @reserved_connections.delete thread_id if thread_id && @reserved_connections[thread_id].empty?
  end
end

#release_connectionObject



56
57
58
59
# File 'lib/switchman/active_record/connection_pool.rb', line 56

def release_connection
  conns = synchronize { @reserved_connections.delete(current_connection_id) }
  conns.each { |conn| checkin conn } if conns
end

#switch_database(conn) ⇒ Object



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

def switch_database(conn)
  if !@schemas && conn.adapter_name == 'PostgreSQL' && !self.shard.database_server.config[:shard_name]
    @schemas = conn.schemas
  end

  spec.config[:shard_name] = self.shard.name
  case conn.adapter_name
    when 'MySQL', 'Mysql2'
      conn.execute("USE #{spec.config[:database]}")
    when 'PostgreSQL'
      conn.schema_search_path = spec.config[:schema_search_path]
    when 'SQLite'
      # This is an artifact of the adapter modifying the path to be an absolute path when it is instantiated; just let it slide
    else
      raise("Cannot switch databases on same DatabaseServer with adapter type: #{conn.adapter_name}. Limit one Shard per DatabaseServer.")
  end
  conn.shard = shard
end