Skip to content
This repository has been archived by the owner on Dec 7, 2018. It is now read-only.

WIP: Add support for etcd registry. #53

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ gem 'celluloid', github: 'celluloid/celluloid', branch: 'master'
gem 'celluloid-io', github: 'celluloid/celluloid-io', branch: 'master'
gem 'celluloid-zmq', github: 'celluloid/celluloid-zmq', branch: 'master'
gem 'celluloid-redis', github: 'celluloid/celluloid-redis', branch: 'master'
gem 'http', github: 'tarcieri/http', branch: 'master'
gem 'reel', github: 'celluloid/reel', branch: 'master'

#gem 'ffi-rzmq', github: 'chuckremes/ffi-rzmq'
Expand All @@ -15,3 +16,5 @@ gem 'coveralls', require: false
gemspec

gem 'zk'
gem 'etcd', '~> 0.2.0.beta.1'

3 changes: 1 addition & 2 deletions lib/dcell/celluloid_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@ class ActorProxy
# Marshal uses respond_to? to determine if this object supports _dump so
# unfortunately we have to monkeypatch in _dump support as the proxy
# itself normally jacks respond_to? and proxies to the actor
alias_method :__respond_to?, :respond_to?
def respond_to?(meth, check_private = false)
return false if meth == :marshal_dump
return true if meth == :_dump
__respond_to?(meth, check_private)
method_missing(:respond_to?, meth, include_private)
end

# Dump an actor proxy via its mailbox
Expand Down
104 changes: 104 additions & 0 deletions lib/dcell/registries/etcd_adapter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
require 'uri'
require 'etcd'

module DCell
module Registry
class EtcdAdapter
PREFIX = '/dcell'
DEFAULT_SCHEME = 'http'
DEFAULT_PORT = 4001

# Create a new connect to Etc daemon.
#
# servers: List of Etcd servers to connect to. Each server
# has a host/port configuration.
def initialize(options={})
options = options.inject({}) { |h,(k,v)| h[k.to_s] = v; h }

@env = options['env'] || 'production'
@base_path = "#{PREFIX}/#{@env}"

if options['server']
servers = [ options['server'] ]
else
servers = options['servers']
end

# Sanity check.
raise 'no Etcd servers given' unless servers

# Add default Etcd port unless specified.
servers.map! do |server|
if server[/:\d+$/]
server
else
"#{server}:#{DEFAULT_PORT}"
end
end

server = server.first
@etcd = Etcd.client(host: server.host, port: server.port)

server = server.is_a?(URI) ? server : URI(server)
if server.scheme && server.host && server.port
server
else
server = URI("#{DEFAULT_SCHEME}://#{server.to_s}:#{DEFAULT_PORT}")
end
end

server = servers[rand(servers.count)]
@etcd = Etcd.client(host: server.host,
port: server.port,
use_ssl: server.scheme == 'https' ? true : false,
user_name: server.user,
password: server.password)

@node_registry = Registry.new(@etcd, @base_path, :nodes)
@global_registry = Registry.new(@etcd, @base_path, :globals)
end

def get_node(node_id); @node_registry.get(node_id) end
def set_node(node_id, addr); @node_registry.set(node_id, addr) end
def nodes; @node_registry.all end
def clear_nodes; @node_registry.clear end

def get_global(key); @global_registry.get(key) end
def set_global(key, value); @global_registry.set(key, value) end
def global_keys; @global_registry.all end
def clear_globals; @global_registry.clear end

class Registry
def initialize(etcd, base_path, name)
@etcd = etcd
@base_path = File.join(base_path, name.to_s)

unless @etcd.exists?(@base_path)
@etcd.create(@base_path, dir: true)
end
end

def get(key)
result = @etcd.get(File.join(base_path, key))
Marshal.load(result.value)
end

def set(key, value)
path = File.join base_path, key
string = Marshal.dump value
@etcd.set(path, value: string)
rescue Etcd::NodeExist
@etcd.update(path, value: string)
end

def all
@etcd.get(@base_path).children
end

def clear
@etcd.delete(@base_path)
@etcd.create(@base_path, dir: true)
end
end
end
end
7 changes: 7 additions & 0 deletions spec/dcell/registries/etcd_adapter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'spec_helper'
require 'dcell/registries/etcd_adapter'

describe DCell::Registry::EtcdAdapter, :pending => ENV["CI"] && "no etcd" do
subject { DCell::Registry::EtcdAdapter.new :server => 'localhost', :env => 'test' }
it_behaves_like "a DCell registry"
end