fraggle-block-spanx 0.2.1
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.
- data/.gitignore +5 -0
- data/Gemfile +4 -0
- data/README.md +26 -0
- data/Rakefile +27 -0
- data/bin/fraggle-block +8 -0
- data/examples/client.rb +19 -0
- data/fraggle-block.gemspec +24 -0
- data/lib/fraggle/block.rb +44 -0
- data/lib/fraggle/block/client.rb +82 -0
- data/lib/fraggle/block/connection.rb +49 -0
- data/lib/fraggle/block/msg.pb.rb +61 -0
- data/lib/fraggle/block/response.rb +24 -0
- data/lib/fraggle/block/version.rb +5 -0
- metadata +91 -0
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Fraggle::Block
|
2
|
+
|
3
|
+
A synchronous Ruby client for [Doozer](https://github.com/ha/doozer).
|
4
|
+
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
>> require 'rubygems'
|
9
|
+
>> require 'fraggle/block'
|
10
|
+
>> client = Fraggle::Block.connect
|
11
|
+
=> #<Fraggle::Block::Client:0x10217b260 @connection=#<Fraggle::Block::Connection:0x10217bbc0 @cn=#<TCPSocket:0x10217b3c8>, host"127.0.0.1", port8046
|
12
|
+
>> res = client.set(1_000_000, '/foo', 'test')
|
13
|
+
=> Fraggle::Block::Response tag: 0, flags: 3, rev: 482
|
14
|
+
>> res = client.get(res.rev, '/foo')
|
15
|
+
=> Fraggle::Block::Response value: "test", tag: 0, flags: 3, rev: 482
|
16
|
+
>> res = client.del(res.rev, '/foo')
|
17
|
+
=> Fraggle::Block::Response tag: 0, flags: 3
|
18
|
+
>> client.disconnect
|
19
|
+
=> nil
|
20
|
+
|
21
|
+
See [examples](https://github.com/dylanegan/fraggle-block/tree/master/examples) for more.
|
22
|
+
|
23
|
+
|
24
|
+
## Install
|
25
|
+
|
26
|
+
$ gem install fraggle-block
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
HOME = ENV["HOME"]
|
5
|
+
PBDIR = HOME+"/Code/heroku/doozer/src/pkg/proto"
|
6
|
+
|
7
|
+
namespace :proto do
|
8
|
+
task :update do
|
9
|
+
ENV["BEEFCAKE_NAMESPACE"] = "Fraggle::Block"
|
10
|
+
sh(
|
11
|
+
"protoc",
|
12
|
+
"--beefcake_out", "lib/fraggle/block",
|
13
|
+
"-I", PBDIR,
|
14
|
+
PBDIR+"/msg.proto"
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'rake/testtask'
|
20
|
+
|
21
|
+
namespace :test do
|
22
|
+
Rake::TestTask.new(:all) do |t|
|
23
|
+
t.libs << "test"
|
24
|
+
t.pattern = 'test/**/*_test.rb'
|
25
|
+
t.verbose = true
|
26
|
+
end
|
27
|
+
end
|
data/bin/fraggle-block
ADDED
data/examples/client.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'fraggle/block'
|
4
|
+
|
5
|
+
client = Fraggle::Block.connect
|
6
|
+
|
7
|
+
rev = client.set(1_000_000, '/foo', 'test').rev
|
8
|
+
puts "Setting /foo to test with rev #{rev}"
|
9
|
+
|
10
|
+
foo = client.get(rev, '/foo')
|
11
|
+
puts "Got /foo with #{foo.value}"
|
12
|
+
|
13
|
+
rev = client.del(rev, '/foo').rev
|
14
|
+
puts "Deleted /foo"
|
15
|
+
|
16
|
+
foo = client.get(rev, '/foo')
|
17
|
+
puts foo.inspect
|
18
|
+
|
19
|
+
client.disconnect
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "fraggle/block/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "fraggle-block-spanx"
|
7
|
+
s.version = Fraggle::Block::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Dylan Egan", "Blake Mizerany"]
|
10
|
+
s.email = ["dylanegan@gmail.com", "blake.mizerany@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/dylanegan/fraggle-block"
|
12
|
+
s.summary = %q{A synchronous Ruby client for Doozer.}
|
13
|
+
s.description = %q{A synchronous Ruby client for Doozer.}
|
14
|
+
|
15
|
+
s.rubyforge_project = "fraggle-block"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
|
22
|
+
s.add_dependency "beefcake-spanx"
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "fraggle/block/client"
|
2
|
+
require "fraggle/block/response"
|
3
|
+
|
4
|
+
module Fraggle
|
5
|
+
module Block
|
6
|
+
Clobber = Client::MaxInt64
|
7
|
+
|
8
|
+
DEFAULT_URI = "doozer:?" + [
|
9
|
+
"ca=127.0.0.1:8046",
|
10
|
+
"ca=127.0.0.1:8041",
|
11
|
+
"ca=127.0.0.1:8042",
|
12
|
+
"ca=127.0.0.1:8043"
|
13
|
+
].join("&")
|
14
|
+
|
15
|
+
def self.connect(uri=nil)
|
16
|
+
uri = uri || ENV["DOOZER_URI"] || DEFAULT_URI
|
17
|
+
|
18
|
+
addrs = URI.parse(uri)
|
19
|
+
|
20
|
+
if addrs.length == 0
|
21
|
+
raise(ArgumentError, "no addrs in doozerd uri '#{uri.inspect}'")
|
22
|
+
end
|
23
|
+
|
24
|
+
Client.new(addrs)
|
25
|
+
end
|
26
|
+
|
27
|
+
module URI
|
28
|
+
def self.parse(u)
|
29
|
+
if u =~ /^doozer:\?(.*)$/
|
30
|
+
parts = $1.split("&")
|
31
|
+
parts.inject([]) do |m, pt|
|
32
|
+
k, v = pt.split("=")
|
33
|
+
if k == "ca"
|
34
|
+
m << v
|
35
|
+
end
|
36
|
+
m
|
37
|
+
end
|
38
|
+
else
|
39
|
+
raise(ArgumentError, "invalid doozerd uri '#{u}'")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require "fraggle/block/connection"
|
2
|
+
|
3
|
+
module Fraggle
|
4
|
+
module Block
|
5
|
+
class Client
|
6
|
+
include Request::Verb
|
7
|
+
|
8
|
+
MaxInt64 = 1<<63 - 1
|
9
|
+
|
10
|
+
class NoMoreAddrs < StandardError; end
|
11
|
+
|
12
|
+
attr_accessor :addrs
|
13
|
+
attr_reader :connection
|
14
|
+
|
15
|
+
def initialize(addrs = [])
|
16
|
+
@addrs = addrs
|
17
|
+
connect
|
18
|
+
end
|
19
|
+
|
20
|
+
def rev
|
21
|
+
send(:verb => REV)
|
22
|
+
end
|
23
|
+
|
24
|
+
def get(rev, path)
|
25
|
+
send(:verb => GET, :rev => rev, :path => path)
|
26
|
+
end
|
27
|
+
|
28
|
+
def set(rev, path, value)
|
29
|
+
send(:verb => SET, :rev => rev, :path => path, :value => value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def del(rev, path)
|
33
|
+
send(:verb => DEL, :rev => rev, :path => path)
|
34
|
+
end
|
35
|
+
|
36
|
+
def walk(rev, path, offset)
|
37
|
+
send(:verb => WALK, :rev => rev, :path => path, :offset => offset)
|
38
|
+
end
|
39
|
+
|
40
|
+
def disconnect
|
41
|
+
@connection.disconnect
|
42
|
+
end
|
43
|
+
|
44
|
+
def reconnect
|
45
|
+
disconnect
|
46
|
+
connect
|
47
|
+
end
|
48
|
+
|
49
|
+
def connect
|
50
|
+
begin
|
51
|
+
host, port = @addrs.shift.split(":")
|
52
|
+
@connection = Connection.new(host, port)
|
53
|
+
find_all_of_the_nodes
|
54
|
+
rescue => e
|
55
|
+
retry if @addrs.any?
|
56
|
+
raise(NoMoreAddrs)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_all_of_the_nodes
|
61
|
+
r = rev.rev
|
62
|
+
i = 0
|
63
|
+
loop do
|
64
|
+
res = walk(r, "/ctl/node/*/addr", i)
|
65
|
+
if res.ok?
|
66
|
+
i += 1
|
67
|
+
@addrs << res.value if !(@addrs.include?(res.value))
|
68
|
+
else
|
69
|
+
break
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
def send(request)
|
77
|
+
@connection.send(Request.new(request))
|
78
|
+
@connection.read
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require "fraggle/block/msg.pb"
|
2
|
+
require "socket"
|
3
|
+
require "timeout"
|
4
|
+
|
5
|
+
module Fraggle
|
6
|
+
module Block
|
7
|
+
class Connection
|
8
|
+
attr_accessor :host, :port, :sock
|
9
|
+
|
10
|
+
def initialize(host, port)
|
11
|
+
@host = host
|
12
|
+
@port = port
|
13
|
+
@sock = connect
|
14
|
+
end
|
15
|
+
|
16
|
+
def address
|
17
|
+
"#{@host}:#{@port}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def connect
|
21
|
+
Timeout::timeout(10) do
|
22
|
+
s = TCPSocket.new(@host, @port)
|
23
|
+
s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
24
|
+
s
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def disconnect
|
29
|
+
@sock.close
|
30
|
+
end
|
31
|
+
|
32
|
+
def send(req)
|
33
|
+
req.tag = 0
|
34
|
+
data = req.encode
|
35
|
+
head = [data.length].pack("N")
|
36
|
+
@sock.write(head+data)
|
37
|
+
end
|
38
|
+
|
39
|
+
def read
|
40
|
+
head = @sock.read(4)
|
41
|
+
raise(Errno::ECONNRESET) if !head
|
42
|
+
length = head.unpack("N")[0]
|
43
|
+
data = @sock.read(length)
|
44
|
+
raise(Errno::ECONNRESET) if !data
|
45
|
+
Response.decode(data)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
## Generated from msg.proto for server
|
2
|
+
require "beefcake"
|
3
|
+
|
4
|
+
module Fraggle
|
5
|
+
module Block
|
6
|
+
|
7
|
+
class Request
|
8
|
+
include Beefcake::Message
|
9
|
+
|
10
|
+
module Verb
|
11
|
+
GET = 1
|
12
|
+
SET = 2
|
13
|
+
DEL = 3
|
14
|
+
REV = 5
|
15
|
+
WAIT = 6
|
16
|
+
NOP = 7
|
17
|
+
WALK = 9
|
18
|
+
GETDIR = 14
|
19
|
+
STAT = 16
|
20
|
+
end
|
21
|
+
|
22
|
+
optional :tag, :int32, 1
|
23
|
+
optional :verb, Request::Verb, 2
|
24
|
+
optional :path, :string, 4
|
25
|
+
optional :value, :bytes, 5
|
26
|
+
optional :other_tag, :int32, 6
|
27
|
+
optional :offset, :int32, 7
|
28
|
+
optional :rev, :int64, 9
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
class Response
|
33
|
+
include Beefcake::Message
|
34
|
+
|
35
|
+
module Err
|
36
|
+
OTHER = 127
|
37
|
+
TAG_IN_USE = 1
|
38
|
+
UNKNOWN_VERB = 2
|
39
|
+
READONLY = 3
|
40
|
+
TOO_LATE = 4
|
41
|
+
REV_MISMATCH = 5
|
42
|
+
BAD_PATH = 6
|
43
|
+
MISSING_ARG = 7
|
44
|
+
RANGE = 8
|
45
|
+
NOTDIR = 20
|
46
|
+
ISDIR = 21
|
47
|
+
NOENT = 22
|
48
|
+
end
|
49
|
+
|
50
|
+
optional :tag, :int32, 1
|
51
|
+
optional :flags, :int32, 2
|
52
|
+
optional :rev, :int64, 3
|
53
|
+
optional :path, :string, 5
|
54
|
+
optional :value, :bytes, 6
|
55
|
+
optional :len, :int32, 8
|
56
|
+
optional :err_code, Response::Err, 100
|
57
|
+
optional :err_detail, :string, 101
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Fraggle
|
2
|
+
module Block
|
3
|
+
class Response
|
4
|
+
SET = 4
|
5
|
+
DEL = 8
|
6
|
+
|
7
|
+
def set?
|
8
|
+
!!flags && ((flags & SET) > 0)
|
9
|
+
end
|
10
|
+
|
11
|
+
def del?
|
12
|
+
!!flags && ((flags & SET) > 0)
|
13
|
+
end
|
14
|
+
|
15
|
+
def missing?
|
16
|
+
rev == 0
|
17
|
+
end
|
18
|
+
|
19
|
+
def ok?
|
20
|
+
err_code.nil?
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fraggle-block-spanx
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Dylan Egan
|
9
|
+
- Blake Mizerany
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2011-08-05 00:00:00.000000000 +01:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: beefcake-spanx
|
18
|
+
requirement: &70115689406640 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ! '>='
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '0'
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *70115689406640
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: &70115689405900 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ! '>='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *70115689405900
|
38
|
+
description: A synchronous Ruby client for Doozer.
|
39
|
+
email:
|
40
|
+
- dylanegan@gmail.com
|
41
|
+
- blake.mizerany@gmail.com
|
42
|
+
executables:
|
43
|
+
- fraggle-block
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- .gitignore
|
48
|
+
- Gemfile
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- bin/fraggle-block
|
52
|
+
- examples/client.rb
|
53
|
+
- fraggle-block.gemspec
|
54
|
+
- lib/fraggle/block.rb
|
55
|
+
- lib/fraggle/block/client.rb
|
56
|
+
- lib/fraggle/block/connection.rb
|
57
|
+
- lib/fraggle/block/msg.pb.rb
|
58
|
+
- lib/fraggle/block/response.rb
|
59
|
+
- lib/fraggle/block/version.rb
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: https://github.com/dylanegan/fraggle-block
|
62
|
+
licenses: []
|
63
|
+
post_install_message:
|
64
|
+
rdoc_options: []
|
65
|
+
require_paths:
|
66
|
+
- lib
|
67
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
hash: 1375443715139952394
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
none: false
|
78
|
+
requirements:
|
79
|
+
- - ! '>='
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '0'
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
hash: 1375443715139952394
|
85
|
+
requirements: []
|
86
|
+
rubyforge_project: fraggle-block
|
87
|
+
rubygems_version: 1.6.2
|
88
|
+
signing_key:
|
89
|
+
specification_version: 3
|
90
|
+
summary: A synchronous Ruby client for Doozer.
|
91
|
+
test_files: []
|