dcell 0.16.0 → 0.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -1
- data/.travis.yml +13 -2
- data/CHANGES.md +4 -0
- data/Gemfile +5 -4
- data/README.md +0 -1
- data/dcell.gemspec +5 -4
- data/examples/itchy.rb +4 -3
- data/examples/scratchy.rb +3 -3
- data/lib/dcell.rb +19 -6
- data/lib/dcell/actor_proxy.rb +3 -2
- data/lib/dcell/celluloid_ext.rb +5 -4
- data/lib/dcell/directory.rb +8 -0
- data/lib/dcell/explorer.rb +1 -1
- data/lib/dcell/node.rb +11 -1
- data/lib/dcell/node_manager.rb +30 -0
- data/lib/dcell/registries/cassandra_adapter.rb +13 -5
- data/lib/dcell/registries/mongodb_adapter.rb +85 -0
- data/lib/dcell/registries/redis_adapter.rb +13 -5
- data/lib/dcell/registries/zk_adapter.rb +40 -4
- data/lib/dcell/server.rb +4 -2
- data/lib/dcell/version.rb +1 -1
- data/spec/dcell/actor_proxy_spec.rb +3 -3
- data/spec/dcell/celluloid_ext_spec.rb +1 -1
- data/spec/dcell/directory_spec.rb +15 -1
- data/spec/dcell/explorer_spec.rb +1 -1
- data/spec/dcell/global_spec.rb +1 -1
- data/spec/dcell/node_spec.rb +2 -2
- data/spec/dcell/registries/mongodb_adapter_spec.rb +7 -0
- data/spec/dcell/registries/redis_adapter_spec.rb +3 -3
- data/spec/dcell/registries/zk_adapter_spec.rb +24 -3
- data/spec/options/01-options.rb +10 -0
- data/spec/options/02-registry.rb +13 -0
- data/spec/spec_helper.rb +9 -2
- data/spec/support/helpers.rb +1 -3
- data/spec/support/registry_examples.rb +1 -1
- data/spec/test_node.rb +6 -2
- metadata +35 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b7abd2458deb859bd4f406ee25e70e2a2acefb1
|
4
|
+
data.tar.gz: 37da6fd6c1177b19898b048eade8700fd965cd25
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a37879c2a2962fcf4dbcb6b424357b1686e4689a4cefcb6627936d08c66ac998ccc0faac64d1c54d5eb26b3df8de7656fa5991677c7f9ad87493e2433b9a139b
|
7
|
+
data.tar.gz: 9566d8144677141bc87a371f3f8ba70641b78538e804ed79f3481417dd04e5b06aea6124980227e913789925ae5f5ea821258fd24dd25dfc5e2377f3bf5e2db9
|
data/.rspec
CHANGED
data/.travis.yml
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
+
language: ruby
|
2
|
+
|
1
3
|
before_install: sudo apt-get install libzmq3-dev
|
2
4
|
|
5
|
+
services:
|
6
|
+
- mongodb
|
7
|
+
- redis-server
|
8
|
+
|
3
9
|
rvm:
|
4
10
|
- 1.9.3
|
5
11
|
- 2.0.0
|
@@ -15,5 +21,10 @@ matrix:
|
|
15
21
|
- rvm: jruby-19mode
|
16
22
|
- rvm: rbx-19mode # rbx seems to be losing exception messages o_O
|
17
23
|
|
18
|
-
|
19
|
-
|
24
|
+
branches:
|
25
|
+
only:
|
26
|
+
- master
|
27
|
+
|
28
|
+
env:
|
29
|
+
- DCELL_TEST_ADAPTER=redis
|
30
|
+
- DCELL_TEST_ADAPTER=mongodb
|
data/CHANGES.md
CHANGED
data/Gemfile
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
|
3
|
-
gem 'celluloid', github: 'celluloid/celluloid',
|
4
|
-
gem 'celluloid-io', github: 'celluloid/celluloid-io',
|
5
|
-
gem 'celluloid-zmq', github: 'celluloid/celluloid-zmq',
|
3
|
+
gem 'celluloid', github: 'celluloid/celluloid', tag: 'v0.16.0'
|
4
|
+
gem 'celluloid-io', github: 'celluloid/celluloid-io', tag: 'v0.16.1'
|
5
|
+
gem 'celluloid-zmq', github: 'celluloid/celluloid-zmq', tag: 'v0.16.0'
|
6
6
|
gem 'celluloid-redis', github: 'celluloid/celluloid-redis', branch: 'master'
|
7
|
-
gem 'reel', github: 'celluloid/reel',
|
7
|
+
gem 'reel', github: 'celluloid/reel', tag: 'v0.4.0'
|
8
8
|
|
9
9
|
#gem 'ffi-rzmq', github: 'chuckremes/ffi-rzmq'
|
10
10
|
|
@@ -15,3 +15,4 @@ gem 'coveralls', require: false
|
|
15
15
|
gemspec
|
16
16
|
|
17
17
|
gem 'zk'
|
18
|
+
gem 'mongoid'
|
data/README.md
CHANGED
@@ -2,7 +2,6 @@
|
|
2
2
|
=====
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/dcell.png)](http://rubygems.org/gems/dcell)
|
4
4
|
[![Build Status](https://secure.travis-ci.org/celluloid/dcell.png?branch=master)](http://travis-ci.org/celluloid/dcell)
|
5
|
-
[![Dependency Status](https://gemnasium.com/celluloid/dcell.png)](https://gemnasium.com/celluloid/dcell)
|
6
5
|
[![Code Climate](https://codeclimate.com/github/celluloid/dcell.png)](https://codeclimate.com/github/celluloid/dcell)
|
7
6
|
[![Coverage Status](https://coveralls.io/repos/celluloid/dcell/badge.png?branch=master)](https://coveralls.io/r/celluloid/dcell)
|
8
7
|
|
data/dcell.gemspec
CHANGED
@@ -17,12 +17,13 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
-
gem.add_runtime_dependency "celluloid", "
|
21
|
-
gem.add_runtime_dependency "celluloid-zmq", "
|
22
|
-
gem.add_runtime_dependency "reel"
|
20
|
+
gem.add_runtime_dependency "celluloid", "~> 0.16.0"
|
21
|
+
gem.add_runtime_dependency "celluloid-zmq", "~> 0.16.0"
|
22
|
+
gem.add_runtime_dependency "reel", "~> 0.4.0"
|
23
|
+
gem.add_runtime_dependency "http", "~> 0.5.0"
|
23
24
|
gem.add_runtime_dependency "celluloid-redis"
|
24
25
|
gem.add_runtime_dependency "redis-namespace"
|
25
26
|
|
26
27
|
gem.add_development_dependency "rake"
|
27
|
-
gem.add_development_dependency "rspec"
|
28
|
+
gem.add_development_dependency "rspec", "~> 2.14.0"
|
28
29
|
end
|
data/examples/itchy.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'dcell'
|
3
3
|
|
4
|
-
DCell.start :id => "itchy"
|
4
|
+
DCell.start :id => "itchy"
|
5
5
|
|
6
6
|
class Itchy
|
7
7
|
include Celluloid
|
@@ -12,12 +12,13 @@ class Itchy
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def fight
|
15
|
-
@n
|
16
|
-
if @n
|
15
|
+
@n += 1
|
16
|
+
if @n % 6 == 0
|
17
17
|
puts "Bite!"
|
18
18
|
else
|
19
19
|
puts "Fight!"
|
20
20
|
end
|
21
|
+
@n
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
data/examples/scratchy.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'dcell'
|
3
3
|
|
4
|
-
DCell.start
|
4
|
+
DCell.start
|
5
5
|
itchy_node = DCell::Node["itchy"]
|
6
6
|
|
7
7
|
puts "Fighting itchy! (check itchy's output)"
|
8
8
|
|
9
|
-
|
10
|
-
itchy_node[:itchy].fight
|
9
|
+
300.times do
|
10
|
+
puts itchy_node[:itchy].fight
|
11
11
|
sleep 1
|
12
12
|
end
|
data/lib/dcell.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'celluloid'
|
2
2
|
require 'reel'
|
3
3
|
require 'celluloid/zmq'
|
4
|
+
require 'socket'
|
5
|
+
require 'securerandom'
|
4
6
|
|
5
7
|
Celluloid::ZMQ.init
|
6
8
|
|
@@ -27,7 +29,6 @@ require 'dcell/celluloid_ext'
|
|
27
29
|
module DCell
|
28
30
|
class NotConfiguredError < RuntimeError; end # Not configured yet
|
29
31
|
|
30
|
-
DEFAULT_PORT = 7777 # Default DCell port
|
31
32
|
@config_lock = Mutex.new
|
32
33
|
|
33
34
|
class << self
|
@@ -45,11 +46,11 @@ module DCell
|
|
45
46
|
@config_lock.synchronize do
|
46
47
|
@configuration = {
|
47
48
|
'id' => generate_node_id,
|
48
|
-
'addr' => "tcp://127.0.0.1
|
49
|
+
'addr' => "tcp://127.0.0.1:*",
|
49
50
|
'registry' => {'adapter' => 'redis', 'server' => 'localhost'}
|
50
51
|
}.merge(options)
|
51
52
|
|
52
|
-
@me = Node.new @configuration['id'],
|
53
|
+
@me = Node.new @configuration['id'], nil
|
53
54
|
|
54
55
|
registry_adapter = @configuration['registry'][:adapter] || @configuration['registry']['adapter']
|
55
56
|
raise ArgumentError, "no registry adapter given in config" unless registry_adapter
|
@@ -64,8 +65,7 @@ module DCell
|
|
64
65
|
|
65
66
|
@registry = registry_class.new(@configuration['registry'])
|
66
67
|
|
67
|
-
|
68
|
-
DCell::Directory.set @configuration['id'], addr
|
68
|
+
ObjectSpace.define_finalizer(me, proc {Directory.remove @configuration['id']})
|
69
69
|
end
|
70
70
|
|
71
71
|
me
|
@@ -81,9 +81,22 @@ module DCell
|
|
81
81
|
def addr; @configuration['addr']; end
|
82
82
|
alias_method :address, :addr
|
83
83
|
|
84
|
+
def addr=(addr)
|
85
|
+
@configuration['addr'] = addr
|
86
|
+
@me.update_server_address addr
|
87
|
+
end
|
88
|
+
alias_method :address=, :addr=
|
89
|
+
|
84
90
|
# Attempt to generate a unique node ID for this machine
|
85
91
|
def generate_node_id
|
86
|
-
|
92
|
+
# a little bit more creative
|
93
|
+
if @registry.respond_to? :unique
|
94
|
+
@registry.unique
|
95
|
+
else
|
96
|
+
digest = Digest::SHA512.new
|
97
|
+
seed = Socket.gethostname + rand.to_s + Time.now.to_s + SecureRandom.hex
|
98
|
+
digest.update(seed).to_s
|
99
|
+
end
|
87
100
|
end
|
88
101
|
|
89
102
|
# Run the DCell application
|
data/lib/dcell/actor_proxy.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module DCell
|
2
2
|
# Proxy object for actors that live on remote nodes
|
3
|
-
class
|
3
|
+
class CellProxy < Celluloid::CellProxy; end
|
4
4
|
|
5
5
|
class ThreadHandleProxy
|
6
6
|
def kill
|
@@ -23,7 +23,8 @@ module DCell
|
|
23
23
|
@mailbox = mailbox
|
24
24
|
@thread = ThreadHandleProxy.new
|
25
25
|
@subject = SubjectProxy.new
|
26
|
+
@proxy = Celluloid::ActorProxy.new(@thread, @mailbox)
|
26
27
|
end
|
27
|
-
attr_reader :mailbox, :thread, :subject
|
28
|
+
attr_reader :mailbox, :thread, :subject, :proxy
|
28
29
|
end
|
29
30
|
end
|
data/lib/dcell/celluloid_ext.rb
CHANGED
@@ -9,7 +9,7 @@
|
|
9
9
|
# DCell overlay network back to the node where the actor actually exists
|
10
10
|
|
11
11
|
module Celluloid
|
12
|
-
class
|
12
|
+
class CellProxy
|
13
13
|
# Marshal uses respond_to? to determine if this object supports _dump so
|
14
14
|
# unfortunately we have to monkeypatch in _dump support as the proxy
|
15
15
|
# itself normally jacks respond_to? and proxies to the actor
|
@@ -33,11 +33,12 @@ module Celluloid
|
|
33
33
|
case mailbox
|
34
34
|
when ::DCell::MailboxProxy
|
35
35
|
actor = ::DCell::Actor.new(mailbox)
|
36
|
-
::DCell::
|
36
|
+
::DCell::CellProxy.new actor.proxy, mailbox, actor.subject.class.to_s
|
37
37
|
when ::Celluloid::Mailbox
|
38
38
|
actor = find_actor(mailbox)
|
39
|
-
::Celluloid::
|
40
|
-
else
|
39
|
+
::Celluloid::CellProxy.new actor.proxy, mailbox, actor.behavior.subject.class.to_s
|
40
|
+
else
|
41
|
+
::Kernel.raise "funny, I did not expect to see a #{mailbox.class} here"
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
data/lib/dcell/directory.rb
CHANGED
data/lib/dcell/explorer.rb
CHANGED
@@ -6,7 +6,7 @@ require 'erb'
|
|
6
6
|
module DCell
|
7
7
|
# Web UI for DCell
|
8
8
|
# TODO: rewrite this entire thing with less hax
|
9
|
-
class Explorer < Reel::Server
|
9
|
+
class Explorer < Reel::Server
|
10
10
|
ASSET_ROOT = Pathname.new File.expand_path("../../../explorer", __FILE__)
|
11
11
|
|
12
12
|
def initialize(host = "127.0.0.1", port = 7778)
|
data/lib/dcell/node.rb
CHANGED
@@ -18,6 +18,7 @@ module DCell
|
|
18
18
|
Celluloid::Logger.info "Connected to #{id}"
|
19
19
|
end
|
20
20
|
state :partitioned do
|
21
|
+
@heartbeat.cancel
|
21
22
|
Celluloid::Logger.warn "Communication with #{id} interrupted"
|
22
23
|
end
|
23
24
|
|
@@ -32,7 +33,7 @@ module DCell
|
|
32
33
|
include Enumerable
|
33
34
|
extend Forwardable
|
34
35
|
|
35
|
-
def_delegators "Celluloid::Actor[:node_manager]", :all, :each, :find, :[]
|
36
|
+
def_delegators "Celluloid::Actor[:node_manager]", :all, :each, :find, :[], :remove, :update
|
36
37
|
def_delegators "Celluloid::Actor[:node_manager]", :heartbeat_rate, :heartbeat_timeout
|
37
38
|
end
|
38
39
|
|
@@ -45,6 +46,15 @@ module DCell
|
|
45
46
|
attach self
|
46
47
|
end
|
47
48
|
|
49
|
+
def update_client_address( addr )
|
50
|
+
@addr = addr
|
51
|
+
send_heartbeat
|
52
|
+
end
|
53
|
+
|
54
|
+
def update_server_address(addr)
|
55
|
+
@addr = addr
|
56
|
+
end
|
57
|
+
|
48
58
|
def shutdown
|
49
59
|
transition :shutdown
|
50
60
|
@socket.close if @socket
|
data/lib/dcell/node_manager.rb
CHANGED
@@ -4,6 +4,8 @@ module DCell
|
|
4
4
|
include Celluloid::ZMQ
|
5
5
|
include Enumerable
|
6
6
|
|
7
|
+
trap_exit :node_died
|
8
|
+
|
7
9
|
attr_reader :heartbeat_rate, :heartbeat_timeout
|
8
10
|
|
9
11
|
def initialize
|
@@ -39,11 +41,39 @@ module DCell
|
|
39
41
|
node = DCell.me
|
40
42
|
else
|
41
43
|
node = Node.new(id, addr)
|
44
|
+
self.link node
|
42
45
|
end
|
43
46
|
|
44
47
|
@nodes[id] ||= node
|
45
48
|
@nodes[id]
|
46
49
|
end
|
47
50
|
alias_method :[], :find
|
51
|
+
|
52
|
+
def node_died(node, reason)
|
53
|
+
if reason.nil? # wtf?
|
54
|
+
# this wtf error seems to come from node socket writes
|
55
|
+
# when the socket is not reachable anymore
|
56
|
+
Celluloid::logger.debug "wtf?"
|
57
|
+
return
|
58
|
+
end
|
59
|
+
# Handle dead node???
|
60
|
+
end
|
61
|
+
|
62
|
+
def update(id)
|
63
|
+
addr = Directory[id]
|
64
|
+
return unless addr
|
65
|
+
if ( node = @nodes[id] ) and node.alive?
|
66
|
+
node.update_client_address( addr )
|
67
|
+
else
|
68
|
+
@nodes[id] = Node.new( id, addr )
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def remove(id)
|
73
|
+
if @nodes[id]
|
74
|
+
@nodes[id].terminate if @nodes[id].alive?
|
75
|
+
@nodes.delete(id)
|
76
|
+
end
|
77
|
+
end
|
48
78
|
end
|
49
79
|
end
|
@@ -48,12 +48,16 @@ module DCell
|
|
48
48
|
@global_registry = GlobalRegistry.new(cass, columnfamily)
|
49
49
|
end
|
50
50
|
|
51
|
-
def
|
52
|
-
@node_registry.
|
51
|
+
def remove_node(node)
|
52
|
+
@node_registry.remove node
|
53
|
+
end
|
54
|
+
|
55
|
+
def clear_all_nodes
|
56
|
+
@node_registry.clear_all
|
53
57
|
end
|
54
58
|
|
55
59
|
def clear_globals
|
56
|
-
@global_registry.
|
60
|
+
@global_registry.clear_all
|
57
61
|
end
|
58
62
|
|
59
63
|
class NodeRegistry
|
@@ -74,7 +78,11 @@ module DCell
|
|
74
78
|
@cass.get(@cf, "nodes").keys
|
75
79
|
end
|
76
80
|
|
77
|
-
def
|
81
|
+
def remove(node)
|
82
|
+
@cass.remove @cf, "nodes", { node_id => node }
|
83
|
+
end
|
84
|
+
|
85
|
+
def clear_all
|
78
86
|
@cass.del @cf, "nodes"
|
79
87
|
end
|
80
88
|
end
|
@@ -105,7 +113,7 @@ module DCell
|
|
105
113
|
@cass.get(@cf, "globals").keys
|
106
114
|
end
|
107
115
|
|
108
|
-
def
|
116
|
+
def clear_all
|
109
117
|
@cass.del @cf, "globals"
|
110
118
|
end
|
111
119
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'mongoid'
|
2
|
+
|
3
|
+
module DCell
|
4
|
+
module Registry
|
5
|
+
class MongodbAdapter
|
6
|
+
# Setup connection to mongodb
|
7
|
+
# config: path to mongoid configuration file
|
8
|
+
# env: mongoid environment to use
|
9
|
+
def initialize(options)
|
10
|
+
if options[:config]
|
11
|
+
Mongoid.load! options[:config], options[:env]
|
12
|
+
elsif options[:db]
|
13
|
+
Mongoid.connect_to options[:db]
|
14
|
+
end
|
15
|
+
if options[:options]
|
16
|
+
Mongoid.options = options[:options]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class DCellNode
|
21
|
+
include Mongoid::Document
|
22
|
+
|
23
|
+
field :key, type: String
|
24
|
+
field :value, type: Hash
|
25
|
+
end
|
26
|
+
|
27
|
+
class DCellGlobal
|
28
|
+
include Mongoid::Document
|
29
|
+
|
30
|
+
field :key, type: String
|
31
|
+
field :value, type: Hash
|
32
|
+
end
|
33
|
+
|
34
|
+
class Proxy
|
35
|
+
class << self
|
36
|
+
def set(storage, key, value)
|
37
|
+
entry = storage.find_or_create_by(key: key)
|
38
|
+
entry.value = {'v' => value}
|
39
|
+
entry.save!
|
40
|
+
value
|
41
|
+
end
|
42
|
+
|
43
|
+
def get(storage, key)
|
44
|
+
first = storage.where(key: key).first
|
45
|
+
if first and first.value
|
46
|
+
return first.value['v']
|
47
|
+
end
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def all(storage)
|
52
|
+
keys = []
|
53
|
+
storage.each do |entry|
|
54
|
+
keys << entry.key
|
55
|
+
end
|
56
|
+
keys
|
57
|
+
end
|
58
|
+
|
59
|
+
def remove(storage, key)
|
60
|
+
begin
|
61
|
+
storage.where(key: key).delete
|
62
|
+
rescue
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def clear_all(storage)
|
67
|
+
storage.delete_all
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_node(node_id); Proxy.get(DCellNode, node_id) end
|
73
|
+
def set_node(node_id, addr); Proxy.set(DCellNode, node_id, addr) end
|
74
|
+
def nodes; Proxy.all(DCellNode) end
|
75
|
+
def remove_node(node_id); Proxy.remove(DCellNode, node_id) end
|
76
|
+
def clear_all_nodes; Proxy.clear_all(DCellNode) end
|
77
|
+
|
78
|
+
def get_global(key); Proxy.get(DCellGlobal, key) end
|
79
|
+
def set_global(key, value); Proxy.set(DCellGlobal, key, value) end
|
80
|
+
def global_keys; Proxy.all(DCellGlobal) end
|
81
|
+
def clear_globals; Proxy.clear_all(DCellGlobal) end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -19,12 +19,16 @@ module DCell
|
|
19
19
|
@global_registry = GlobalRegistry.new(@redis)
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
@node_registry.
|
22
|
+
def remove_node(node)
|
23
|
+
@node_registry.remove node
|
24
|
+
end
|
25
|
+
|
26
|
+
def clear_all_nodes
|
27
|
+
@node_registry.clear_all
|
24
28
|
end
|
25
29
|
|
26
30
|
def clear_globals
|
27
|
-
@global_registry.
|
31
|
+
@global_registry.clear_all
|
28
32
|
end
|
29
33
|
|
30
34
|
class NodeRegistry
|
@@ -44,7 +48,11 @@ module DCell
|
|
44
48
|
@redis.hkeys 'nodes'
|
45
49
|
end
|
46
50
|
|
47
|
-
def
|
51
|
+
def remove(node)
|
52
|
+
@redis.hdel 'nodes', node
|
53
|
+
end
|
54
|
+
|
55
|
+
def clear_all
|
48
56
|
@redis.del 'nodes'
|
49
57
|
end
|
50
58
|
end
|
@@ -74,7 +82,7 @@ module DCell
|
|
74
82
|
@redis.hkeys 'globals'
|
75
83
|
end
|
76
84
|
|
77
|
-
def
|
85
|
+
def clear_all
|
78
86
|
@redis.del 'globals'
|
79
87
|
end
|
80
88
|
end
|
@@ -46,15 +46,36 @@ module DCell
|
|
46
46
|
@base_path = File.join(base_path, name.to_s)
|
47
47
|
@ephemeral = ephemeral
|
48
48
|
@zk.mkdir_p @base_path
|
49
|
+
@events = {}
|
50
|
+
end
|
51
|
+
|
52
|
+
def register(key)
|
53
|
+
path = "#{@base_path}/#{key}"
|
54
|
+
@events[path] ||= @zk.register(path) do |event|
|
55
|
+
key = event.path.match(/#{@base_path}\/(\w+)/)[1]
|
56
|
+
@events[event.path].unsubscribe
|
57
|
+
@events[event.path] = nil
|
58
|
+
if event.node_changed?
|
59
|
+
Celluloid::logger.debug "zk callback: node changed!"
|
60
|
+
Node.update(key)
|
61
|
+
end
|
62
|
+
if event.node_deleted?
|
63
|
+
Celluloid::logger.debug "zk callback: node deleted!"
|
64
|
+
Node.remove(key)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
49
68
|
end
|
50
69
|
|
51
70
|
def get(key)
|
52
|
-
|
71
|
+
register(key)
|
72
|
+
result, _ = @zk.get("#{@base_path}/#{key}", watch: true)
|
53
73
|
Marshal.load result
|
54
74
|
rescue ZK::Exceptions::NoNode
|
55
75
|
end
|
56
76
|
|
57
77
|
def set(key, value)
|
78
|
+
register(key)
|
58
79
|
path = "#{@base_path}/#{key}"
|
59
80
|
string = Marshal.dump value
|
60
81
|
@zk.set path, string
|
@@ -66,7 +87,21 @@ module DCell
|
|
66
87
|
@zk.children @base_path
|
67
88
|
end
|
68
89
|
|
69
|
-
def
|
90
|
+
def remove(key)
|
91
|
+
keys.each do |key|
|
92
|
+
path = "#{@base_path}/#{key}"
|
93
|
+
@zk.delete path
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def clear_all
|
98
|
+
# delete znodes so any registered
|
99
|
+
# callback is triggered
|
100
|
+
all.each do |key|
|
101
|
+
remove key
|
102
|
+
end
|
103
|
+
@events.values.compact.each(&:unsubscribe)
|
104
|
+
@events.clear
|
70
105
|
@zk.rm_rf @base_path
|
71
106
|
@zk.mkdir_p @base_path
|
72
107
|
end
|
@@ -75,12 +110,13 @@ module DCell
|
|
75
110
|
def get_node(node_id); @node_registry.get(node_id) end
|
76
111
|
def set_node(node_id, addr); @node_registry.set(node_id, addr) end
|
77
112
|
def nodes; @node_registry.all end
|
78
|
-
def
|
113
|
+
def remove_node(node_id); @node_registry.clear(node_id) end
|
114
|
+
def clear_all_nodes; @node_registry.clear_all end
|
79
115
|
|
80
116
|
def get_global(key); @global_registry.get(key) end
|
81
117
|
def set_global(key, value); @global_registry.set(key, value) end
|
82
118
|
def global_keys; @global_registry.all end
|
83
|
-
def clear_globals; @global_registry.
|
119
|
+
def clear_globals; @global_registry.clear_all end
|
84
120
|
|
85
121
|
end
|
86
122
|
end
|
data/lib/dcell/server.rb
CHANGED
@@ -10,11 +10,13 @@ module DCell
|
|
10
10
|
# The gossip protocol is dependent on the node manager
|
11
11
|
link Celluloid::Actor[:node_manager]
|
12
12
|
|
13
|
-
@addr = DCell.addr
|
14
13
|
@socket = PullSocket.new
|
15
14
|
|
16
15
|
begin
|
17
|
-
@socket.bind(
|
16
|
+
@socket.bind(DCell.addr)
|
17
|
+
real_addr = @socket.get(::ZMQ::LAST_ENDPOINT).strip
|
18
|
+
DCell::Directory.set DCell.id, real_addr
|
19
|
+
DCell.addr = real_addr
|
18
20
|
rescue IOError
|
19
21
|
@socket.close
|
20
22
|
raise
|
data/lib/dcell/version.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe DCell::
|
3
|
+
describe DCell::CellProxy do
|
4
4
|
before :all do
|
5
|
-
@node = DCell::Node[
|
6
|
-
@node.id.should ==
|
5
|
+
@node = DCell::Node[TEST_NODE[:id]]
|
6
|
+
@node.id.should == TEST_NODE[:id]
|
7
7
|
@remote_actor = @node[:test_actor]
|
8
8
|
|
9
9
|
class LocalActor
|
@@ -5,4 +5,18 @@ describe DCell::Directory do
|
|
5
5
|
DCell::Directory["foobar"] = "tcp://localhost:1870"
|
6
6
|
DCell::Directory["foobar"].should == "tcp://localhost:1870"
|
7
7
|
end
|
8
|
-
|
8
|
+
it "presents all stored addresses" do
|
9
|
+
DCell::Directory["foo"] = "tcp://fooaddress"
|
10
|
+
DCell::Directory["bar"] = "tcp://baraddress"
|
11
|
+
DCell::Directory.all.should include("foo")
|
12
|
+
DCell::Directory.all.should include("bar")
|
13
|
+
end
|
14
|
+
it "clears node addresses" do
|
15
|
+
DCell::Directory["foo"] = "tcp://fooaddress"
|
16
|
+
DCell::Directory["foobar"].should == "tcp://localhost:1870"
|
17
|
+
["foo", "foobar"].each do |node|
|
18
|
+
DCell::Directory.remove node
|
19
|
+
end
|
20
|
+
DCell::Directory["foobar"].should_not == "tcp://localhost:1870"
|
21
|
+
end
|
22
|
+
end
|
data/spec/dcell/explorer_spec.rb
CHANGED
@@ -12,6 +12,6 @@ describe DCell::Explorer do
|
|
12
12
|
|
13
13
|
it "reports the current node's status" do
|
14
14
|
response = Net::HTTP.get URI(EXPLORER_BASE)
|
15
|
-
response[%r{<
|
15
|
+
response[%r{<a href="/nodes/(.*?)">}, 1].should == DCell.id
|
16
16
|
end
|
17
17
|
end
|
data/spec/dcell/global_spec.rb
CHANGED
@@ -10,7 +10,7 @@ describe DCell::Global do
|
|
10
10
|
DCell::Global[:the_answer].should == 42
|
11
11
|
|
12
12
|
# Double check the global value is available on all nodes
|
13
|
-
node = DCell::Node[
|
13
|
+
node = DCell::Node[TEST_NODE[:id]]
|
14
14
|
node[:test_actor].the_answer.should == 42
|
15
15
|
end
|
16
16
|
|
data/spec/dcell/node_spec.rb
CHANGED
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'dcell/registries/mongodb_adapter'
|
3
|
+
|
4
|
+
describe DCell::Registry::MongodbAdapter, :pending => TEST_ADEPTER != 'mongodb' && "no mongodb" do
|
5
|
+
subject { DCell::Registry::MongodbAdapter.new TEST_DB[:mongodb] }
|
6
|
+
it_behaves_like "a DCell registry"
|
7
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe DCell::Registry::RedisAdapter do
|
4
|
-
subject { DCell::Registry::RedisAdapter.new :
|
3
|
+
describe DCell::Registry::RedisAdapter, :pending => TEST_ADEPTER != 'redis' && "no redis" do
|
4
|
+
subject { DCell::Registry::RedisAdapter.new TEST_DB[:redis] }
|
5
5
|
it_behaves_like "a DCell registry"
|
6
|
-
end
|
6
|
+
end
|
@@ -1,7 +1,28 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'dcell/registries/zk_adapter'
|
3
3
|
|
4
|
-
describe DCell::Registry::ZkAdapter, :pending =>
|
5
|
-
subject { DCell::Registry::ZkAdapter.new :
|
6
|
-
it_behaves_like "a DCell registry"
|
4
|
+
describe DCell::Registry::ZkAdapter, :pending => TEST_ADEPTER != 'zk' && "no zookeeper" do
|
5
|
+
subject { DCell::Registry::ZkAdapter.new TEST_DB[:zk] }
|
6
|
+
it_behaves_like "a DCell registry" do
|
7
|
+
context "when one znode changes" do
|
8
|
+
it "updates a node" do
|
9
|
+
expect(DCell::Node).to receive(:update).with("foo")
|
10
|
+
subject.set_node("foo", "tcp://fooaddress")
|
11
|
+
# WARNING: only by calling get_node we renew the watcher
|
12
|
+
subject.get_node("foo").should eq("tcp://fooaddress")
|
13
|
+
subject.set_node("foo", "tcp://newaddress")
|
14
|
+
sleep 0.8 # takes some time to zookeeper watchers to take full effect
|
15
|
+
end
|
16
|
+
end
|
17
|
+
context "when one znode is deleted" do
|
18
|
+
it "deletes a node" do
|
19
|
+
expect(DCell::Node).to receive(:remove).with("foo")
|
20
|
+
subject.set_node("foo", "tcp://fooaddress")
|
21
|
+
# WARNING: only by calling get_node we renew the watcher
|
22
|
+
subject.get_node("foo").should eq("tcp://fooaddress")
|
23
|
+
subject.remove_node "foo"
|
24
|
+
sleep 0.8 # takes some time to zookeeper watchers to take full effect
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
7
28
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
TEST_ADEPTER = ENV['DCELL_TEST_ADAPTER'] || 'redis'
|
2
|
+
|
3
|
+
require "dcell/registries/#{TEST_ADEPTER}_adapter"
|
4
|
+
|
5
|
+
def test_db_options
|
6
|
+
options = {}
|
7
|
+
adapter = TEST_ADEPTER
|
8
|
+
if adapter
|
9
|
+
options[:registry] = {:adapter => adapter}
|
10
|
+
options[:registry].merge! TEST_DB[adapter.to_sym]
|
11
|
+
end
|
12
|
+
options
|
13
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,12 +4,19 @@ require 'coveralls'
|
|
4
4
|
Coveralls.wear!
|
5
5
|
|
6
6
|
require 'dcell'
|
7
|
+
Dir['./spec/options/*.rb'].map { |f| require f }
|
7
8
|
Dir['./spec/support/*.rb'].map { |f| require f }
|
8
9
|
|
9
10
|
RSpec.configure do |config|
|
10
11
|
config.before(:suite) do
|
11
|
-
|
12
|
-
|
12
|
+
options = {}
|
13
|
+
options.merge! test_db_options
|
14
|
+
begin
|
15
|
+
DCell.start options
|
16
|
+
rescue => e
|
17
|
+
puts e
|
18
|
+
raise
|
19
|
+
end
|
13
20
|
|
14
21
|
TestNode.start
|
15
22
|
TestNode.wait_until_ready
|
data/spec/support/helpers.rb
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
require 'rubygems'
|
3
3
|
|
4
4
|
module TestNode
|
5
|
-
PORT = 21264
|
6
|
-
|
7
5
|
def self.start
|
8
6
|
@pid = Process.spawn Gem.ruby, File.expand_path("../../test_node.rb", __FILE__)
|
9
7
|
unless @pid
|
@@ -18,7 +16,7 @@ module TestNode
|
|
18
16
|
socket = nil
|
19
17
|
30.times do
|
20
18
|
begin
|
21
|
-
socket = TCPSocket.open(
|
19
|
+
socket = TCPSocket.open(TEST_NODE[:addr], TEST_NODE[:port])
|
22
20
|
break if socket
|
23
21
|
rescue Errno::ECONNREFUSED
|
24
22
|
STDERR.print "."
|
data/spec/test_node.rb
CHANGED
@@ -6,7 +6,11 @@ require 'bundler'
|
|
6
6
|
Bundler.setup
|
7
7
|
|
8
8
|
require 'dcell'
|
9
|
-
|
9
|
+
Dir['./spec/options/*.rb'].map { |f| require f }
|
10
|
+
|
11
|
+
options = {:id => TEST_NODE[:id], :addr => "tcp://#{TEST_NODE[:addr]}:#{TEST_NODE[:port]}"}
|
12
|
+
options.merge! test_db_options
|
13
|
+
DCell.start options
|
10
14
|
|
11
15
|
class TestActor
|
12
16
|
include Celluloid
|
@@ -31,4 +35,4 @@ class TestActor
|
|
31
35
|
end
|
32
36
|
|
33
37
|
TestActor.supervise_as :test_actor
|
34
|
-
sleep
|
38
|
+
sleep
|
metadata
CHANGED
@@ -1,57 +1,71 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dcell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.16.
|
4
|
+
version: 0.16.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Arcieri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: celluloid
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: 0.16.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 0.16.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: celluloid-zmq
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 0.16.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.16.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: reel
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 0.4.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 0.4.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: http
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.5.0
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.5.0
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: celluloid-redis
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,16 +112,16 @@ dependencies:
|
|
98
112
|
name: rspec
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- - "
|
115
|
+
- - "~>"
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
117
|
+
version: 2.14.0
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- - "
|
122
|
+
- - "~>"
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
124
|
+
version: 2.14.0
|
111
125
|
description: DCell is an distributed object framework based on Celluloid built on
|
112
126
|
0MQ and Zookeeper
|
113
127
|
email:
|
@@ -155,6 +169,7 @@ files:
|
|
155
169
|
- lib/dcell/node.rb
|
156
170
|
- lib/dcell/node_manager.rb
|
157
171
|
- lib/dcell/registries/cassandra_adapter.rb
|
172
|
+
- lib/dcell/registries/mongodb_adapter.rb
|
158
173
|
- lib/dcell/registries/redis_adapter.rb
|
159
174
|
- lib/dcell/registries/zk_adapter.rb
|
160
175
|
- lib/dcell/responses.rb
|
@@ -170,8 +185,11 @@ files:
|
|
170
185
|
- spec/dcell/explorer_spec.rb
|
171
186
|
- spec/dcell/global_spec.rb
|
172
187
|
- spec/dcell/node_spec.rb
|
188
|
+
- spec/dcell/registries/mongodb_adapter_spec.rb
|
173
189
|
- spec/dcell/registries/redis_adapter_spec.rb
|
174
190
|
- spec/dcell/registries/zk_adapter_spec.rb
|
191
|
+
- spec/options/01-options.rb
|
192
|
+
- spec/options/02-registry.rb
|
175
193
|
- spec/spec_helper.rb
|
176
194
|
- spec/support/helpers.rb
|
177
195
|
- spec/support/registry_examples.rb
|
@@ -210,10 +228,12 @@ test_files:
|
|
210
228
|
- spec/dcell/explorer_spec.rb
|
211
229
|
- spec/dcell/global_spec.rb
|
212
230
|
- spec/dcell/node_spec.rb
|
231
|
+
- spec/dcell/registries/mongodb_adapter_spec.rb
|
213
232
|
- spec/dcell/registries/redis_adapter_spec.rb
|
214
233
|
- spec/dcell/registries/zk_adapter_spec.rb
|
234
|
+
- spec/options/01-options.rb
|
235
|
+
- spec/options/02-registry.rb
|
215
236
|
- spec/spec_helper.rb
|
216
237
|
- spec/support/helpers.rb
|
217
238
|
- spec/support/registry_examples.rb
|
218
239
|
- spec/test_node.rb
|
219
|
-
has_rdoc:
|