grotesque 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create use ruby-1.9.3-p194@grotesque
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in grotesque.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Nathan Sutton
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,35 @@
1
+ # Grotesque
2
+
3
+ To understand this library you'll want to first have a look at the dictionary definition of [grotesque](http://dictionary.reference.com/browse/grotesque), then understand that this is bizarre, fantastically ugly, and absurd.
4
+
5
+ This library will provide tooling to use Apache ZooKeeper like Redis. It will provide a server which you can run alongside your ZooKeeper instances that will provide an API to clients. Via this API you will be able to perform atomic modifications to data structures stored in ZooKeeper. I may even provide a server-less version, who knows.
6
+
7
+ The goal here is to provide many of the data structures that Redis provides but in an extremely fault-tolerant way. This may be far too slow for some purposes, but I guess we'll see. I plan to port the server to golang if I can make it work well enough.
8
+
9
+ This may be my worst idea yet.
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ gem 'grotesque'
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install grotesque
24
+
25
+ ## Usage
26
+
27
+ Don't use this yet, but see the specs for how you might use it in the future if it works out at all.
28
+
29
+ ## Contributing
30
+
31
+ 1. Fork it
32
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
33
+ 3. Commit your changes with specs (`git commit -am 'Added some feature'`)
34
+ 4. Push to the branch (`git push origin my-new-feature`)
35
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/grotesque/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Nathan Sutton"]
6
+ gem.email = ["nathan.sutton@gmail.com"]
7
+ gem.description = %q{Use ZooKeeper like Redis. A grotesque.}
8
+ gem.summary = %q{A library that makes is possible to use ZooKeeper like Redis. A grotesque.}
9
+
10
+ gem.files = `git ls-files`.split($\)
11
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
12
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
13
+ gem.name = "grotesque"
14
+ gem.require_paths = ["lib"]
15
+ gem.version = Grotesque::VERSION
16
+ gem.add_dependency "zk"
17
+ gem.add_dependency "msgpack-rpc"
18
+ gem.add_development_dependency "rspec"
19
+ end
@@ -0,0 +1,7 @@
1
+ require "grotesque/version"
2
+ require "grotesque/server"
3
+ require "grotesque/client"
4
+
5
+ module Grotesque
6
+ # Your code goes here...
7
+ end
@@ -0,0 +1,5 @@
1
+ module Grotesque
2
+ class Client
3
+
4
+ end
5
+ end
@@ -0,0 +1,92 @@
1
+ require "zk"
2
+ require "msgpack/rpc"
3
+
4
+ module Grotesque
5
+ class Server
6
+
7
+ attr_reader :zk
8
+
9
+ def self.run(options)
10
+ new(options).run
11
+ end
12
+
13
+ def initialize(options={})
14
+ @options = options.clone
15
+ @port = options.delete(:port) || 9090
16
+ @host = options.delete(:host) || "0.0.0.0"
17
+ @zk_port = options.delete(:zk_port) || 2181
18
+ @zk_host = options.delete(:zk_host) || "localhost"
19
+ @zk_chroot = options.delete(:zk_chroot) || "grotesque"
20
+ @zk = ZK.new("#{@zk_host}:#{@zk_port}/#{@zk_chroot}")
21
+ end
22
+
23
+ def run
24
+ server = MessagePack::RPC::Server.new
25
+ server.listen(@host, @port, self, ["get", "set"])
26
+ server.run
27
+ end
28
+
29
+ def get(key)
30
+ key = normalize_key(key)
31
+ value = nil
32
+
33
+ @zk.with_lock(key, :mode => :shared) do
34
+ begin
35
+ value, _ = @zk.get(key)
36
+ rescue ZK::Exceptions::NoNode
37
+ end
38
+ end
39
+
40
+ value
41
+ end
42
+
43
+ def set(key, value)
44
+ key = normalize_key(key)
45
+
46
+ @zk.with_lock(key, :mode => :exclusive) do
47
+ @zk.create(key, value, :or => :set)
48
+ end
49
+
50
+ true
51
+ end
52
+
53
+ def del(*keys)
54
+ deleted = 0
55
+
56
+ keys.each do |key|
57
+ key = normalize_key(key)
58
+
59
+ @zk.with_lock(key, :mode => :exclusive) do
60
+ begin
61
+ @zk.delete(key)
62
+ deleted += 1
63
+ rescue ZK::Exceptions::NoNode
64
+ end
65
+ end
66
+ end
67
+
68
+ deleted
69
+ end
70
+
71
+ def flushall
72
+ flushdb
73
+ end
74
+
75
+ def flushdb
76
+ @zk.rm_rf("/")
77
+ @zk.create("/")
78
+ true
79
+ end
80
+
81
+
82
+ protected
83
+
84
+ def normalize_key(key)
85
+ raise ArgumentError, %{key "#{key.inspect}" must be a string} unless key.is_a?(String)
86
+ raise ArgumentError, %{key "#{key.inspect}" contains an invalid character ("/")} if key.include?("/")
87
+
88
+ "/#{key}"
89
+ end
90
+
91
+ end
92
+ end
@@ -0,0 +1,3 @@
1
+ module Grotesque
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,5 @@
1
+ require "spec_helper"
2
+
3
+ describe Grotesque::Client do
4
+
5
+ end
@@ -0,0 +1,61 @@
1
+ describe Grotesque::Server do
2
+ let(:server) { Grotesque::Server.new(:zk_chroot => "grotesque_test") }
3
+ let(:zk) { server.zk }
4
+
5
+ before do
6
+ server.flushall
7
+ end
8
+
9
+ context "when setting values" do
10
+ it "should set a value for a given key" do
11
+ server.set("foo", "bar")
12
+ zk.get("/foo")[0].should == "bar"
13
+ end
14
+
15
+ it "should overwrite a value for a given key" do
16
+ server.set("foo", "bar")
17
+ server.set("foo", "baz")
18
+ zk.get("/foo")[0].should == "baz"
19
+ end
20
+
21
+ it "should return true" do
22
+ server.set("foo", "bar").should be_true
23
+ end
24
+ end
25
+
26
+ context "when getting values" do
27
+ it "should return nil when a value hasn't been set for the given key" do
28
+ server.get("foo").should be_nil
29
+ end
30
+
31
+ it "should return a value when it has been set for the given key" do
32
+ zk.create("/foo", "bar", :or => :set)
33
+ server.get("foo").should == "bar"
34
+ end
35
+ end
36
+
37
+ context "when deleting values" do
38
+ it "should return zero when deleting a non-existant key" do
39
+ server.del("foo").should == 0
40
+ end
41
+
42
+ it "should return 1 when deleting a key that exists" do
43
+ zk.create("/foo", "bar", :or => :set)
44
+ server.del("foo").should == 1
45
+ end
46
+
47
+ it "should return the number of keys that were deleted when" do
48
+ zk.create("/foo", "bar", :or => :set)
49
+ zk.create("/bar", "baz", :or => :set)
50
+ zk.create("/bonk", "bing", :or => :set)
51
+ server.del("foo", "bar", "blip", "bloop").should == 2
52
+ end
53
+
54
+ it "should delete the values" do
55
+ zk.create("/foo", "bar", :or => :set)
56
+ server.del("foo").should == 1
57
+ expect{ zk.get("/foo") }.to raise_error(ZK::Exceptions::NoNode)
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,3 @@
1
+ describe Grotesque do
2
+
3
+ end
@@ -0,0 +1,16 @@
1
+ require "grotesque"
2
+ require "rubygems"
3
+ require "bundler"
4
+ Bundler.setup
5
+
6
+ # This file was generated by the `rspec --init` command. Conventionally, all
7
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
8
+ # Require this file using `require "spec_helper.rb"` to ensure that it is only
9
+ # loaded once.
10
+ #
11
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grotesque
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Nathan Sutton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: zk
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: msgpack-rpc
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Use ZooKeeper like Redis. A grotesque.
63
+ email:
64
+ - nathan.sutton@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rspec
71
+ - .rvmrc
72
+ - Gemfile
73
+ - LICENSE
74
+ - README.md
75
+ - Rakefile
76
+ - grotesque.gemspec
77
+ - lib/grotesque.rb
78
+ - lib/grotesque/client.rb
79
+ - lib/grotesque/server.rb
80
+ - lib/grotesque/version.rb
81
+ - spec/grotesque/client_spec.rb
82
+ - spec/grotesque/server_spec.rb
83
+ - spec/grotesque_spec.rb
84
+ - spec/spec_helper.rb
85
+ homepage:
86
+ licenses: []
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ! '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ requirements: []
104
+ rubyforge_project:
105
+ rubygems_version: 1.8.24
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: A library that makes is possible to use ZooKeeper like Redis. A grotesque.
109
+ test_files:
110
+ - spec/grotesque/client_spec.rb
111
+ - spec/grotesque/server_spec.rb
112
+ - spec/grotesque_spec.rb
113
+ - spec/spec_helper.rb