genghis 1.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/README +0 -0
- data/lib/genghis.rb +206 -0
- metadata +74 -0
data/README
ADDED
File without changes
|
data/lib/genghis.rb
ADDED
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'mongo'
|
3
|
+
|
4
|
+
class Genghis
|
5
|
+
include Mongo
|
6
|
+
|
7
|
+
def self.environment=(environment = :development)
|
8
|
+
base = File.dirname(__FILE__)
|
9
|
+
base = Rails.root if defined?(Rails)
|
10
|
+
|
11
|
+
config_file = File.join(base,'config', 'mongodb.yml')
|
12
|
+
yaml = YAML.load_file(config_file)
|
13
|
+
@@config = yaml[environment.to_s]
|
14
|
+
@@config.each do |k, v|
|
15
|
+
self.class.instance_eval do
|
16
|
+
define_method(k.to_sym){v}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.connection
|
22
|
+
@connection || safe_create_connection
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.database(db_alias)
|
26
|
+
connection.db(self.databases[db_alias])
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.reconnect
|
30
|
+
@connection = safe_create_connection
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def self.max_retries
|
36
|
+
connection_options
|
37
|
+
@@retries || 5
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.connection_options
|
41
|
+
@@connection_options ||= symbolize_keys((@@config['connection_options']) || default_connection_options)
|
42
|
+
@@retries ||= @@connection_options.delete(:max_retries)
|
43
|
+
@@connection_options
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.default_connection_options
|
47
|
+
{:max_retries => 5,
|
48
|
+
:pool_size => 5,
|
49
|
+
:timeout => 5,
|
50
|
+
:use_slave => false
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.safe_create_connection
|
55
|
+
opts = connection_options
|
56
|
+
if self.servers.is_a? Hash
|
57
|
+
servers = self.servers
|
58
|
+
servers = [parse_host(servers['left']), parse_host(servers['right'])]
|
59
|
+
connection = Connection.paired(servers, opts)
|
60
|
+
else
|
61
|
+
host, port = parse_host(self.servers)
|
62
|
+
connection = Connection.new(host, port, opts)
|
63
|
+
end
|
64
|
+
connection
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.parse_host(host)
|
68
|
+
a = host.split(':')
|
69
|
+
a << 27017 if a.size == 1
|
70
|
+
a
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.symbolize_keys(hash)
|
74
|
+
hash.inject({}){|memo, (k, v)| memo[k.to_sym] = v; memo}
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
module ProxyMethods
|
79
|
+
|
80
|
+
def self.included(mod)
|
81
|
+
mod.class_eval do
|
82
|
+
extend ClassMethods
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
module ClassMethods
|
87
|
+
attr_accessor :protected_class
|
88
|
+
|
89
|
+
def protects(clazz)
|
90
|
+
Guardian.add(clazz)
|
91
|
+
@protected_class= clazz
|
92
|
+
end
|
93
|
+
|
94
|
+
def protected?(clazz)
|
95
|
+
@@protected_classes.include? clazz
|
96
|
+
end
|
97
|
+
|
98
|
+
def method_missing(method, *args, &block)
|
99
|
+
protect_from_exception do
|
100
|
+
Guardian.make_safe(@protected_class.__send__(method, *args, &block))
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def allocate
|
105
|
+
@protected_class.allocate
|
106
|
+
end
|
107
|
+
|
108
|
+
def safe?
|
109
|
+
true
|
110
|
+
end
|
111
|
+
|
112
|
+
def protect_from_exception(&block)
|
113
|
+
success = false
|
114
|
+
max_retries = Genghis.max_retries
|
115
|
+
retries = 0
|
116
|
+
rv = nil
|
117
|
+
while !success
|
118
|
+
begin
|
119
|
+
rv = yield
|
120
|
+
success = true
|
121
|
+
rescue Mongo::ConnectionFailure => ex
|
122
|
+
Rails.logger.fatal('Mongo has died ', ex)
|
123
|
+
WebServiceFailed.deliver_mongo_down(ex, Genghis.connection)
|
124
|
+
retries += 1
|
125
|
+
raise ex if retries > max_retries
|
126
|
+
fix_broken_connection
|
127
|
+
sleep(1)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
rv
|
131
|
+
end
|
132
|
+
|
133
|
+
def fix_broken_connection
|
134
|
+
Genghis.reconnect
|
135
|
+
MongoMapper.connection = Genghis.connection
|
136
|
+
MongoMapper.database = Genghis.databases['mongo_mapper']
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
class Guardian
|
143
|
+
alias_method :old_class, :class
|
144
|
+
instance_methods.each { |m| undef_method m unless m =~ /^__|^old/}
|
145
|
+
|
146
|
+
include ProxyMethods
|
147
|
+
|
148
|
+
def initialize(*args)
|
149
|
+
|
150
|
+
opts = args.extract_options!
|
151
|
+
if opts.empty?
|
152
|
+
if args.empty?
|
153
|
+
what = self.old_class.protected_class.new
|
154
|
+
else
|
155
|
+
what = args.first
|
156
|
+
end
|
157
|
+
else
|
158
|
+
what = self.old_class.protected_class.new(opts)
|
159
|
+
end
|
160
|
+
|
161
|
+
@protected = what
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.protected_classes
|
165
|
+
@@protected_classes ||= Set.new
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.add(clazz)
|
169
|
+
protected_classes << clazz
|
170
|
+
end
|
171
|
+
|
172
|
+
def self.under_protection?(clazz)
|
173
|
+
protected_classes.include?(clazz)
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.classes_under_protection
|
177
|
+
protected_classes
|
178
|
+
end
|
179
|
+
|
180
|
+
def self.make_safe(o)
|
181
|
+
if o.is_a? Array
|
182
|
+
Guardian.under_protection?(o.first.class) ? ArrayProxy.new(o) : o
|
183
|
+
else
|
184
|
+
Guardian.under_protection?(o.class) ? Guardian.new(o) : o
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
def method_missing(method, *args, &block)
|
190
|
+
return true if method == :safe?
|
191
|
+
self.old_class.protect_from_exception do
|
192
|
+
Guardian.make_safe(@protected.__send__(method, *args, &block))
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
end
|
197
|
+
|
198
|
+
class ArrayProxy < Guardian
|
199
|
+
protects Array
|
200
|
+
|
201
|
+
def to_ary
|
202
|
+
@protected
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|
metadata
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: genghis
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 1
|
7
|
+
- 0
|
8
|
+
version: "1.0"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- Steve Cohen
|
12
|
+
autorequire: genghis
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2010-03-15 00:00:00 -07:00
|
17
|
+
default_executable:
|
18
|
+
dependencies:
|
19
|
+
- !ruby/object:Gem::Dependency
|
20
|
+
name: mongo
|
21
|
+
prerelease: false
|
22
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
segments:
|
27
|
+
- 0
|
28
|
+
- 19
|
29
|
+
version: "0.19"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
description:
|
33
|
+
email: scohen@scohen.org
|
34
|
+
executables: []
|
35
|
+
|
36
|
+
extensions: []
|
37
|
+
|
38
|
+
extra_rdoc_files:
|
39
|
+
- README
|
40
|
+
files:
|
41
|
+
- lib/genghis.rb
|
42
|
+
- README
|
43
|
+
has_rdoc: true
|
44
|
+
homepage: http://github.com/scohen/genghis
|
45
|
+
licenses: []
|
46
|
+
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
segments:
|
64
|
+
- 0
|
65
|
+
version: "0"
|
66
|
+
requirements: []
|
67
|
+
|
68
|
+
rubyforge_project:
|
69
|
+
rubygems_version: 1.3.6
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: Genghis is a mongoDB configuration and resilience framework
|
73
|
+
test_files: []
|
74
|
+
|