manana 0.1.0 → 0.5.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.
- checksums.yaml +7 -0
- data/.travis.yml +1 -0
- data/Gemfile +6 -5
- data/README.md +1 -1
- data/lib/manana/version.rb +1 -1
- data/lib/manana.rb +34 -32
- data/manana.gemspec +1 -1
- data/samples/exponential_backoff.rb +1 -1
- data/samples/fast_startup.rb +1 -1
- data/samples/self_healing.rb +1 -1
- data/test/base_klass.rb +17 -0
- data/test/minitest_helper.rb +1 -0
- data/test/test_manana.rb +4 -3
- data/test/test_with_subclass.rb +42 -0
- metadata +22 -32
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4260f96ef0f5a33bc8a66db747e1759388927bc1
|
4
|
+
data.tar.gz: 9cb8a090b23e690c940fdefbbd1ababa97c41fd7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd56b8099f8cfad6e654fb4c2093d95e583c96dd433d3a690661e63d98c0228337e6c48739feda76a5757a8232ffb90d4bd63785cff5179d90d1181b17ee91a3
|
7
|
+
data.tar.gz: 46bcc0990610755a158174ce7715c41c2d70bbd55d7858e289714a013bee6cb4e460bc910f178dab0ec6ef7541089795ab4063401d40d2fd96fdd3b90c9372d7
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -10,10 +10,12 @@ unless ENV["TRAVIS"] == "1"
|
|
10
10
|
gem 'yard'
|
11
11
|
gem 'redcarpet'
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
if RUBY_VERSION =~ /^2\./
|
14
|
+
gem 'pry-byebug'
|
15
|
+
else
|
16
|
+
gem 'pry'
|
17
|
+
end
|
18
|
+
|
17
19
|
end
|
18
20
|
|
19
21
|
group :samples do
|
@@ -29,6 +31,5 @@ end
|
|
29
31
|
|
30
32
|
# for travis.cl
|
31
33
|
group :test do
|
32
|
-
gem 'rake'
|
33
34
|
gem 'mocha'
|
34
35
|
end
|
data/README.md
CHANGED
data/lib/manana/version.rb
CHANGED
data/lib/manana.rb
CHANGED
@@ -4,7 +4,7 @@ require "manana/version"
|
|
4
4
|
# *Manana* lets you defer the initialization of an object until its methods are called.
|
5
5
|
# @example basic usage - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
|
6
6
|
# # initialization...
|
7
|
-
# client = Manana.
|
7
|
+
# client = Manana.wrap {
|
8
8
|
# Weather.setup
|
9
9
|
# Weather
|
10
10
|
# }
|
@@ -16,50 +16,52 @@ require "manana/version"
|
|
16
16
|
# }
|
17
17
|
#
|
18
18
|
class Manana
|
19
|
-
|
20
|
-
|
19
|
+
private_class_method :new
|
20
|
+
|
21
|
+
# wraps the initialization of an object so that it can be deferred to a later time when object methods are called.
|
21
22
|
# @example wrap an object - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
|
22
|
-
# client = Manana.
|
23
|
+
# client = Manana.wrap {
|
23
24
|
# Weather.setup # initialize the class
|
24
25
|
# Weather # return the Weather class
|
25
26
|
# }
|
26
27
|
#
|
27
28
|
# @param initialization_block [Proc] object initialization. the block must return the object to be wrapped.
|
28
|
-
# @return [
|
29
|
-
def self.
|
30
|
-
|
29
|
+
# @return [Deferrable] a wrapped version of the object.
|
30
|
+
def self.wrap(&initialization_block)
|
31
|
+
Deferrable.send(:new,&initialization_block)
|
31
32
|
end
|
32
33
|
|
33
|
-
#
|
34
|
-
|
35
|
-
|
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
|
-
#
|
40
|
-
def method_missing(method, *args, &block)
|
41
|
-
instance = safe_get_instance
|
42
|
-
instance.send(method, *args, &block);
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
34
|
+
# class that proxies all requests to the wrapped object, ensuring that the object has been correctly initialized first.
|
35
|
+
class Deferrable < ::BasicObject
|
36
|
+
private_class_method :new
|
46
37
|
|
47
|
-
|
48
|
-
|
49
|
-
@
|
50
|
-
|
38
|
+
# passes any method call through to the wrapped object after ensuring that the initialization block has
|
39
|
+
# successfully completed once (thereby initializing the wrapped object).
|
40
|
+
# @note Once the initialization block succeeds, it keeps the resulting object for subsequent method calls.
|
41
|
+
#
|
42
|
+
# @example calling a wrapped object - see {https://github.com/coldnebo/manana/blob/master/samples/self_healing.rb samples/self_healing.rb}
|
43
|
+
# weather = client.city_weather("02201")
|
44
|
+
#
|
45
|
+
def method_missing(method, *args, &block)
|
46
|
+
_object.send(method, *args, &block);
|
47
|
+
end
|
51
48
|
|
52
|
-
|
53
|
-
@
|
54
|
-
|
49
|
+
# allows direct access to the wrapped object -- useful for debugging
|
50
|
+
# @return [Object] the object being wrapped
|
51
|
+
def _object
|
52
|
+
@mutex.synchronize do
|
53
|
+
if @object.nil?
|
54
|
+
@object = @deferred_initialization.call
|
55
|
+
end
|
56
|
+
@object
|
57
|
+
end
|
55
58
|
end
|
56
|
-
end
|
57
59
|
|
58
|
-
|
59
|
-
|
60
|
-
@
|
60
|
+
private
|
61
|
+
def initialize(&initialization_block)
|
62
|
+
@mutex = ::Mutex.new
|
63
|
+
@deferred_initialization = initialization_block
|
61
64
|
end
|
62
|
-
@instance
|
63
65
|
end
|
64
66
|
|
65
67
|
end
|
data/manana.gemspec
CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_development_dependency "bundler"
|
21
|
+
spec.add_development_dependency "bundler"
|
22
22
|
spec.add_development_dependency "rake"
|
23
23
|
spec.add_development_dependency "minitest"
|
24
24
|
end
|
data/samples/fast_startup.rb
CHANGED
@@ -44,7 +44,7 @@ mini_death_star = nil
|
|
44
44
|
puts "[Vader]: requsition a new DeathStar and make it snappy!"
|
45
45
|
# boss said requisitions have to be faster*! Manana to the rescue!
|
46
46
|
puts Benchmark.measure {
|
47
|
-
mini_death_star = Manana.
|
47
|
+
mini_death_star = Manana.wrap {
|
48
48
|
DeathStar.new
|
49
49
|
}
|
50
50
|
}
|
data/samples/self_healing.rb
CHANGED
@@ -47,7 +47,7 @@ end
|
|
47
47
|
|
48
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
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.
|
50
|
+
client = Manana.wrap {
|
51
51
|
Weather.setup
|
52
52
|
Weather
|
53
53
|
}
|
data/test/base_klass.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# something like ActiveRecord::Base
|
2
|
+
class BaseKlass
|
3
|
+
|
4
|
+
def self.connected?
|
5
|
+
@@connected ||= false
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.establish_connection
|
9
|
+
@@connected = true
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.find
|
13
|
+
raise "not connected!" unless self.connected?
|
14
|
+
[1,2,3]
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/test/minitest_helper.rb
CHANGED
data/test/test_manana.rb
CHANGED
@@ -33,10 +33,10 @@ class TestManana < Minitest::Test
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
36
|
+
def test_wrap
|
37
37
|
obj = nil
|
38
38
|
out, err = capture_io do
|
39
|
-
obj = Manana.
|
39
|
+
obj = Manana.wrap {
|
40
40
|
Klass.new
|
41
41
|
}
|
42
42
|
end
|
@@ -65,11 +65,12 @@ class TestManana < Minitest::Test
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
|
68
69
|
# https://github.com/coldnebo/manana/issues/1
|
69
70
|
def test_that_init_is_threadsafe
|
70
71
|
Klass.reset
|
71
72
|
|
72
|
-
klass = Manana.
|
73
|
+
klass = Manana.wrap {
|
73
74
|
sleep(1)
|
74
75
|
Klass.incr
|
75
76
|
Klass
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'minitest_helper'
|
2
|
+
require 'base_klass'
|
3
|
+
|
4
|
+
class TestWithSubclass < Minitest::Test
|
5
|
+
|
6
|
+
# initialize a very generic example object that does some stuff in initialization and has some instance methods you can call.
|
7
|
+
def setup
|
8
|
+
BaseKlass.class_variable_set(:@@connected, false)
|
9
|
+
end
|
10
|
+
|
11
|
+
# sanity check
|
12
|
+
def test_that_things_work_without_manana
|
13
|
+
@subklass = Class.new(BaseKlass)
|
14
|
+
|
15
|
+
assert_raises RuntimeError do
|
16
|
+
res = @subklass.find
|
17
|
+
end
|
18
|
+
|
19
|
+
BaseKlass.establish_connection
|
20
|
+
|
21
|
+
res = @subklass.find
|
22
|
+
refute_empty(res)
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_wrap
|
27
|
+
|
28
|
+
@subklass = Manana.wrap {
|
29
|
+
unless BaseKlass.connected?
|
30
|
+
BaseKlass.establish_connection
|
31
|
+
end
|
32
|
+
subklass = Class.new(BaseKlass)
|
33
|
+
}
|
34
|
+
|
35
|
+
res = @subklass.find
|
36
|
+
refute_empty(res)
|
37
|
+
assert(BaseKlass.connected?)
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
end
|
metadata
CHANGED
@@ -1,62 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.5.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- coldnebo
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-04-10 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: bundler
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
19
|
+
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
26
|
+
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rake
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: minitest
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
description: provides a simple way to defer initialization of an object until its
|
@@ -67,9 +60,9 @@ executables: []
|
|
67
60
|
extensions: []
|
68
61
|
extra_rdoc_files: []
|
69
62
|
files:
|
70
|
-
- .gitignore
|
71
|
-
- .travis.yml
|
72
|
-
- .yardopts
|
63
|
+
- ".gitignore"
|
64
|
+
- ".travis.yml"
|
65
|
+
- ".yardopts"
|
73
66
|
- Gemfile
|
74
67
|
- LICENSE.txt
|
75
68
|
- README.md
|
@@ -83,43 +76,40 @@ files:
|
|
83
76
|
- samples/exponential_backoff.rb
|
84
77
|
- samples/fast_startup.rb
|
85
78
|
- samples/self_healing.rb
|
79
|
+
- test/base_klass.rb
|
86
80
|
- test/klass.rb
|
87
81
|
- test/minitest_helper.rb
|
88
82
|
- test/test_manana.rb
|
83
|
+
- test/test_with_subclass.rb
|
89
84
|
homepage: https://github.com/coldnebo/manana
|
90
85
|
licenses:
|
91
86
|
- MIT
|
87
|
+
metadata: {}
|
92
88
|
post_install_message:
|
93
89
|
rdoc_options: []
|
94
90
|
require_paths:
|
95
91
|
- lib
|
96
92
|
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
93
|
requirements:
|
99
|
-
- -
|
94
|
+
- - ">="
|
100
95
|
- !ruby/object:Gem::Version
|
101
96
|
version: '0'
|
102
|
-
segments:
|
103
|
-
- 0
|
104
|
-
hash: -3306959934859244204
|
105
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
98
|
requirements:
|
108
|
-
- -
|
99
|
+
- - ">="
|
109
100
|
- !ruby/object:Gem::Version
|
110
101
|
version: '0'
|
111
|
-
segments:
|
112
|
-
- 0
|
113
|
-
hash: -3306959934859244204
|
114
102
|
requirements: []
|
115
103
|
rubyforge_project:
|
116
|
-
rubygems_version:
|
104
|
+
rubygems_version: 2.4.3
|
117
105
|
signing_key:
|
118
|
-
specification_version:
|
106
|
+
specification_version: 4
|
119
107
|
summary: provides a simple way to defer initialization of an object until its methods
|
120
108
|
are called
|
121
109
|
test_files:
|
110
|
+
- test/base_klass.rb
|
122
111
|
- test/klass.rb
|
123
112
|
- test/minitest_helper.rb
|
124
113
|
- test/test_manana.rb
|
114
|
+
- test/test_with_subclass.rb
|
125
115
|
has_rdoc:
|