ap4r 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +17 -7
- data/MIT-LICENSE +1 -1
- data/README +4 -145
- data/Rakefile +50 -4
- data/lib/ap4r.rb +1 -1
- data/lib/ap4r/carrier.rb +107 -0
- data/lib/ap4r/dispatcher.rb +326 -0
- data/lib/ap4r/message_store_ext.rb +9 -5
- data/lib/ap4r/mongrel.rb +9 -4
- data/{script → lib/ap4r}/mongrel_ap4r.rb +1 -2
- data/lib/ap4r/multi_queue.rb +2 -1
- data/lib/ap4r/queue_manager_ext.rb +86 -200
- data/lib/ap4r/queue_manager_ext_debug.rb +15 -7
- data/lib/ap4r/retention_history.rb +3 -2
- data/lib/ap4r/script/base.rb +1 -1
- data/lib/ap4r/script/queue_manager_control.rb +1 -1
- data/lib/ap4r/script/setup.rb +1 -1
- data/lib/ap4r/script/workspace_generator.rb +2 -2
- data/lib/ap4r/start_with_log4r.rb +4 -1
- data/lib/ap4r/store_and_forward.rb +10 -6
- data/lib/ap4r/stored_message.rb +4 -3
- data/lib/ap4r/util/irm.rb +3 -3
- data/lib/ap4r/util/queue_client.rb +1 -1
- data/lib/ap4r/version.rb +2 -2
- data/rails_plugin/ap4r/lib/async_controller.rb +52 -41
- data/script/mongrel_ap4r +4 -0
- metadata +34 -8
- data/lib/ap4r/util/loc.rb +0 -12
- data/lib/ap4r/xxx_create_table_for_saf.rb +0 -21
- data/rails_plugin/ap4r/init.rb +0 -10
@@ -1,10 +1,11 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
require 'active_support'
|
6
6
|
|
7
|
-
module ReliableMsg
|
7
|
+
module ReliableMsg #:nodoc:
|
8
|
+
|
8
9
|
# This class is too much experimental.
|
9
10
|
# The aim: for performance monitoring, records unprocessed message count
|
10
11
|
# in every queues at some interval.
|
data/lib/ap4r/script/base.rb
CHANGED
data/lib/ap4r/script/setup.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
require 'fileutils'
|
@@ -8,7 +8,7 @@ require 'optparse'
|
|
8
8
|
module Ap4r
|
9
9
|
module Script
|
10
10
|
class WorkspaceGenerator < Base
|
11
|
-
AP4R_Directories = %w(config log script tmp)
|
11
|
+
AP4R_Directories = %w(config log public script tmp)
|
12
12
|
|
13
13
|
def run argv, options
|
14
14
|
OptionParser.new {|opt|
|
@@ -1,13 +1,16 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
|
+
# Sample script to use Log4R
|
6
|
+
|
5
7
|
require 'rubygems'
|
6
8
|
require 'log4r'
|
7
9
|
require 'log4r/yamlconfigurator'
|
8
10
|
# we use various outputters, so require them, otherwise config chokes
|
9
11
|
require 'log4r/outputter/datefileoutputter'
|
10
12
|
require 'log4r/outputter/emailoutputter'
|
13
|
+
|
11
14
|
include Log4r
|
12
15
|
|
13
16
|
cfg = YamlConfigurator
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Author:: Kiwamu Kato
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
begin require 'rubygems'; rescue LoadError; end
|
@@ -25,9 +25,12 @@ module Ap4r
|
|
25
25
|
# :queue_message => message, :queue_headers => options})
|
26
26
|
#
|
27
27
|
module StoreAndForward
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
# TODO: make AsyncController include this module. 2007/05/02 by shino
|
29
|
+
|
30
|
+
# TODO: constant or class variable, whick is better? 2007/05/02 by shino
|
31
|
+
DRUBY_HOST = ENV['AP4R_DRUBY_HOST'] || 'localhost'
|
32
|
+
DRUBY_PORT = ENV['AP4R_DRUBY_PORT'] || '6438'
|
33
|
+
DRUBY_URI = "druby://#{DRUBY_HOST}:#{DRUBY_PORT}"
|
31
34
|
|
32
35
|
# This method needs information about stored message, such as
|
33
36
|
# putting queue's name, message, options, as aruments.
|
@@ -59,6 +62,7 @@ module Ap4r
|
|
59
62
|
# See the StoreMessage rdoc for more details.
|
60
63
|
#
|
61
64
|
def __ap4r_forward_by_stored_message_id(stored_message_id, options)
|
65
|
+
raise "not implemented"
|
62
66
|
# TODO: Find record and make queue info , 2006/10/13 kato-k
|
63
67
|
queue_name = nil
|
64
68
|
queue_message = nil
|
@@ -68,7 +72,7 @@ module Ap4r
|
|
68
72
|
alias :forward_by_stored_message_id :__ap4r_forward_by_stored_message_id
|
69
73
|
|
70
74
|
|
71
|
-
#
|
75
|
+
# Puts a message into queue.
|
72
76
|
# As queue_headers, some options are supported.
|
73
77
|
# See the reliable-msg docuememt for more details.
|
74
78
|
def __ap4r_queue_put(queue_name, queue_message, queue_headers)
|
@@ -84,7 +88,7 @@ end
|
|
84
88
|
# For test
|
85
89
|
if __FILE__ == $0
|
86
90
|
|
87
|
-
class TestSaf
|
91
|
+
class TestSaf #:nodoc:
|
88
92
|
|
89
93
|
include ::Ap4r::StoreAndForward
|
90
94
|
|
data/lib/ap4r/stored_message.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Author:: Kiwamu Kato
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
begin
|
@@ -59,13 +59,14 @@ module Ap4r
|
|
59
59
|
# * :delete_mode (:physical or :logical)
|
60
60
|
# Default delete mmode is physical.
|
61
61
|
# If you need logical delete, for example you neeed checking message
|
62
|
-
# duplication etc,
|
62
|
+
# duplication etc, set the <tt>Ap4r::AsyncController.saf_delete_mode</tt>
|
63
|
+
# <tt>:logical</tt>.
|
63
64
|
def self.destroy_if_exists(id, options)
|
64
65
|
result = nil
|
65
66
|
begin
|
66
67
|
result = StoredMessage.find(id)
|
67
68
|
rescue ActiveRecord::RecordNotFound
|
68
|
-
# There are
|
69
|
+
# There are possibilities that other threads or processes have already forwarded.
|
69
70
|
return nil
|
70
71
|
end
|
71
72
|
result.destroy_or_update(options)
|
data/lib/ap4r/util/irm.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
# Copyright:: Copyright (c)
|
1
|
+
# Author:: Shunichi Shinohara
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
$KCODE = 'u'
|
@@ -71,7 +71,7 @@ Ap4r::Configuration.load_setting_files
|
|
71
71
|
|
72
72
|
$original_main = self
|
73
73
|
|
74
|
-
class Object
|
74
|
+
class Object #:nodoc:
|
75
75
|
Ap4r::Configuration.services.each {|s|
|
76
76
|
module_eval <<-EOS
|
77
77
|
def #{s.name.to_s}
|
data/lib/ap4r/version.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Author:: Kiwamu Kato
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
module Ap4r
|
@@ -8,7 +8,7 @@ module Ap4r
|
|
8
8
|
module VERSION #:nodoc:
|
9
9
|
MAJOR = 0
|
10
10
|
MINOR = 3
|
11
|
-
TINY =
|
11
|
+
TINY = 2
|
12
12
|
|
13
13
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
14
14
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# Author:: Shunichi Shinohara
|
2
|
-
# Copyright:: Copyright (c)
|
2
|
+
# Copyright:: Copyright (c) 2007 Future Architect Inc.
|
3
3
|
# Licence:: MIT Licence
|
4
4
|
|
5
5
|
require 'reliable-msg'
|
@@ -24,21 +24,31 @@ module Ap4r
|
|
24
24
|
|
25
25
|
module Base
|
26
26
|
Converters = {}
|
27
|
-
|
27
|
+
|
28
|
+
# TODO: constant or class variable, whick is better? 2007/05/02 by shino
|
29
|
+
DRUBY_HOST = ENV['AP4R_DRUBY_HOST'] || 'localhost'
|
30
|
+
DRUBY_PORT = ENV['AP4R_DRUBY_PORT'] || '6438'
|
31
|
+
DRUBY_URI = "druby://#{DRUBY_HOST}:#{DRUBY_PORT}"
|
28
32
|
|
29
33
|
@@default_dispatch_mode = :HTTP
|
30
|
-
@@default_rm_options = { :delivery => :once }
|
34
|
+
@@default_rm_options = { :delivery => :once, :dispatch_mode => @@default_dispatch_mode }
|
31
35
|
@@default_queue_prefix = "queue."
|
32
36
|
|
33
37
|
mattr_accessor :default_dispatch_mode, :default_rm_options, :default_queue_prefix, :saf_delete_mode
|
34
38
|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
39
|
+
# Provides at-least-once QoS level.
|
40
|
+
# +block+ are tipically composed of database accesses and +async_dispatch+ calls.
|
41
|
+
# Database accesses are executed transactionallly by +active_record_class+'s transaction method.
|
42
|
+
# In the +block+, +async_dispatch+ calls invoke NOT immediate queueing but just storing messages
|
43
|
+
# to the database (assumed to be the same one as application uses).
|
44
|
+
#
|
45
|
+
# If the execution of +block+ finishes successfully, database transaction is committed and
|
46
|
+
# forward process of each stored message begins.
|
47
|
+
# Forward process composed in two parts. First puts the message into a queue, secondary update
|
48
|
+
# or delete the entry from a management table.
|
49
|
+
#
|
50
|
+
# SAF (store and forward) processing like this guarantees that any message
|
51
|
+
# is never lost and keeps reasonable performance (without two phase commit).
|
42
52
|
#
|
43
53
|
# Examples: Just call async_dispath method in this block.
|
44
54
|
#
|
@@ -57,7 +67,7 @@ module Ap4r
|
|
57
67
|
Thread.current[:stored_messages] = {}
|
58
68
|
|
59
69
|
# store
|
60
|
-
active_record_class ||= StoredMessage
|
70
|
+
active_record_class ||= ::Ap4r::StoredMessage
|
61
71
|
active_record_class.transaction(*objects, &block)
|
62
72
|
|
63
73
|
# forward
|
@@ -68,13 +78,14 @@ module Ap4r
|
|
68
78
|
# Once some error occured, such as disconnect reliable-msg or server crush,
|
69
79
|
# which is smart to keep to put a message or stop to do it?
|
70
80
|
# In the case of being many async messages, the former strategy is not so good.
|
81
|
+
#
|
82
|
+
# TODO: add delayed forward mode 2007/05/02 by shino
|
71
83
|
Thread.current[:stored_messages].each {|k,v|
|
72
84
|
__queue_put(v[:queue_name], v[:queue_message], v[:queue_headers])
|
73
85
|
forwarded_messages[k] = v
|
74
86
|
}
|
75
87
|
rescue Exception => err
|
76
|
-
# Don't raise any Exception.
|
77
|
-
# nop
|
88
|
+
# Don't raise any Exception. Application logic has already completed and messages are saved.
|
78
89
|
logger.warn("Failed to put a message into queue: #{err}")
|
79
90
|
end
|
80
91
|
|
@@ -86,8 +97,7 @@ module Ap4r
|
|
86
97
|
}
|
87
98
|
end
|
88
99
|
rescue Exception => err
|
89
|
-
# Don't raise any Exception.
|
90
|
-
# nop
|
100
|
+
# Don't raise any Exception. Application logic has already completed and messages are saved.
|
91
101
|
logger.warn("Failed to put a message into queue: #{err}")
|
92
102
|
end
|
93
103
|
|
@@ -115,29 +125,28 @@ module Ap4r
|
|
115
125
|
# Object of argumemts (async_params, options and rm_options) will not be modified.
|
116
126
|
# Implementors (of this class and converters) should not modify them.
|
117
127
|
#
|
118
|
-
def async_dispatch(
|
128
|
+
def async_dispatch(url_options = {}, async_params = nil, rm_options = nil)
|
129
|
+
# TODO: add :url to url_options to specify :target_url shortly 2007/05/02 by shino
|
119
130
|
if logger.debug?
|
131
|
+
logger.debug("url_options: ")
|
132
|
+
logger.debug(url_options.inspect)
|
120
133
|
logger.debug("async_params: ")
|
121
134
|
logger.debug(async_params.inspect)
|
122
|
-
logger.debug("
|
123
|
-
logger.debug(options.inspect)
|
124
|
-
logger.debug("rm_options")
|
135
|
+
logger.debug("rm_options: ")
|
125
136
|
logger.debug(rm_options.inspect)
|
126
137
|
end
|
127
138
|
|
128
139
|
# TODO: clone it, 2006/10/16 shino
|
129
|
-
|
130
|
-
|
140
|
+
url_options ||= {}
|
141
|
+
url_options[:controller] ||= self.controller_path.gsub("/", ".")
|
131
142
|
rm_options = @@default_rm_options.merge(rm_options || {})
|
132
|
-
# TODO: put into :dispatch_mode to @@default_rm_options
|
133
|
-
rm_options[:dispatch_mode] ||= @@default_dispatch_mode
|
134
143
|
|
135
144
|
# Only async_params is not cloned. options and rm_options are cloned before now.
|
136
145
|
# This is a current contract between this class and converter classes.
|
137
|
-
converter = Converters[rm_options[:dispatch_mode]].new(
|
146
|
+
converter = Converters[rm_options[:dispatch_mode]].new(url_options, async_params, rm_options, self)
|
138
147
|
logger.debug{"druby uri for queue-manager : #{DRUBY_URI}"}
|
139
148
|
|
140
|
-
queue_name = __get_queue_name(
|
149
|
+
queue_name = __get_queue_name(url_options, rm_options)
|
141
150
|
queue_message = converter.make_params
|
142
151
|
queue_headers = converter.make_rm_options
|
143
152
|
|
@@ -159,6 +168,7 @@ module Ap4r
|
|
159
168
|
|
160
169
|
private
|
161
170
|
def __queue_put(queue_name, queue_message, queue_headers)
|
171
|
+
# TODO: can use a Queue instance repeatedly? 2007/05/02 by shino
|
162
172
|
q = ReliableMsg::Queue.new(queue_name, :drb_uri => DRUBY_URI)
|
163
173
|
q.put(queue_message, queue_headers)
|
164
174
|
end
|
@@ -171,15 +181,14 @@ module Ap4r
|
|
171
181
|
|
172
182
|
end
|
173
183
|
|
174
|
-
|
175
|
-
# TODO: pluralize it, 2006/10/16 shino
|
176
|
-
module Converter #:nodoc:
|
184
|
+
module Converters #:nodoc:
|
177
185
|
|
178
186
|
# A base class for converter classes.
|
179
187
|
# Responsibilities of subclasses are as folows
|
180
188
|
# * by +make_params+, convert async_params to appropriate object
|
181
189
|
# * by +make_rm_options+, make appropriate +Hash+ passed by <tt>ReliableMsg::Queue#put</tt>
|
182
190
|
class Base
|
191
|
+
|
183
192
|
# Difine a constant +DISPATCH_MODE+ to value 'mode_symbol' and
|
184
193
|
# add self to a Converters list.
|
185
194
|
def self.dispatch_mode(mode_symbol)
|
@@ -187,31 +196,33 @@ module Ap4r
|
|
187
196
|
::Ap4r::AsyncController::Base::Converters[mode_symbol] = self
|
188
197
|
end
|
189
198
|
|
190
|
-
def initialize(
|
191
|
-
@
|
199
|
+
def initialize(url_options, async_params, rm_options, url_for_handler)
|
200
|
+
@url_options = url_options
|
192
201
|
@async_params = async_params
|
193
|
-
@options = options
|
194
202
|
@rm_options = rm_options
|
195
|
-
|
196
|
-
|
197
|
-
# helper method for <tt>ActionController#url_for</tt>
|
198
|
-
def url_for(url_for_options, *parameter_for_method_reference)
|
199
|
-
@controller.url_for(url_for_options, *parameter_for_method_reference)
|
203
|
+
@url_for_handler = url_for_handler
|
200
204
|
end
|
201
205
|
|
202
206
|
# Returns a object which passed to <tt>ReliableMsg::Queue.put(message, headers)</tt>'s
|
203
207
|
# first argument +message+.
|
204
208
|
# Should be implemented by subclasses.
|
205
209
|
def make_params
|
206
|
-
raise 'must be implemented'
|
210
|
+
raise 'must be implemented in subclasses'
|
207
211
|
end
|
208
212
|
|
209
213
|
# Returns a object which passed to <tt>ReliableMsg::Queue.put(message, headers)</tt>'s
|
210
214
|
# second argument +headers+.
|
211
215
|
# Should be implemented by subclasses.
|
212
216
|
def make_rm_options
|
213
|
-
raise 'must be implemented'
|
217
|
+
raise 'must be implemented in subclasses'
|
214
218
|
end
|
219
|
+
|
220
|
+
private
|
221
|
+
# helper method for <tt>ActionController#url_for</tt>
|
222
|
+
def url_for(url_for_options, *parameter_for_method_reference)
|
223
|
+
@url_for_handler.url_for(url_for_options, *parameter_for_method_reference)
|
224
|
+
end
|
225
|
+
|
215
226
|
end
|
216
227
|
|
217
228
|
class Http < Base
|
@@ -222,7 +233,7 @@ module Ap4r
|
|
222
233
|
end
|
223
234
|
|
224
235
|
def make_rm_options
|
225
|
-
@rm_options[:target_url] ||= url_for(@
|
236
|
+
@rm_options[:target_url] ||= url_for(@url_options)
|
226
237
|
@rm_options[:target_method] ||= 'POST'
|
227
238
|
#TODO: make option key to specify HTTP headers, 2006/10/16 shino
|
228
239
|
@rm_options
|
@@ -243,12 +254,12 @@ module Ap4r
|
|
243
254
|
end
|
244
255
|
|
245
256
|
def action_api_name
|
246
|
-
action_method_name = @
|
257
|
+
action_method_name = @url_options[:action]
|
247
258
|
action_method_name.camelcase
|
248
259
|
end
|
249
260
|
|
250
261
|
def options_without_action
|
251
|
-
new_opts = @
|
262
|
+
new_opts = @url_options.dup
|
252
263
|
new_opts[:action] = nil
|
253
264
|
new_opts
|
254
265
|
end
|
data/script/mongrel_ap4r
ADDED
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ap4r
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.3.
|
7
|
-
date: 2007-
|
6
|
+
version: 0.3.2
|
7
|
+
date: 2007-06-06 00:00:00 +09:00
|
8
8
|
summary: Asynchronous Processing for Ruby.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -36,12 +36,11 @@ files:
|
|
36
36
|
- doc
|
37
37
|
- lib
|
38
38
|
- MIT-LICENSE
|
39
|
-
- pkg
|
40
39
|
- rails_plugin
|
41
40
|
- Rakefile
|
42
41
|
- README
|
43
42
|
- script
|
44
|
-
-
|
43
|
+
- spec
|
45
44
|
- bin/ap4r_setup
|
46
45
|
- config/ap4r_settings.rb
|
47
46
|
- config/log4r.yaml
|
@@ -49,18 +48,20 @@ files:
|
|
49
48
|
- config/queues_disk.cfg
|
50
49
|
- config/queues_mysql.cfg
|
51
50
|
- rails_plugin/ap4r
|
52
|
-
- rails_plugin/ap4r/init.rb
|
53
51
|
- rails_plugin/ap4r/lib
|
54
52
|
- rails_plugin/ap4r/lib/async_controller.rb
|
55
53
|
- script/irm
|
56
54
|
- script/loop.cmd
|
57
55
|
- script/loop.rb
|
58
|
-
- script/mongrel_ap4r
|
56
|
+
- script/mongrel_ap4r
|
59
57
|
- script/start
|
60
58
|
- script/stop
|
61
59
|
- lib/ap4r
|
60
|
+
- lib/ap4r/carrier.rb
|
61
|
+
- lib/ap4r/dispatcher.rb
|
62
62
|
- lib/ap4r/message_store_ext.rb
|
63
63
|
- lib/ap4r/mongrel.rb
|
64
|
+
- lib/ap4r/mongrel_ap4r.rb
|
64
65
|
- lib/ap4r/multi_queue.rb
|
65
66
|
- lib/ap4r/queue_manager_ext.rb
|
66
67
|
- lib/ap4r/queue_manager_ext_debug.rb
|
@@ -75,10 +76,8 @@ files:
|
|
75
76
|
- lib/ap4r/stored_message.rb
|
76
77
|
- lib/ap4r/util
|
77
78
|
- lib/ap4r/util/irm.rb
|
78
|
-
- lib/ap4r/util/loc.rb
|
79
79
|
- lib/ap4r/util/queue_client.rb
|
80
80
|
- lib/ap4r/version.rb
|
81
|
-
- lib/ap4r/xxx_create_table_for_saf.rb
|
82
81
|
- lib/ap4r.rb
|
83
82
|
test_files: []
|
84
83
|
|
@@ -108,3 +107,30 @@ dependencies:
|
|
108
107
|
- !ruby/object:Gem::Version
|
109
108
|
version: 1.1.0
|
110
109
|
version:
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: rake
|
112
|
+
version_requirement:
|
113
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.0.0
|
118
|
+
version:
|
119
|
+
- !ruby/object:Gem::Dependency
|
120
|
+
name: activesupport
|
121
|
+
version_requirement:
|
122
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ">"
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: 0.0.0
|
127
|
+
version:
|
128
|
+
- !ruby/object:Gem::Dependency
|
129
|
+
name: mongrel
|
130
|
+
version_requirement:
|
131
|
+
version_requirements: !ruby/object:Gem::Version::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">"
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: 0.0.0
|
136
|
+
version:
|