liveresource 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.gitignore +1 -0
  2. data/BSDL +24 -0
  3. data/COPYING +59 -0
  4. data/GPL +339 -0
  5. data/README.md +289 -0
  6. data/Rakefile +47 -0
  7. data/benchmark/benchmark_helper.rb +19 -0
  8. data/benchmark/method_benchmark.rb +94 -0
  9. data/lib/live_resource.rb +66 -0
  10. data/lib/live_resource/attributes.rb +77 -0
  11. data/lib/live_resource/declarations.rb +200 -0
  12. data/lib/live_resource/finders.rb +43 -0
  13. data/lib/live_resource/log_helper.rb +24 -0
  14. data/lib/live_resource/methods.rb +41 -0
  15. data/lib/live_resource/methods/dispatcher.rb +176 -0
  16. data/lib/live_resource/methods/forward.rb +23 -0
  17. data/lib/live_resource/methods/future.rb +27 -0
  18. data/lib/live_resource/methods/method.rb +93 -0
  19. data/lib/live_resource/methods/token.rb +22 -0
  20. data/lib/live_resource/redis_client.rb +100 -0
  21. data/lib/live_resource/redis_client/attributes.rb +40 -0
  22. data/lib/live_resource/redis_client/methods.rb +194 -0
  23. data/lib/live_resource/redis_client/registration.rb +25 -0
  24. data/lib/live_resource/resource.rb +44 -0
  25. data/lib/live_resource/resource_proxy.rb +180 -0
  26. data/old/benchmark/attribute_benchmark.rb +58 -0
  27. data/old/benchmark/thread_benchmark.rb +89 -0
  28. data/old/examples/attribute.rb +22 -0
  29. data/old/examples/attribute_rmw.rb +30 -0
  30. data/old/examples/attribute_subscriber.rb +32 -0
  31. data/old/examples/method_provider_sleep.rb +22 -0
  32. data/old/examples/methods.rb +37 -0
  33. data/old/lib/live_resource/subscriber.rb +98 -0
  34. data/old/redis_test.rb +127 -0
  35. data/old/state_publisher_test.rb +139 -0
  36. data/old/test/attribute_modify_test.rb +52 -0
  37. data/old/test/attribute_options_test.rb +54 -0
  38. data/old/test/attribute_subscriber_test.rb +94 -0
  39. data/old/test/composite_resource_test.rb +61 -0
  40. data/old/test/method_sender_test.rb +41 -0
  41. data/old/test/redis_api_test.rb +185 -0
  42. data/old/test/simple_attribute_test.rb +75 -0
  43. data/test/attribute_test.rb +212 -0
  44. data/test/declarations_test.rb +119 -0
  45. data/test/logger_test.rb +44 -0
  46. data/test/method_call_test.rb +223 -0
  47. data/test/method_forward_continue_test.rb +83 -0
  48. data/test/method_params_test.rb +81 -0
  49. data/test/method_routing_test.rb +59 -0
  50. data/test/multiple_class_test.rb +47 -0
  51. data/test/new_api_DISABLED.rb +127 -0
  52. data/test/test_helper.rb +9 -0
  53. data/test/volume_create_DISABLED.rb +74 -0
  54. metadata +129 -0
@@ -0,0 +1,81 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ParamsTest < Test::Unit::TestCase
4
+ class ParamsClass
5
+ include LiveResource::Resource
6
+
7
+ remote_reader :name
8
+ remote_reader :age
9
+
10
+ resource_name :name
11
+ resource_class :params_class
12
+
13
+ def initialize(name, age)
14
+ remote_attribute_write(:name, name)
15
+ remote_attribute_write(:age, age)
16
+ end
17
+
18
+ def no_params_method
19
+ self.age
20
+ end
21
+
22
+ def fixed_params_method(arg1, arg2)
23
+ arg1 + arg2
24
+ end
25
+
26
+ def splat_params_method(*params)
27
+ params.length
28
+ end
29
+
30
+ def mixed_params_method(arg1, arg2, *params)
31
+ result = arg1 + arg2
32
+ params.each do |param|
33
+ result = result + param
34
+ end
35
+ result
36
+ end
37
+ end
38
+
39
+ def setup
40
+ Redis.new.flushall
41
+
42
+ LiveResource::RedisClient.logger.level = Logger::INFO
43
+
44
+ # Class resources
45
+ LiveResource::register ParamsClass
46
+
47
+ @test_class = LiveResource::find(:params_class)
48
+ @test_instance = @test_class.new("bob", 42)
49
+ end
50
+
51
+ def teardown
52
+ LiveResource::stop
53
+ end
54
+
55
+ def test_no_params_method
56
+ assert_equal 42, @test_instance.no_params_method
57
+ assert_raise(ArgumentError) { @test_instance.no_params_method("foo") }
58
+ end
59
+
60
+ def test_fixed_params_method
61
+ assert_equal 13, @test_instance.fixed_params_method(6, 7)
62
+ assert_raise(ArgumentError) { @test_instance.fixed_params_method }
63
+ assert_raise(ArgumentError) { @test_instance.fixed_params_method(6, 7, 8) }
64
+ end
65
+
66
+ def test_splat_params_method
67
+ assert_equal 0, @test_instance.splat_params_method
68
+ assert_equal 1, @test_instance.splat_params_method("foo")
69
+ assert_equal 2, @test_instance.splat_params_method("foo", "bar")
70
+ assert_equal 3, @test_instance.splat_params_method("foo", "bar", "baz")
71
+ end
72
+
73
+ def test_mixed_params_method
74
+ assert_equal 3, @test_instance.mixed_params_method(1, 2)
75
+ assert_equal 6, @test_instance.mixed_params_method(1, 2, 3)
76
+ assert_equal 10, @test_instance.mixed_params_method(1, 2, 3, 4)
77
+
78
+ assert_raise(ArgumentError) { @test_instance.mixed_params_method }
79
+ assert_raise(ArgumentError) { @test_instance.mixed_params_method(1) }
80
+ end
81
+ end
@@ -0,0 +1,59 @@
1
+ require_relative 'test_helper'
2
+
3
+ class MethodRoutingTest < Test::Unit::TestCase
4
+ class Class1
5
+ include LiveResource::Resource
6
+
7
+ resource_class :class_1
8
+ resource_name :object_id
9
+
10
+ def method1
11
+ [1]
12
+ end
13
+ end
14
+
15
+ class Class2
16
+ include LiveResource::Resource
17
+
18
+ resource_class :class_2
19
+ resource_name :object_id
20
+
21
+ def method2(i)
22
+ [i, 2]
23
+ end
24
+ end
25
+
26
+ class Class3
27
+ include LiveResource::Resource
28
+
29
+ resource_class :class_3
30
+ resource_name :object_id
31
+
32
+ def method3(i, j)
33
+ [i, j, 3]
34
+ end
35
+ end
36
+
37
+ def setup
38
+ Redis.new.flushall
39
+ Class1.new
40
+ Class2.new
41
+ Class3.new
42
+ end
43
+
44
+ def teardown
45
+ LiveResource::stop
46
+ end
47
+
48
+ def test_create_method
49
+ m = LiveResource::RemoteMethod.new(:method => :method1)
50
+ c1 = LiveResource::any(:class_1)
51
+ c2 = LiveResource::any(:class_2)
52
+ c3 = LiveResource::any(:class_3)
53
+
54
+ m.add_destination(c2, :method2, [])
55
+ m.add_destination(c3, :method3, [])
56
+
57
+ assert_equal [1, 2, 3], c1.wait_for_done(c1.remote_send(m))
58
+ end
59
+ end
@@ -0,0 +1,47 @@
1
+ require_relative 'test_helper'
2
+
3
+ class ClassMethodTest < Test::Unit::TestCase
4
+ class Class1
5
+ include LiveResource::Resource
6
+
7
+ resource_class :class_1
8
+ resource_name :object_id
9
+
10
+ def self.class_method_1
11
+ "42"
12
+ end
13
+ end
14
+
15
+ class Class2
16
+ include LiveResource::Resource
17
+
18
+ resource_class :class_2
19
+ resource_name :object_id
20
+
21
+ def self.class_method_2
22
+ "foo"
23
+ end
24
+ end
25
+
26
+ def setup
27
+ Redis.new.flushall
28
+
29
+ LiveResource::register Class1
30
+ LiveResource::register Class2
31
+ end
32
+
33
+ def teardown
34
+ LiveResource::stop
35
+ end
36
+
37
+ def test_classes_dont_conflict
38
+ c1 = LiveResource::find(:class_1)
39
+ c2 = LiveResource::find(:class_2)
40
+
41
+ assert_equal true, c1.respond_to?(:class_method_1)
42
+ assert_equal false, c1.respond_to?(:class_method_2)
43
+
44
+ assert_equal true, c2.respond_to?(:class_method_2)
45
+ assert_equal false, c2.respond_to?(:class_method_1)
46
+ end
47
+ end
@@ -0,0 +1,127 @@
1
+ require_relative 'test_helper'
2
+
3
+ class VolumeResource
4
+ include LiveResource::Resource
5
+
6
+ # Class type: "volume-class"
7
+ # Class instance name: "volume-class.{hostname}.{pid}"
8
+ # Instance type: "volume"
9
+ # Instance name: "volume.my_volume_name"
10
+ resource_type :volume
11
+ resource_name "<%= self.name %>"
12
+
13
+ # Attribute and method declarations stay the same.
14
+ remote_attribute :name, :online
15
+ remote_method :start, :stop
16
+
17
+ # LR will always provide class-namespace methods like all() and
18
+ # find(&block), implemented on the client side. If any class
19
+ # methods are provided, then we'll also start a class-level method
20
+ # dispatcher.
21
+ remote_class_method :create_volume
22
+
23
+ def initialize(name)
24
+ @name = name
25
+ @online = false
26
+
27
+ LiveResource::Worker::register(self)
28
+ end
29
+
30
+ def start
31
+ unless @online
32
+ info "starting"
33
+ @online = true
34
+ end
35
+
36
+ @online
37
+ end
38
+
39
+ def stop
40
+ if @online
41
+ info "stopping"
42
+ @online = false
43
+ end
44
+
45
+ @online
46
+ end
47
+
48
+ def self.create_volume(name)
49
+ info "creating new volume #{name}"
50
+ VolumeResource.new(name)
51
+ end
52
+ end
53
+
54
+ class ModuleTest < Test::Unit::TestCase
55
+ def setup
56
+ Redis.new.flushall
57
+
58
+ LiveResource::Worker::register_class(VolumeResource)
59
+
60
+ # Run method dispatchers in separate threads; use LR::run to
61
+ # block while they run (e.g., for a dedicated worker process).
62
+ # Each instance will still have its own thread regardless.
63
+ LiveResource::Worker::start
64
+ end
65
+
66
+ def teardown
67
+ # Stop and join method dispatchers
68
+ LiveResource::Worker::stop
69
+ end
70
+
71
+ def test_foo
72
+ # Resource finders:
73
+ # LiveResource::all(type) -> [array]
74
+ # LiveResource::find(type) -> class resource
75
+ # LiveResource::find(t,name) -> resource matching name
76
+ # LiveResource::find(t,&block) -> resource matching condition
77
+ # LiveResource::first(type) -> first resource
78
+ # LiveResource::any(type) -> picks one randomly
79
+
80
+ # Find on type alone gives the class resource.
81
+ vc = LiveResource::find(:volume)
82
+
83
+ # Sync class-level method call
84
+ vc.create_volume "foo"
85
+
86
+ # Async class-level call with future
87
+ done = vc.create_volume!?("bar")
88
+
89
+ # Wait for complete
90
+ done.value
91
+
92
+ # Find by resource type and name, in this case name is the same
93
+ # as volume name. (See resource_name declaration above.)
94
+ v1 = LiveResource::find(:volume, "foo")
95
+
96
+ # Find by resource matching type and block.
97
+ v2 = LiveResource::find(:volume) { |v| v.name == "bar" }
98
+
99
+ # Attribute read: only consults Redis
100
+ assert_equal false, v1.online
101
+
102
+ # Syncronous method call, blocks until complete
103
+ assert_equal true, v1.start
104
+ assert_equal true, v1.online
105
+
106
+ # Async method call
107
+ v2.start!
108
+ 10.times { Thread.pass }
109
+ assert_equal true, v2.online
110
+
111
+ # Async method with future
112
+ done = []
113
+
114
+ # Note: each applies to instances, excluding the class instance.
115
+ LiveResource::each(:volume) { |v| done << v.stop!? }
116
+
117
+ begin
118
+ done.each { |d| d.value }
119
+ rescue e
120
+ # Log error and continue waiting for others to complete.
121
+ nil
122
+ end
123
+
124
+ ## TODO: wrap the above construct in one method that takes one
125
+ # block for the action, another for completion action.
126
+ end
127
+ end
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'thread'
4
+ require 'mocha'
5
+ require 'pp'
6
+
7
+ require_relative '../lib/live_resource'
8
+
9
+ Thread.abort_on_exception = true
@@ -0,0 +1,74 @@
1
+ require_relative 'test_helper'
2
+
3
+ class VolumeResource
4
+ include LiveResource::Resource
5
+
6
+ resource_type :volume
7
+ resource_name "<%= self.name %>"
8
+
9
+ remote_attribute :name, :status
10
+ remote_method :start, :stop
11
+
12
+ # Internal-only volume create methods
13
+ remote_method :stage1_create_gluster_config
14
+ remote_method :stage2_create_gluster_config_done
15
+
16
+ # TODO:
17
+ # Implicit in declaring remote_class_method :new
18
+ # class << self
19
+ # alias_method object_new new
20
+ # end
21
+ #
22
+ remote_class_method :new
23
+
24
+ def initialize(name)
25
+ @name = name
26
+
27
+ LiveResource::Worker::register(self)
28
+ end
29
+
30
+ def self.new(name)
31
+ info "creating new volume #{name}"
32
+ v = VolumeResource.object_new(name)
33
+
34
+ v.status = :creating
35
+ v.stage1_create_gluster_config!
36
+ end
37
+
38
+ def stage1_create_gluster_config
39
+ params = { } # stuff here that Gluster needs
40
+
41
+ # This builds up a state object that's returned to the method dispatcher.
42
+ # - Instead of reply, this is a forward
43
+ # - It goes to a :gluster instance
44
+ # - The new method and params are wrapped up in same way as a new method call
45
+ # - There's a hidden parameter which specifies the continuation method
46
+ LiveResource::any(:gluster).forward(:create_config, self).continue_to(:stage2_create_gluster_config_done)
47
+ end
48
+
49
+ # Return values from remote methods:
50
+ # - Explicit reply
51
+ # - Forward to another actor
52
+ # - Something else, that gets treated as a reply
53
+ #
54
+ # Method dispatcher may already have state for continuing to another method.
55
+
56
+ def stage2_create_gluster_config_done
57
+ @status = :stopped
58
+ end
59
+ end
60
+
61
+ class GlusterResource
62
+ include LiveResource::Resource
63
+
64
+ resource_type :gluster
65
+ resource_name "<%= self.hostname %>"
66
+
67
+ remote_method :create_config
68
+
69
+ def create_config(volume)
70
+ # do gluster stuff here to set up volume
71
+
72
+ nil # No params necessary
73
+ end
74
+ end
metadata ADDED
@@ -0,0 +1,129 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: liveresource
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Spectra Logic
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: redis
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: yard
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Remote-callable attributes and methods for IPC and cluster use.
47
+ email: public@joshcarter.com
48
+ executables: []
49
+ extensions: []
50
+ extra_rdoc_files: []
51
+ files:
52
+ - .gitignore
53
+ - BSDL
54
+ - COPYING
55
+ - GPL
56
+ - README.md
57
+ - Rakefile
58
+ - benchmark/benchmark_helper.rb
59
+ - benchmark/method_benchmark.rb
60
+ - lib/live_resource.rb
61
+ - lib/live_resource/attributes.rb
62
+ - lib/live_resource/declarations.rb
63
+ - lib/live_resource/finders.rb
64
+ - lib/live_resource/log_helper.rb
65
+ - lib/live_resource/methods.rb
66
+ - lib/live_resource/methods/dispatcher.rb
67
+ - lib/live_resource/methods/forward.rb
68
+ - lib/live_resource/methods/future.rb
69
+ - lib/live_resource/methods/method.rb
70
+ - lib/live_resource/methods/token.rb
71
+ - lib/live_resource/redis_client.rb
72
+ - lib/live_resource/redis_client/attributes.rb
73
+ - lib/live_resource/redis_client/methods.rb
74
+ - lib/live_resource/redis_client/registration.rb
75
+ - lib/live_resource/resource.rb
76
+ - lib/live_resource/resource_proxy.rb
77
+ - old/benchmark/attribute_benchmark.rb
78
+ - old/benchmark/thread_benchmark.rb
79
+ - old/examples/attribute.rb
80
+ - old/examples/attribute_rmw.rb
81
+ - old/examples/attribute_subscriber.rb
82
+ - old/examples/method_provider_sleep.rb
83
+ - old/examples/methods.rb
84
+ - old/lib/live_resource/subscriber.rb
85
+ - old/redis_test.rb
86
+ - old/state_publisher_test.rb
87
+ - old/test/attribute_modify_test.rb
88
+ - old/test/attribute_options_test.rb
89
+ - old/test/attribute_subscriber_test.rb
90
+ - old/test/composite_resource_test.rb
91
+ - old/test/method_sender_test.rb
92
+ - old/test/redis_api_test.rb
93
+ - old/test/simple_attribute_test.rb
94
+ - test/attribute_test.rb
95
+ - test/declarations_test.rb
96
+ - test/logger_test.rb
97
+ - test/method_call_test.rb
98
+ - test/method_forward_continue_test.rb
99
+ - test/method_params_test.rb
100
+ - test/method_routing_test.rb
101
+ - test/multiple_class_test.rb
102
+ - test/new_api_DISABLED.rb
103
+ - test/test_helper.rb
104
+ - test/volume_create_DISABLED.rb
105
+ homepage: https://github.com/joshcarter/liveresource
106
+ licenses: []
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 1.8.24
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: Live Resource
129
+ test_files: []