ar_connection_pool 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/init.rb +1 -0
- data/lib/ar_connection_pool.rb +305 -0
- data/lib/tasks/rubyforge_config.yml +5 -0
- metadata +52 -0
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# require 'ar_connection_pool'
|
@@ -0,0 +1,305 @@
|
|
1
|
+
require 'benchmark'
|
2
|
+
require 'date'
|
3
|
+
require 'bigdecimal'
|
4
|
+
require 'bigdecimal/util'
|
5
|
+
|
6
|
+
require 'active_record/connection_adapters/abstract/schema_definitions'
|
7
|
+
require 'active_record/connection_adapters/abstract/schema_statements'
|
8
|
+
require 'active_record/connection_adapters/abstract/database_statements'
|
9
|
+
require 'active_record/connection_adapters/abstract/quoting'
|
10
|
+
require 'active_record/connection_adapters/abstract/connection_specification'
|
11
|
+
|
12
|
+
module ActiveRecord
|
13
|
+
module ConnectionAdapters # :nodoc:
|
14
|
+
# All the concrete database adapters follow the interface laid down in this class.
|
15
|
+
# You can use this interface directly by borrowing the database connection from the Base with
|
16
|
+
# Base.connection.
|
17
|
+
#
|
18
|
+
# Most of the methods in the adapter are useful during migrations. Most
|
19
|
+
# notably, SchemaStatements#create_table, SchemaStatements#drop_table,
|
20
|
+
# SchemaStatements#add_index, SchemaStatements#remove_index,
|
21
|
+
# SchemaStatements#add_column, SchemaStatements#change_column and
|
22
|
+
# SchemaStatements#remove_column are very useful.
|
23
|
+
class ArConnectionPoolAdapter < AbstractAdapter
|
24
|
+
include Quoting, DatabaseStatements, SchemaStatements
|
25
|
+
@@row_even = true
|
26
|
+
|
27
|
+
def initialize(connection, logger = nil) #:nodoc:
|
28
|
+
@connection, @logger = connection, logger
|
29
|
+
@runtime = 0
|
30
|
+
@last_verification = 0
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the human-readable name of the adapter. Use mixed case - one
|
34
|
+
# can always use downcase if needed.
|
35
|
+
def adapter_name
|
36
|
+
'ArConnectionPool'
|
37
|
+
end
|
38
|
+
|
39
|
+
# Does this adapter support migrations? Backend specific, as the
|
40
|
+
# abstract adapter always returns +false+.
|
41
|
+
def supports_migrations?
|
42
|
+
false
|
43
|
+
end
|
44
|
+
|
45
|
+
# Does this adapter support using DISTINCT within COUNT? This is +true+
|
46
|
+
# for all adapters except sqlite.
|
47
|
+
def supports_count_distinct?
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
# Should primary key values be selected from their corresponding
|
52
|
+
# sequence before the insert statement? If true, next_sequence_value
|
53
|
+
# is called before each insert to set the record's primary key.
|
54
|
+
# This is false for all adapters but Firebird.
|
55
|
+
def prefetch_primary_key?(table_name = nil)
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def reset_runtime #:nodoc:
|
60
|
+
rt, @runtime = @runtime, 0
|
61
|
+
rt
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
# CONNECTION MANAGEMENT ====================================
|
66
|
+
|
67
|
+
# Is this connection active and ready to perform queries?
|
68
|
+
def active?
|
69
|
+
@active != false
|
70
|
+
end
|
71
|
+
|
72
|
+
# Close this connection and open a new one in its place.
|
73
|
+
def reconnect!
|
74
|
+
@active = true
|
75
|
+
end
|
76
|
+
|
77
|
+
# Close this connection
|
78
|
+
def disconnect!
|
79
|
+
@active = false
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns true if its safe to reload the connection between requests for development mode.
|
83
|
+
# This is not the case for Ruby/MySQL and it's not necessary for any adapters except SQLite.
|
84
|
+
def requires_reloading?
|
85
|
+
false
|
86
|
+
end
|
87
|
+
|
88
|
+
# Lazily verify this connection, calling +active?+ only if it hasn't
|
89
|
+
# been called for +timeout+ seconds.
|
90
|
+
def verify!(timeout)
|
91
|
+
now = Time.now.to_i
|
92
|
+
if (now - @last_verification) > timeout
|
93
|
+
reconnect! unless active?
|
94
|
+
@last_verification = now
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Provides access to the underlying database connection. Useful for
|
99
|
+
# when you need to call a proprietary method such as postgresql's lo_*
|
100
|
+
# methods
|
101
|
+
def raw_connection
|
102
|
+
@connection
|
103
|
+
end
|
104
|
+
|
105
|
+
protected
|
106
|
+
def log(sql, name)
|
107
|
+
if block_given?
|
108
|
+
if @logger and @logger.level <= Logger::INFO
|
109
|
+
result = nil
|
110
|
+
seconds = Benchmark.realtime { result = yield }
|
111
|
+
@runtime += seconds
|
112
|
+
log_info(sql, name, seconds)
|
113
|
+
result
|
114
|
+
else
|
115
|
+
yield
|
116
|
+
end
|
117
|
+
else
|
118
|
+
log_info(sql, name, 0)
|
119
|
+
nil
|
120
|
+
end
|
121
|
+
rescue Exception => e
|
122
|
+
# Log message and raise exception.
|
123
|
+
# Set last_verfication to 0, so that connection gets verified
|
124
|
+
# upon reentering the request loop
|
125
|
+
@last_verification = 0
|
126
|
+
message = "#{e.class.name}: #{e.message}: #{sql}"
|
127
|
+
log_info(message, name, 0)
|
128
|
+
raise ActiveRecord::StatementInvalid, message
|
129
|
+
end
|
130
|
+
|
131
|
+
def log_info(sql, name, runtime)
|
132
|
+
return unless @logger
|
133
|
+
|
134
|
+
@logger.debug(
|
135
|
+
format_log_entry(
|
136
|
+
"#{name.nil? ? "SQL" : name} (#{sprintf("%f", runtime)})",
|
137
|
+
sql.gsub(/ +/, " ")
|
138
|
+
)
|
139
|
+
)
|
140
|
+
end
|
141
|
+
|
142
|
+
def format_log_entry(message, dump = nil)
|
143
|
+
if ActiveRecord::Base.colorize_logging
|
144
|
+
if @@row_even
|
145
|
+
@@row_even = false
|
146
|
+
message_color, dump_color = "4;36;1", "0;1"
|
147
|
+
else
|
148
|
+
@@row_even = true
|
149
|
+
message_color, dump_color = "4;35;1", "0"
|
150
|
+
end
|
151
|
+
|
152
|
+
log_entry = " \e[#{message_color}m#{message}\e[0m "
|
153
|
+
log_entry << "\e[#{dump_color}m%#{String === dump ? 's' : 'p'}\e[0m" % dump if dump
|
154
|
+
log_entry
|
155
|
+
else
|
156
|
+
"%s %s" % [message, dump]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
|
164
|
+
# require 'singleton'
|
165
|
+
# module ActiveRecord
|
166
|
+
# module ConnectionPool
|
167
|
+
# class Expired < Exception
|
168
|
+
# end
|
169
|
+
#
|
170
|
+
# # class PersistentConnection < ActiveRecord::Base
|
171
|
+
# # self.abstract_class = true
|
172
|
+
# # establish_connection RAILS_ENV.to_sym
|
173
|
+
# # end
|
174
|
+
#
|
175
|
+
# class Configuration
|
176
|
+
# include Singleton
|
177
|
+
#
|
178
|
+
# def initialize
|
179
|
+
# self.pool_size = 2
|
180
|
+
# self.usage_limit = 200
|
181
|
+
# self.ttl = 1.minutes
|
182
|
+
# end
|
183
|
+
#
|
184
|
+
# attr_accessor :pool_size
|
185
|
+
# attr_accessor :usage_limit
|
186
|
+
# attr_accessor :ttl
|
187
|
+
#
|
188
|
+
# end
|
189
|
+
#
|
190
|
+
# class Pool
|
191
|
+
# include Singleton
|
192
|
+
#
|
193
|
+
# def initialize
|
194
|
+
# self.pool = []
|
195
|
+
# ActiveRecord::ConnectionPool::Configuration.instance.pool_size.times do |i|
|
196
|
+
# self.pool << ActiveRecord::ConnectionPool::Connection.new(RAILS_ENV)
|
197
|
+
# end
|
198
|
+
# end
|
199
|
+
#
|
200
|
+
# def connection
|
201
|
+
# conn = self.pool[rand(self.pool.size)]
|
202
|
+
# begin
|
203
|
+
# return conn.connection
|
204
|
+
# rescue ActiveRecord::ConnectionPool::Expired => e
|
205
|
+
# msg e.inspect
|
206
|
+
# msg "Removing connection: #{conn.class_name}"
|
207
|
+
# conn.class_name.constantize.remove_connection
|
208
|
+
# msg "Deleting connection from pool... (#{self.pool.size})"
|
209
|
+
# self.pool.delete(conn)
|
210
|
+
# msg "Deleted connection from pool... (#{self.pool.size})"
|
211
|
+
# self.pool << ActiveRecord::ConnectionPool::Connection.new(RAILS_ENV)
|
212
|
+
# msg "Created new connection #{self.pool.last.class_name} (#{self.pool.size})"
|
213
|
+
# return connection
|
214
|
+
# end
|
215
|
+
# end
|
216
|
+
#
|
217
|
+
# protected
|
218
|
+
# attr_accessor :pool
|
219
|
+
#
|
220
|
+
# end
|
221
|
+
#
|
222
|
+
# class Connection
|
223
|
+
#
|
224
|
+
# attr_accessor :usage
|
225
|
+
# attr_accessor :connection_name
|
226
|
+
# attr_accessor :class_name
|
227
|
+
# attr_accessor :created_at
|
228
|
+
# attr_accessor :expired
|
229
|
+
#
|
230
|
+
# def initialize(con_name)
|
231
|
+
# self.usage = 0
|
232
|
+
# self.connection_name = con_name
|
233
|
+
# self.created_at = Time.now
|
234
|
+
# self.expired = false
|
235
|
+
# self.class_name = "ActiveRecord::ConnectionPool::#{connection_name.to_s.camelize}#{rand(100000)}"
|
236
|
+
# puts "self.connection_name = #{self.connection_name}"
|
237
|
+
# eval %{
|
238
|
+
# class #{self.class_name} < ActiveRecord::Base
|
239
|
+
# self.abstract_class = true
|
240
|
+
# establish_connection :#{self.connection_name}
|
241
|
+
# end
|
242
|
+
# }
|
243
|
+
# msg self.class_name
|
244
|
+
# end
|
245
|
+
#
|
246
|
+
# def connection
|
247
|
+
# self.usage += 1
|
248
|
+
# if self.expired || self.usage >= ActiveRecord::ConnectionPool::Configuration.instance.usage_limit ||
|
249
|
+
# (Time.now - self.created_at) >= ActiveRecord::ConnectionPool::Configuration.instance.ttl
|
250
|
+
# self.expired = true
|
251
|
+
# raise ActiveRecord::ConnectionPool::Expired.new(self.inspect)
|
252
|
+
# end
|
253
|
+
# msg "Selected: #{self.inspect}"
|
254
|
+
# self.class_name.constantize.ar_connection
|
255
|
+
# end
|
256
|
+
#
|
257
|
+
# end
|
258
|
+
# end
|
259
|
+
# end
|
260
|
+
#
|
261
|
+
# if RAILS_ENV == "development"
|
262
|
+
# def msg(x)
|
263
|
+
# txt = "!-----------------------------\n"
|
264
|
+
# txt << "AR: #{x}\n"
|
265
|
+
# txt << "-----------------------------!\n"
|
266
|
+
# puts txt
|
267
|
+
# end
|
268
|
+
# else
|
269
|
+
# def msg(x)
|
270
|
+
# end
|
271
|
+
# end
|
272
|
+
#
|
273
|
+
# class ActiveRecord::Base
|
274
|
+
#
|
275
|
+
# alias_method :ar_connection, :connection
|
276
|
+
#
|
277
|
+
# def connection
|
278
|
+
# c = ivar_cache("ar_instance_connection") do
|
279
|
+
# ActiveRecord::Base.connection
|
280
|
+
# end
|
281
|
+
# msg(c)
|
282
|
+
# c
|
283
|
+
# end
|
284
|
+
#
|
285
|
+
# end
|
286
|
+
#
|
287
|
+
# class << ActiveRecord::Base
|
288
|
+
#
|
289
|
+
# alias_method :ar_connection, :connection
|
290
|
+
#
|
291
|
+
# def connection
|
292
|
+
# begin
|
293
|
+
# puts "RAILS_ENV = #{RAILS_ENV}"
|
294
|
+
# return ActiveRecord::ConnectionPool::Pool.instance.connection
|
295
|
+
# rescue Exception => e
|
296
|
+
# msg e.inspect
|
297
|
+
# raise e
|
298
|
+
# end
|
299
|
+
# end
|
300
|
+
#
|
301
|
+
# # def persistent_connection
|
302
|
+
# # ActiveRecord::ConnectionPool::PersistentConnection.ar_connection
|
303
|
+
# # end
|
304
|
+
#
|
305
|
+
# end
|
metadata
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: ar_connection_pool
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2007-09-20 00:00:00 -04:00
|
8
|
+
summary: ar_connection_pool
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
- lib
|
12
|
+
- lib
|
13
|
+
- lib/tasks
|
14
|
+
email:
|
15
|
+
homepage:
|
16
|
+
rubyforge_project: magrathea
|
17
|
+
description: "ar_connection_pool was developed by: markbates"
|
18
|
+
autorequire:
|
19
|
+
- ar_connection_pool
|
20
|
+
default_executable:
|
21
|
+
bindir: bin
|
22
|
+
has_rdoc: false
|
23
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 0.0.0
|
28
|
+
version:
|
29
|
+
platform: ruby
|
30
|
+
signing_key:
|
31
|
+
cert_chain:
|
32
|
+
post_install_message:
|
33
|
+
authors:
|
34
|
+
- markbates
|
35
|
+
files:
|
36
|
+
- init.rb
|
37
|
+
- lib/ar_connection_pool.rb
|
38
|
+
- lib/tasks/rubyforge_config.yml
|
39
|
+
test_files: []
|
40
|
+
|
41
|
+
rdoc_options: []
|
42
|
+
|
43
|
+
extra_rdoc_files: []
|
44
|
+
|
45
|
+
executables: []
|
46
|
+
|
47
|
+
extensions: []
|
48
|
+
|
49
|
+
requirements: []
|
50
|
+
|
51
|
+
dependencies: []
|
52
|
+
|