liveresource 2.0.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 (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: []