RingyDingy 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGES ADDED
@@ -0,0 +1,4 @@
1
+ = 1.0.0
2
+
3
+ Birthday!
4
+
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright 2006, Eric Hodel. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ 2. Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+ 3. Neither the names of the authors nor the names of their contributors
13
+ may be used to endorse or promote products derived from this software
14
+ without specific prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
17
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
20
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
21
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
22
+ OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23
+ BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25
+ OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26
+ EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/Manifest.txt ADDED
@@ -0,0 +1,7 @@
1
+ CHANGES
2
+ LICENSE
3
+ Manifest.txt
4
+ README
5
+ Rakefile
6
+ lib/ringy_dingy.rb
7
+ test/test_ringy_dingy.rb
data/README ADDED
@@ -0,0 +1,38 @@
1
+ = RingyDingy
2
+
3
+ RingyDingy is a little boat that keeps your DRb service afloat!
4
+
5
+ Rubyforge Project:
6
+
7
+ http://rubyforge.org/projects/seattlerb
8
+
9
+ Documentation:
10
+
11
+ ri RingyDingy
12
+
13
+ == About
14
+
15
+ RingyDingy automatically registers a service with a RingServer. If
16
+ communication between the RingServer and the RingyDingy is lost, RingyDingy
17
+ will re-register its service with the RingServer when it reappears.
18
+
19
+ Similarly, the RingServer will automatically drop registrations by a RingyDingy
20
+ that it can't communicate with after a short timeout.
21
+
22
+ == Installing RingyDingy
23
+
24
+ Just install the gem:
25
+
26
+ $ sudo gem install RingyDingy
27
+
28
+ == Using RingyDingy
29
+
30
+ require 'rubygems'
31
+ require 'ringy_dingy'
32
+ require 'my_drb_service'
33
+
34
+ my_drb_service = MyDRbService.new
35
+
36
+ RingyDingy.new(my_drb_service).run
37
+
38
+ DRb.thread.join
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/gempackagetask'
6
+
7
+ $VERBOSE = nil
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = 'RingyDingy'
11
+ s.version = '1.0.0'
12
+ s.summary = 'RingyDingy is a little boat that keeps your DRb service afloat!'
13
+ s.description = 'RingyDingy automatically re-registers your DRb service with a RingServer should communication with the RingServer stop.'
14
+ s.author = 'Eric Hodel'
15
+ s.email = 'drbrain@segment7.net'
16
+
17
+ s.has_rdoc = true
18
+ s.files = File.read('Manifest.txt').split($/)
19
+ s.require_path = 'lib'
20
+ end
21
+
22
+ desc 'Run tests'
23
+ task :default => [ :test ]
24
+
25
+ Rake::TestTask.new('test') do |t|
26
+ t.libs << 'test'
27
+ t.pattern = 'test/test_*.rb'
28
+ t.verbose = true
29
+ end
30
+
31
+ desc 'Update Manifest.txt'
32
+ task :update_manifest do
33
+ sh "find . -type f | sed -e 's%./%%' | egrep -v 'svn|swp|~' | egrep -v '^(doc|pkg)/' | sort > Manifest.txt"
34
+ end
35
+
36
+ desc 'Generate RDoc'
37
+ Rake::RDocTask.new :rdoc do |rd|
38
+ rd.rdoc_dir = 'doc'
39
+ rd.rdoc_files.add 'lib', 'README', 'LICENSE', 'CHANGES'
40
+ rd.main = 'README'
41
+ rd.options << '-d' if `which dot` =~ /\/dot/
42
+ rd.options << '-t RingyDingy Documentation'
43
+ end
44
+
45
+ desc 'Build Gem'
46
+ Rake::GemPackageTask.new spec do |pkg|
47
+ pkg.need_tar = true
48
+ end
49
+
50
+ desc 'Clean up'
51
+ task :clean => [ :clobber_rdoc, :clobber_package ]
52
+
53
+ desc 'Clean up'
54
+ task :clobber => [ :clean ]
55
+
56
+ # vim: syntax=Ruby
@@ -0,0 +1,120 @@
1
+ require 'English'
2
+ require 'drb'
3
+ require 'rinda/ring'
4
+
5
+ ##
6
+ # RingyDingy registers a DRb service with a Rinda::RingServer and re-registers
7
+ # the service if communication with the Rinda::RingServer is ever lost.
8
+ #
9
+ # Similarly, if the Rinda::RingServer should ever lose contact with the
10
+ # service the registration will be automatically dropped after a short
11
+ # timeout.
12
+ #
13
+ # = Example
14
+ #
15
+ # my_service = MyService.new
16
+ # rd = RingyDingy.new my_service, :MyService
17
+ # rd.run
18
+ # DRb.thread.join
19
+
20
+ class RingyDingy
21
+
22
+ ##
23
+ # Interval to check the RingServer for our registration information.
24
+
25
+ attr_accessor :check_every
26
+
27
+ ##
28
+ # RingyDingy service identifier. Use this to distinguish between
29
+ # RingyDingys registering the same service.
30
+
31
+ attr_reader :identifier
32
+
33
+ ##
34
+ # RingyDingy run loop thread.
35
+
36
+ attr_reader :thread
37
+
38
+ if $TESTING then
39
+ attr_accessor :ring_finger, :renewer, :thread # :nodoc:
40
+ attr_writer :ring_server # :nodoc:
41
+ end
42
+
43
+ ##
44
+ # Creates a new RingyDingy that registers +object+ as +service+ with
45
+ # optional identifier +name+.
46
+
47
+ def initialize(object, service = :RingyDingy, name = nil)
48
+ DRb.start_service
49
+
50
+ @identifier = [Socket.gethostname.downcase, $PID, name].compact.join '_'
51
+ @object = object
52
+ @service = service || :RingyDingy
53
+
54
+ @check_every = 180
55
+ @renewer = Rinda::SimpleRenewer.new
56
+
57
+ @ring_finger = Rinda::RingFinger.new
58
+ @ring_server = nil
59
+
60
+ @thread = nil
61
+ end
62
+
63
+ ##
64
+ # Registers this service with the primary Rinda::RingServer.
65
+
66
+ def register
67
+ ring_server.write [:name, @service, DRbObject.new(@object), @identifier],
68
+ @renewer
69
+ return nil
70
+ end
71
+
72
+ ##
73
+ # Looks for a registration tuple in the primary Rinda::RingServer. If a
74
+ # RingServer can't be found or contacted, returns false.
75
+
76
+ def registered?
77
+ registrations = ring_server.read_all [:name, :RingyDingy, nil, @identifier]
78
+ registrations.any? { |registration| registration[2] == @object }
79
+ rescue DRb::DRbConnError
80
+ @ring_server = nil
81
+ return false
82
+ end
83
+
84
+ ##
85
+ # Looks up the primary Rinde::RingServer.
86
+
87
+ def ring_server
88
+ return @ring_server unless @ring_server.nil?
89
+ @ring_server = @ring_finger.lookup_ring_any
90
+ end
91
+
92
+ ##
93
+ # Starts a thread that checks for a registration tuple every #check_every
94
+ # seconds.
95
+
96
+ def run
97
+ @thread = Thread.start do
98
+ loop do
99
+ begin
100
+ register unless registered?
101
+ rescue DRb::DRbConnError
102
+ @ring_server = nil
103
+ rescue RuntimeError => e
104
+ raise unless e.message == 'RingNotFound'
105
+ end
106
+ sleep @check_every
107
+ end
108
+ end
109
+ end
110
+
111
+ ##
112
+ # Stops checking for registration tuples.
113
+
114
+ def stop
115
+ @thread.kill
116
+ return nil
117
+ end
118
+
119
+ end
120
+
@@ -0,0 +1,156 @@
1
+ require 'test/unit'
2
+
3
+ $TESTING = true
4
+
5
+ require 'ringy_dingy'
6
+
7
+ class StubRingFinger
8
+
9
+ attr_accessor :ring_server
10
+
11
+ def initialize
12
+ @ring_server = nil
13
+ end
14
+
15
+ def lookup_ring_any
16
+ raise RuntimeError, 'RingNotFound' if @ring_server.nil?
17
+ @ring_server
18
+ end
19
+
20
+ end
21
+
22
+ class StubRingServer
23
+
24
+ attr_accessor :tuples
25
+
26
+ def initialize
27
+ @tuples = []
28
+ end
29
+
30
+ def write(*args)
31
+ @tuples << args
32
+ end
33
+
34
+ def read_all(*args)
35
+ @tuples.map { |t,r| t }
36
+ end
37
+
38
+ end
39
+
40
+ class Rinda::SimpleRenewer
41
+
42
+ attr_reader :sec
43
+
44
+ def ==(other)
45
+ self.class === other and sec == other.sec
46
+ end
47
+
48
+ end
49
+
50
+ class TestRingyDingy < Test::Unit::TestCase
51
+
52
+ def setup
53
+ @identifier = "#{Socket.gethostname.downcase}_#{$PID}"
54
+ @object = ""
55
+ @ringy_dingy = RingyDingy.new @object
56
+
57
+ @stub_ring_server = StubRingServer.new
58
+ @ringy_dingy.ring_server = @stub_ring_server
59
+ end
60
+
61
+ def test_identifier
62
+ assert_equal @identifier, @ringy_dingy.identifier
63
+
64
+ @ringy_dingy = RingyDingy.new @object, nil, 'blah'
65
+
66
+ assert_equal "#{@identifier}_blah", @ringy_dingy.identifier
67
+ end
68
+
69
+ def test_register
70
+ @ringy_dingy.register
71
+
72
+ expected = [
73
+ [[:name, :RingyDingy, DRbObject.new(@object), @identifier],
74
+ Rinda::SimpleRenewer.new]
75
+ ]
76
+
77
+ assert_equal expected, @stub_ring_server.tuples
78
+ end
79
+
80
+ def test_register_service
81
+ @ringy_dingy = RingyDingy.new @object, :MyDRbService
82
+ @ringy_dingy.ring_server = @stub_ring_server
83
+ @ringy_dingy.register
84
+
85
+ expected = [
86
+ [[:name, :MyDRbService, DRbObject.new(@object), @identifier],
87
+ Rinda::SimpleRenewer.new]
88
+ ]
89
+
90
+ assert_equal expected, @stub_ring_server.tuples
91
+ end
92
+
93
+ def test_registered_eh
94
+ @stub_ring_server.tuples << [
95
+ [:name, :RingyDingy, @object, @identifier], nil]
96
+
97
+ assert_equal true, @ringy_dingy.registered?
98
+ end
99
+
100
+ def test_registered_eh_not_registered
101
+ assert_equal false, @ringy_dingy.registered?
102
+ end
103
+
104
+ def test_registered_eh_no_ring_server
105
+ def @stub_ring_server.read_all(*args)
106
+ raise DRb::DRbConnError
107
+ end
108
+
109
+ assert_equal false, @ringy_dingy.registered?
110
+
111
+ assert_equal nil, @ringy_dingy.instance_variable_get(:@ring_server)
112
+ end
113
+
114
+ def test_registered_eh_service
115
+ @ringy_dingy = RingyDingy.new @object, :MyDRbService
116
+ @ringy_dingy.ring_server = @stub_ring_server
117
+
118
+ @stub_ring_server.tuples << [
119
+ [:name, :MyDRbService, @object, @identifier], nil]
120
+
121
+ assert_equal true, @ringy_dingy.registered?
122
+ end
123
+
124
+ def test_renewer
125
+ assert_equal Rinda::SimpleRenewer.new, @ringy_dingy.renewer
126
+ end
127
+
128
+ def test_ring_server
129
+ util_create_stub_ring_finger :server
130
+
131
+ assert_equal :server, @ringy_dingy.ring_server
132
+ end
133
+
134
+ def test_ring_server_not_found
135
+ util_create_stub_ring_finger
136
+
137
+ assert_raise RuntimeError do @ringy_dingy.ring_server end
138
+ end
139
+
140
+ def test_stop
141
+ @ringy_dingy.thread = Thread.start do sleep end
142
+ assert_equal nil, @ringy_dingy.stop
143
+ end
144
+
145
+ def util_create_stub_ring_finger(rs = nil)
146
+ @ringy_dingy.ring_server = nil
147
+
148
+ ring_finger = StubRingFinger.new
149
+
150
+ ring_finger.ring_server = rs unless rs.nil?
151
+
152
+ @ringy_dingy.ring_finger = ring_finger
153
+ end
154
+
155
+ end
156
+
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.99
3
+ specification_version: 1
4
+ name: RingyDingy
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.0.0
7
+ date: 2006-09-09 00:00:00 -07:00
8
+ summary: RingyDingy is a little boat that keeps your DRb service afloat!
9
+ require_paths:
10
+ - lib
11
+ email: drbrain@segment7.net
12
+ homepage:
13
+ rubyforge_project:
14
+ description: RingyDingy automatically re-registers your DRb service with a RingServer should communication with the RingServer stop.
15
+ autorequire:
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Eric Hodel
31
+ files:
32
+ - CHANGES
33
+ - LICENSE
34
+ - Manifest.txt
35
+ - README
36
+ - Rakefile
37
+ - lib/ringy_dingy.rb
38
+ - test/test_ringy_dingy.rb
39
+ test_files: []
40
+
41
+ rdoc_options: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ executables: []
46
+
47
+ extensions: []
48
+
49
+ requirements: []
50
+
51
+ dependencies: []
52
+