manana 0.0.1 → 0.0.2
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/.yardopts +1 -1
- data/Gemfile +20 -4
- data/LICENSE.txt +1 -1
- data/README.md +37 -7
- data/Rakefile +7 -0
- data/lib/manana/version.rb +1 -1
- data/lib/manana.rb +35 -5
- data/manana.gemspec +3 -3
- data/samples/common/samples.gemfile +10 -0
- data/samples/common/samples.gemfile.lock +42 -0
- data/samples/common/samples_helper.rb +7 -0
- data/samples/exponential_backoff.rb +65 -0
- data/samples/fast_startup.rb +83 -0
- data/samples/self_healing.rb +104 -0
- data/test/test_manana.rb +17 -5
- metadata +15 -8
data/.yardopts
CHANGED
data/Gemfile
CHANGED
@@ -5,10 +5,26 @@ gemspec
|
|
5
5
|
|
6
6
|
# these aren't strictly needed for development but are nice to have
|
7
7
|
unless ENV["TRAVIS"] == "1"
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
|
9
|
+
group :development do
|
10
|
+
gem 'yard'
|
11
|
+
gem 'redcarpet'
|
12
|
+
|
13
|
+
gem 'pry'
|
14
|
+
gem 'pry-debugger'
|
15
|
+
gem 'pry-rescue'
|
16
|
+
gem 'pry-stack_explorer'
|
17
|
+
end
|
18
|
+
|
19
|
+
group :samples do
|
20
|
+
gem 'savon', '~> 2.3'
|
21
|
+
gem 'webmock'
|
22
|
+
end
|
23
|
+
|
24
|
+
group :test do
|
25
|
+
gem 'simplecov'
|
26
|
+
end
|
27
|
+
|
12
28
|
end
|
13
29
|
|
14
30
|
# for travis.cl
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,42 @@
|
|
1
1
|
# Manana
|
2
2
|
|
3
|
-
*Manana* lets you defer the initialization of
|
3
|
+
*Manana* lets you defer the initialization of an object until its methods are called.
|
4
4
|
|
5
|
-
This can be useful in cases where
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
This can be useful in cases where initialization may take a long time or fail due to errors. For example, in rails, if
|
6
|
+
the database specified in `database.yml` doesn't exist at start time, the rails application will fail initialization. Likewise
|
7
|
+
if you tie configuration of SOAP services (e.g. using [Savon](http://savonrb.com/version2/)) to your application initialization,
|
8
|
+
and the service wsdl isn't up, your application will fail to start.
|
9
|
+
|
10
|
+
Instead, it is an established best practice in service-oriented architectures to make your application or service *startup order independent*:
|
11
|
+
i.e. your app starts fast and initializes other dependencies afterwards, providing fault detection and *self-healing* properties for the app.
|
12
|
+
|
13
|
+
*Manana* is a simple approach that allows you to keep your configuration and initialization code in the same place, while deferring it to method calls.
|
14
|
+
|
15
|
+
### Pros
|
16
|
+
|
17
|
+
* Reduces the startup time for your app. (i.e. moves the startup cost from initialization to first use)
|
18
|
+
|
19
|
+
* Once initialization is succesful, it stores the object instance for reuse.
|
20
|
+
|
21
|
+
* Until the initialization is successful, it will retry every time a method is called.
|
22
|
+
|
23
|
+
* You can layer more complex retry semantics such as [exponential backoff](http://en.wikipedia.org/wiki/Exponential_backoff) using this wrapper. See [samples/exponential_backoff.rb](https://github.com/coldnebo/manana/blob/master/samples/exponential_backoff.rb)
|
24
|
+
|
25
|
+
### Cons
|
26
|
+
|
27
|
+
* If your initialization takes a very long time, (i.e. a cache) you may want to pre-warm it instead of taking the hit on the first use of the object.
|
28
|
+
|
29
|
+
* Very simple approach. You may want more complex retry semantics, or pooling.
|
30
|
+
|
31
|
+
### Similar ideas:
|
32
|
+
|
33
|
+
* [Connection pool](http://en.wikipedia.org/wiki/Connection_pool) of one?
|
34
|
+
|
35
|
+
* [Avoid Start Order Dependencies](http://wiki.osgi.org/wiki/Avoid_Start_Order_Dependencies)
|
36
|
+
|
37
|
+
* [Data Centers need shutdown/startup order](http://www.boche.net/blog/index.php/2009/01/01/datacenters-need-shutdownstartup-order/)
|
38
|
+
|
39
|
+
* 'self-healing' initialization faults from the practice of [Autonomic computing](http://en.wikipedia.org/wiki/Autonomic_computing)
|
10
40
|
|
11
41
|
## Installation
|
12
42
|
|
@@ -24,7 +54,7 @@ Or install it yourself as:
|
|
24
54
|
|
25
55
|
## Usage
|
26
56
|
|
27
|
-
|
57
|
+
See the [samples](https://github.com/coldnebo/manana/blob/master/samples) for examples of use.
|
28
58
|
|
29
59
|
## Contributing
|
30
60
|
|
data/Rakefile
CHANGED
data/lib/manana/version.rb
CHANGED
data/lib/manana.rb
CHANGED
@@ -1,12 +1,42 @@
|
|
1
1
|
require "manana/version"
|
2
2
|
|
3
|
+
|
4
|
+
# *Manana* lets you defer the initialization of an object until its methods are called.
|
5
|
+
# @example basic usage - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
|
6
|
+
# # initialization...
|
7
|
+
# client = Manana.wrap {
|
8
|
+
# Weather.setup
|
9
|
+
# Weather
|
10
|
+
# }
|
11
|
+
#
|
12
|
+
# runtime_loop {
|
13
|
+
# # wait for next interval
|
14
|
+
# weather = client.city_weather("02201") # deferred initialization happens here once
|
15
|
+
# puts "At %s the temperature is currently %s F and the humidity is %s." % [weather.city, weather.temperature, weather.relative_humidity]
|
16
|
+
# }
|
17
|
+
#
|
3
18
|
class Manana
|
4
|
-
attr_reader :deferred_initialization, :instance
|
5
19
|
|
6
|
-
|
7
|
-
|
20
|
+
# wraps an object initialization block so that it can be deferred to a later time when object methods are called.
|
21
|
+
# @example wrap an object - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
|
22
|
+
# client = Manana.wrap {
|
23
|
+
# Weather.setup # initialize the class
|
24
|
+
# Weather # return the Weather class
|
25
|
+
# }
|
26
|
+
#
|
27
|
+
# @param initialization_block [Proc] object initialization. the block must return the object to be wrapped.
|
28
|
+
# @return [Manana] a wrapped version of the object.
|
29
|
+
def self.wrap(&initialization_block)
|
30
|
+
Manana.new(&initialization_block)
|
8
31
|
end
|
9
32
|
|
33
|
+
# passes any method call through to the wrapped object after ensuring that the initialization block has
|
34
|
+
# successfully completed once (setting a valid instance of the object).
|
35
|
+
# @note Once the initialization block succeeds, it keeps the resulting object instance for subsequent method calls.
|
36
|
+
#
|
37
|
+
# @example calling a wrapped object - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
|
38
|
+
# weather = client.city_weather("02201")
|
39
|
+
#
|
10
40
|
def method_missing(method, *args, &block)
|
11
41
|
instance = get_instance
|
12
42
|
instance.send(method, *args, &block);
|
@@ -14,8 +44,8 @@ class Manana
|
|
14
44
|
|
15
45
|
private
|
16
46
|
|
17
|
-
def initialize(&
|
18
|
-
@deferred_initialization =
|
47
|
+
def initialize(&initialization_block)
|
48
|
+
@deferred_initialization = initialization_block
|
19
49
|
end
|
20
50
|
|
21
51
|
def get_instance
|
data/manana.gemspec
CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Manana::VERSION
|
9
9
|
spec.authors = ["coldnebo"]
|
10
10
|
spec.email = ["larry.kyrala@gmail.com"]
|
11
|
-
spec.description = %q{provides a simple way to defer initialization of an object
|
12
|
-
spec.summary = %q{
|
13
|
-
spec.homepage = ""
|
11
|
+
spec.description = %q{provides a simple way to defer initialization of an object until its methods are called}
|
12
|
+
spec.summary = %q{provides a simple way to defer initialization of an object until its methods are called}
|
13
|
+
spec.homepage = "https://github.com/coldnebo/manana"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/)
|
@@ -0,0 +1,42 @@
|
|
1
|
+
GEM
|
2
|
+
remote: https://rubygems.org/
|
3
|
+
specs:
|
4
|
+
addressable (2.3.5)
|
5
|
+
akami (1.2.0)
|
6
|
+
gyoku (>= 0.4.0)
|
7
|
+
nokogiri (>= 1.4.0)
|
8
|
+
builder (3.2.2)
|
9
|
+
crack (0.4.1)
|
10
|
+
safe_yaml (~> 0.9.0)
|
11
|
+
gyoku (1.1.0)
|
12
|
+
builder (>= 2.1.2)
|
13
|
+
httpi (2.1.0)
|
14
|
+
rack
|
15
|
+
rubyntlm (~> 0.3.2)
|
16
|
+
nokogiri (1.5.10)
|
17
|
+
nori (2.3.0)
|
18
|
+
rack (1.5.2)
|
19
|
+
rubyntlm (0.3.4)
|
20
|
+
safe_yaml (0.9.7)
|
21
|
+
savon (2.3.0)
|
22
|
+
akami (~> 1.2.0)
|
23
|
+
builder (>= 2.1.2)
|
24
|
+
gyoku (~> 1.1.0)
|
25
|
+
httpi (~> 2.1.0)
|
26
|
+
nokogiri (>= 1.4.0, < 1.6)
|
27
|
+
nori (~> 2.3.0)
|
28
|
+
wasabi (~> 3.2.0)
|
29
|
+
wasabi (3.2.0)
|
30
|
+
httpi (~> 2.0)
|
31
|
+
nokogiri (>= 1.4.0, < 1.6)
|
32
|
+
webmock (1.15.2)
|
33
|
+
addressable (>= 2.2.7)
|
34
|
+
crack (>= 0.3.2)
|
35
|
+
|
36
|
+
PLATFORMS
|
37
|
+
ruby
|
38
|
+
|
39
|
+
DEPENDENCIES
|
40
|
+
rack
|
41
|
+
savon (~> 2.3)
|
42
|
+
webmock
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# sample helper takes care of loading the gem from source without requiring it to be rebuilt and installed.
|
2
|
+
# this is useful in allowing the samples in this directory to evolve the behavior of the actual gem.
|
3
|
+
|
4
|
+
lp = File.expand_path(File.join(*%w[.. .. lib]), File.dirname(__FILE__))
|
5
|
+
unless $LOAD_PATH.include?(lp)
|
6
|
+
$LOAD_PATH.unshift(lp)
|
7
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# This sample demonstrates how exponential backoff can be layered on top of Manana
|
2
|
+
#
|
3
|
+
# run from the gem dir with:
|
4
|
+
# $ rake samples
|
5
|
+
# $ ruby samples/exponential_backoff.rb
|
6
|
+
|
7
|
+
require_relative 'common/samples_helper.rb'
|
8
|
+
|
9
|
+
# ------------------------- sample code starts here -------------------------
|
10
|
+
|
11
|
+
require 'manana'
|
12
|
+
require 'benchmark'
|
13
|
+
|
14
|
+
|
15
|
+
class PoorService
|
16
|
+
@@instance = 0
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@@instance += 1
|
20
|
+
if @@instance <= 3
|
21
|
+
raise "failed to init"
|
22
|
+
end
|
23
|
+
puts "successfully inited service."
|
24
|
+
end
|
25
|
+
|
26
|
+
def process
|
27
|
+
puts "successfully called service!"
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
# ------------ initialization code
|
33
|
+
|
34
|
+
client = Manana.wrap {
|
35
|
+
# exponential backkoff logic in the initialization block
|
36
|
+
retries = 0
|
37
|
+
obj = nil
|
38
|
+
|
39
|
+
puts "trying to create service object..."
|
40
|
+
begin
|
41
|
+
obj = PoorService.new
|
42
|
+
rescue RuntimeError => e
|
43
|
+
puts "couldn't create object, sleeping for #{2**retries} seconds before next try..."
|
44
|
+
sleep(2**retries)
|
45
|
+
retries += 1
|
46
|
+
|
47
|
+
if retries <= 3
|
48
|
+
retry
|
49
|
+
else
|
50
|
+
puts "giving up."
|
51
|
+
raise e
|
52
|
+
end
|
53
|
+
end
|
54
|
+
obj
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
# ------------ runtime code
|
59
|
+
|
60
|
+
client.process
|
61
|
+
client.process
|
62
|
+
client.process
|
63
|
+
client.process
|
64
|
+
|
65
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# This sample demonstrates how Manana may be used to defer a long initialization
|
2
|
+
# to the first method call.
|
3
|
+
#
|
4
|
+
# run from the gem dir with:
|
5
|
+
# $ rake samples
|
6
|
+
# $ ruby samples/fast_startup.rb
|
7
|
+
|
8
|
+
require_relative 'common/samples_helper.rb'
|
9
|
+
|
10
|
+
# ------------------------- sample code starts here -------------------------
|
11
|
+
|
12
|
+
require 'manana'
|
13
|
+
require 'benchmark'
|
14
|
+
|
15
|
+
|
16
|
+
class DeathStar
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
puts " DeathStar initialization sequence commencing..."
|
20
|
+
super_complex_startup_sequence
|
21
|
+
puts " ...sequence complete."
|
22
|
+
end
|
23
|
+
|
24
|
+
def navigate_to(planet)
|
25
|
+
puts "setting course for the planet '#{planet}'"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def super_complex_startup_sequence
|
31
|
+
puts " 1. press the 'start' button."
|
32
|
+
puts " 2. snooze while Vader isn't looking."
|
33
|
+
sleep(5)
|
34
|
+
puts " 3. ???"
|
35
|
+
puts " 4. profit!"
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
# ------------ initialization code
|
41
|
+
|
42
|
+
mini_death_star = nil
|
43
|
+
|
44
|
+
puts "[Vader]: requsition a new DeathStar and make it snappy!"
|
45
|
+
# boss said requisitions have to be faster*! Manana to the rescue!
|
46
|
+
puts Benchmark.measure {
|
47
|
+
mini_death_star = Manana.wrap {
|
48
|
+
DeathStar.new
|
49
|
+
}
|
50
|
+
}
|
51
|
+
puts "[Expendable Commander]: completed, sir!"
|
52
|
+
|
53
|
+
|
54
|
+
puts "-------------------------------------------"
|
55
|
+
|
56
|
+
|
57
|
+
# ------------ runtime code
|
58
|
+
|
59
|
+
puts "[Vader]: ok, send it towards some rebels..."
|
60
|
+
|
61
|
+
# * this first method eats the hidden startup cost...
|
62
|
+
puts Benchmark.measure {
|
63
|
+
mini_death_star.navigate_to("Yavin")
|
64
|
+
}
|
65
|
+
puts "[Vader raises an eyebrow and starts to reach towards the commander] \n# first method call was long, but subsequent calls are faster..."
|
66
|
+
|
67
|
+
# * subsequent method calls are fast though... maybe tradeoff is good enough for Vader?
|
68
|
+
puts Benchmark.measure {
|
69
|
+
mini_death_star.navigate_to("Bespin")
|
70
|
+
}
|
71
|
+
|
72
|
+
puts Benchmark.measure {
|
73
|
+
mini_death_star.navigate_to("Tatooine")
|
74
|
+
}
|
75
|
+
|
76
|
+
puts "[Vader shrugs]: Well done Expendable Commander!"
|
77
|
+
puts "[Expendable Commander sweatly profusely]: Thank you Lord Vader!"
|
78
|
+
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# This sample demonstrates how Manana may be used to create a self-healing soap adapter
|
2
|
+
# by wrapping an existing Savon::Model client.
|
3
|
+
#
|
4
|
+
# run from the gem dir with:
|
5
|
+
# $ rake samples
|
6
|
+
# $ ruby samples/self_healing.rb
|
7
|
+
|
8
|
+
require_relative 'common/samples_helper.rb'
|
9
|
+
|
10
|
+
# ------------------------- sample code starts here -------------------------
|
11
|
+
|
12
|
+
require 'manana'
|
13
|
+
require 'savon'
|
14
|
+
require 'ostruct'
|
15
|
+
|
16
|
+
# used to simulate conn up/down
|
17
|
+
require 'webmock'
|
18
|
+
include WebMock::API
|
19
|
+
# fake a failure to get the wsdl (service down temporarily)
|
20
|
+
stub_request(:any, /wsf.cdyne.com\/.*/).
|
21
|
+
to_return(:status => 500, :body => "Internal Server Error", :headers => {})
|
22
|
+
|
23
|
+
|
24
|
+
LOGGING_ENABLED = false
|
25
|
+
HTTPI.log = false unless LOGGING_ENABLED
|
26
|
+
|
27
|
+
class Weather < OpenStruct
|
28
|
+
extend Savon::Model
|
29
|
+
|
30
|
+
client wsdl: "http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL", convert_request_keys_to: :none, log: LOGGING_ENABLED
|
31
|
+
|
32
|
+
def self.setup
|
33
|
+
# if this were outside of setup() the class would fail to load if the service was down.
|
34
|
+
# instead we dynamically initialize the available operations from withing a class method to be used by the Manana wrapper.
|
35
|
+
operations *client.operations
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.city_weather(zip)
|
39
|
+
resp = get_city_weather_by_zip(message: {"ZIP" => zip})
|
40
|
+
weather = resp.body[:get_city_weather_by_zip_response][:get_city_weather_by_zip_result]
|
41
|
+
Weather.new(weather)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
# ------------ initialization code
|
47
|
+
|
48
|
+
# Before we start, we use Manana to wrap the client setup so that method calls on the client can be self-healing in case of failure.
|
49
|
+
# NOTE: that the caller doesn't have to deal with whether or not this initialization succeeded, they can just call the client methods repeatedly.
|
50
|
+
client = Manana.wrap {
|
51
|
+
Weather.setup
|
52
|
+
Weather
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
# ------------ runtime code
|
57
|
+
|
58
|
+
# first call fails...
|
59
|
+
# a) Weather.setup() called, but raises because the server is 500.
|
60
|
+
begin
|
61
|
+
weather = client.city_weather("02201")
|
62
|
+
rescue Wasabi::Resolver::HTTPError => e
|
63
|
+
puts "# 1. first call failed as expected, because Weather.setup() couldn't connect to provide the operations for the client."
|
64
|
+
end
|
65
|
+
|
66
|
+
# server restored
|
67
|
+
WebMock.disable!
|
68
|
+
|
69
|
+
# second call ok...
|
70
|
+
# a) Weather.setup() succeeds, caches instance for future use.
|
71
|
+
# b) city_weather() succeeds.
|
72
|
+
weather = client.city_weather("02201")
|
73
|
+
|
74
|
+
puts "# 2. second call should succeed; Weather.setup() runs successfully and returns a successfully intialized Weather class."
|
75
|
+
puts " > At %s the temperature is currently %s F and the humidity is %s." % [weather.city, weather.temperature, weather.relative_humidity]
|
76
|
+
|
77
|
+
# server down again
|
78
|
+
WebMock.enable!
|
79
|
+
|
80
|
+
# third call; service down again...
|
81
|
+
# remember, we already have a valid instance, so Weather.setup() is not called this time.
|
82
|
+
# a) city_weather() fails because the server is 500.
|
83
|
+
begin
|
84
|
+
weather = client.city_weather("02201")
|
85
|
+
rescue Savon::HTTPError => e
|
86
|
+
puts "# 3. third call fails; the connection is down again, but this time the failure is in the API call since Weather has successfully intialized opertaions from call #2."
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# server restored
|
91
|
+
WebMock.disable!
|
92
|
+
|
93
|
+
# fourth call ok...
|
94
|
+
# a) city_weather() succeeds.
|
95
|
+
weather = client.city_weather("02201")
|
96
|
+
|
97
|
+
puts "# 4. fourth call should succeed; connection is up again, still using cached operations from the first time service was up (call #2)."
|
98
|
+
puts " > At %s the temperature is currently %s F and the humidity is %s." % [weather.city, weather.temperature, weather.relative_humidity]
|
99
|
+
|
100
|
+
|
101
|
+
puts "\nThis concludes the demonstration of how Manana provides self-healing capability to a web-service adapter."
|
102
|
+
|
103
|
+
|
104
|
+
|
data/test/test_manana.rb
CHANGED
@@ -22,11 +22,7 @@ class TestManana < MiniTest::Unit::TestCase
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def raise_something
|
25
|
-
raise "
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.do_another_thing
|
29
|
-
"I did something else" # simulate a class method call
|
25
|
+
raise "kablooey!" # simulate a call that raises an exception
|
30
26
|
end
|
31
27
|
}
|
32
28
|
end
|
@@ -43,6 +39,14 @@ class TestManana < MiniTest::Unit::TestCase
|
|
43
39
|
assert_raises RuntimeError do
|
44
40
|
obj.raise_something
|
45
41
|
end
|
42
|
+
|
43
|
+
begin
|
44
|
+
obj.raise_something
|
45
|
+
rescue Exception => e
|
46
|
+
# make sure we get an appropriate stack trace at the point of raise.
|
47
|
+
assert_match(/test_manana.rb:25:in .raise_something./, e.backtrace.first)
|
48
|
+
end
|
49
|
+
|
46
50
|
end
|
47
51
|
|
48
52
|
def test_deferred_init
|
@@ -68,6 +72,14 @@ class TestManana < MiniTest::Unit::TestCase
|
|
68
72
|
assert_instance_of(String, result)
|
69
73
|
|
70
74
|
|
75
|
+
begin
|
76
|
+
handle.raise_something
|
77
|
+
rescue Exception => e
|
78
|
+
# make sure we get an appropriate stack trace at the point of raise.
|
79
|
+
assert_match(/test_manana.rb:25:in .raise_something./, e.backtrace.first)
|
80
|
+
end
|
81
|
+
|
82
|
+
|
71
83
|
end
|
72
84
|
|
73
85
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-11-
|
12
|
+
date: 2013-11-15 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -59,8 +59,8 @@ dependencies:
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
-
description: provides a simple way to defer initialization of an object
|
63
|
-
|
62
|
+
description: provides a simple way to defer initialization of an object until its
|
63
|
+
methods are called
|
64
64
|
email:
|
65
65
|
- larry.kyrala@gmail.com
|
66
66
|
executables: []
|
@@ -77,9 +77,15 @@ files:
|
|
77
77
|
- lib/manana.rb
|
78
78
|
- lib/manana/version.rb
|
79
79
|
- manana.gemspec
|
80
|
+
- samples/common/samples.gemfile
|
81
|
+
- samples/common/samples.gemfile.lock
|
82
|
+
- samples/common/samples_helper.rb
|
83
|
+
- samples/exponential_backoff.rb
|
84
|
+
- samples/fast_startup.rb
|
85
|
+
- samples/self_healing.rb
|
80
86
|
- test/minitest_helper.rb
|
81
87
|
- test/test_manana.rb
|
82
|
-
homepage:
|
88
|
+
homepage: https://github.com/coldnebo/manana
|
83
89
|
licenses:
|
84
90
|
- MIT
|
85
91
|
post_install_message:
|
@@ -94,7 +100,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
94
100
|
version: '0'
|
95
101
|
segments:
|
96
102
|
- 0
|
97
|
-
hash: -
|
103
|
+
hash: -1234298163661349463
|
98
104
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
105
|
none: false
|
100
106
|
requirements:
|
@@ -103,13 +109,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
103
109
|
version: '0'
|
104
110
|
segments:
|
105
111
|
- 0
|
106
|
-
hash: -
|
112
|
+
hash: -1234298163661349463
|
107
113
|
requirements: []
|
108
114
|
rubyforge_project:
|
109
115
|
rubygems_version: 1.8.25
|
110
116
|
signing_key:
|
111
117
|
specification_version: 3
|
112
|
-
summary:
|
118
|
+
summary: provides a simple way to defer initialization of an object until its methods
|
119
|
+
are called
|
113
120
|
test_files:
|
114
121
|
- test/minitest_helper.rb
|
115
122
|
- test/test_manana.rb
|