genghis 1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README +0 -0
  2. data/lib/genghis.rb +206 -0
  3. metadata +74 -0
data/README ADDED
File without changes
@@ -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
+