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.
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
+