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 ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ *.swp
3
+ .bundle
4
+ Gemfile.lock
5
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fraggle-block.gemspec
4
+ gemspec
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
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), "../lib"))
4
+ require "fraggle/block"
5
+ require "irb"
6
+
7
+ @client = Fraggle::Block.connect
8
+ IRB.start
@@ -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
@@ -0,0 +1,5 @@
1
+ module Fraggle
2
+ module Block
3
+ VERSION = "0.2.1"
4
+ end
5
+ 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: []