alloc8 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +35 -7
- data/alloc8.gemspec +2 -1
- data/bin/alloc8 +46 -0
- data/lib/alloc8.rb +42 -21
- data/lib/alloc8/version.rb +1 -1
- data/spec/alloc8_spec.rb +23 -1
- metadata +26 -12
data/README.md
CHANGED
@@ -1,18 +1,46 @@
|
|
1
1
|
Simple distributed resource allocation using Redis.
|
2
2
|
|
3
|
+
To use resources:
|
3
4
|
<pre>
|
5
|
+
require 'rubygems'
|
4
6
|
require 'alloc8'
|
5
7
|
|
6
8
|
HOST = "my-redis"
|
7
9
|
PORT = 6379 # default Redis port
|
8
10
|
|
9
|
-
|
10
|
-
@allocator = Alloc8::Tor.new(HOST, PORT)
|
11
|
-
@allocator.create("worker", "worker1.my.org")
|
12
|
-
@allocator.create("worker", "worker2.my.org")
|
13
|
-
|
14
|
-
# to use them
|
11
|
+
puts "acquiring worker"
|
15
12
|
Alloc8::Tor.with_resource("worker", HOST, PORT) do |worker|
|
13
|
+
puts "about to do something with #{worker}"
|
16
14
|
# something
|
17
15
|
end
|
18
|
-
</pre>
|
16
|
+
</pre>
|
17
|
+
|
18
|
+
Command-line tool to set up resources:
|
19
|
+
<pre>
|
20
|
+
$ alloc8
|
21
|
+
Tasks:
|
22
|
+
alloc8 create CLASS RESOURCE # Create a resource of a specific class
|
23
|
+
alloc8 help [TASK] # Describe available tasks or one specific task
|
24
|
+
alloc8 list CLASS [-A] # List all instances (or just available) of a resource class
|
25
|
+
alloc8 purge CLASS # Delete all resources from a class
|
26
|
+
alloc8 reset CLASS # Release acquired resources for a class
|
27
|
+
|
28
|
+
Options:
|
29
|
+
-p, [--port=N] # Redis store port
|
30
|
+
# Default: 6379
|
31
|
+
[--db=N] # Redis store database number
|
32
|
+
-h, [--host=HOST] # Redis store hostname
|
33
|
+
# Default: localhost
|
34
|
+
|
35
|
+
$ export ALLOC8_HOST="my-redis"
|
36
|
+
$ alloc8 list worker
|
37
|
+
List entries for worker:
|
38
|
+
$ alloc8 create worker worker1.my.org
|
39
|
+
Added worker1.my.org to worker.
|
40
|
+
$ alloc8 create worker worker2.my.org
|
41
|
+
Added worker2.my.org to worker.
|
42
|
+
$ alloc8 list worker
|
43
|
+
List entries for worker:
|
44
|
+
worker1.my.org
|
45
|
+
worker2.my.org
|
46
|
+
</pre>
|
data/alloc8.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
21
|
s.require_paths = ["lib"]
|
22
22
|
|
23
|
-
s.add_runtime_dependency "redis", "
|
23
|
+
s.add_runtime_dependency "redis", ">= 2.0"
|
24
|
+
s.add_runtime_dependency "thor"
|
24
25
|
s.add_development_dependency "rspec", "~> 2.0"
|
25
26
|
end
|
data/bin/alloc8
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'thor'
|
4
|
+
require 'alloc8'
|
5
|
+
|
6
|
+
class Alloc8Cmd < Thor
|
7
|
+
|
8
|
+
class_option :host, :aliases => "-h", :type => :string, :default => (ENV["ALLOC8_HOST"] || "localhost"),
|
9
|
+
:desc => "Redis store hostname"
|
10
|
+
class_option :port, :aliases => "-p", :type => :numeric, :default => 6379, :desc => "Redis store port"
|
11
|
+
class_option :db, :type => :numeric, :desc => "Redis store database number"
|
12
|
+
|
13
|
+
desc "list CLASS [-A]", "List all instances (or just available) of a resource class"
|
14
|
+
method_option :available, :aliases => "-A", :type => :boolean, :desc => "List only the available (non-acquired) instances"
|
15
|
+
def list(klass)
|
16
|
+
allocator = Alloc8::Tor.new options[:host], options[:port], options[:db]
|
17
|
+
verb = options[:available] ? :available : :list
|
18
|
+
puts "#{verb.to_s.capitalize} entries for #{klass}:"
|
19
|
+
allocator.send(verb, klass).each do |res|
|
20
|
+
puts " #{res}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "create CLASS RESOURCE", "Create a resource of a specific class"
|
25
|
+
def create(klass, resource)
|
26
|
+
allocator = Alloc8::Tor.new options[:host], options[:port], options[:db]
|
27
|
+
allocator.create(klass, resource)
|
28
|
+
puts "Added #{resource} to #{klass}."
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "purge CLASS", "Delete all resources from a class"
|
32
|
+
def purge(klass)
|
33
|
+
allocator = Alloc8::Tor.new options[:host], options[:port], options[:db]
|
34
|
+
allocator.purge(klass)
|
35
|
+
puts "Purged all entries for #{klass}."
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "reset CLASS", "Release acquired resources for a class"
|
39
|
+
def reset(klass)
|
40
|
+
allocator = Alloc8::Tor.new options[:host], options[:port], options[:db]
|
41
|
+
allocator.reset(klass)
|
42
|
+
puts "Reset all acquired entries for #{klass}."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
Alloc8Cmd.start
|
data/lib/alloc8.rb
CHANGED
@@ -2,51 +2,72 @@ require 'redis'
|
|
2
2
|
|
3
3
|
module Alloc8
|
4
4
|
class Tor
|
5
|
-
# initialize connection to
|
5
|
+
# initialize connection to redis
|
6
6
|
def initialize(host, port, db=nil)
|
7
7
|
@redis = Redis.new(:host => host, :port => port)
|
8
8
|
@redis.select(db) if db
|
9
9
|
end
|
10
10
|
|
11
11
|
# create a resource in a class
|
12
|
-
def create(
|
13
|
-
if @redis.sadd(
|
14
|
-
@redis.lpush
|
12
|
+
def create(klass, resource)
|
13
|
+
if @redis.sadd(key(klass), resource.to_s)
|
14
|
+
@redis.lpush key(klass, :avail), resource.to_s
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
#
|
19
|
-
def
|
20
|
-
|
18
|
+
# list all resources in class
|
19
|
+
def list(klass)
|
20
|
+
@redis.smembers(key(klass))
|
21
|
+
end
|
22
|
+
|
23
|
+
# delete a resource class
|
24
|
+
def purge(klass)
|
25
|
+
nkeys = @redis.del key(klass, :avail), key(klass)
|
21
26
|
nkeys == 2 # true if purged all
|
22
27
|
end
|
23
28
|
|
24
29
|
# reset available items in resource class
|
25
|
-
def reset(
|
26
|
-
|
27
|
-
@redis.
|
28
|
-
|
30
|
+
def reset(klass)
|
31
|
+
akey = key(klass, :avail)
|
32
|
+
@redis.del akey
|
33
|
+
@redis.smembers(key(klass)).each do |resource|
|
34
|
+
@redis.lpush akey, resource.to_s
|
29
35
|
end
|
30
36
|
end
|
31
37
|
|
38
|
+
# list all available items in resource class
|
39
|
+
def available(klass)
|
40
|
+
akey = key(klass, :avail)
|
41
|
+
avail = []
|
42
|
+
@redis.llen(akey).times do |i|
|
43
|
+
avail << @redis.lindex(akey, i)
|
44
|
+
end
|
45
|
+
avail
|
46
|
+
end
|
47
|
+
|
32
48
|
# acquire next available resource
|
33
|
-
def acquire(
|
34
|
-
|
49
|
+
def acquire(klass, timeout = 0)
|
50
|
+
akey, res = @redis.brpop key(klass, :avail), timeout
|
35
51
|
res
|
36
52
|
end
|
37
53
|
|
38
54
|
# return resource
|
39
|
-
def return(
|
40
|
-
raise Exception if !@redis.sismember
|
41
|
-
@redis.lpush
|
55
|
+
def return(klass, resource)
|
56
|
+
raise Exception.new("Invalid resource #{resource} for class #{klass}") if !@redis.sismember key(klass), resource.to_s
|
57
|
+
@redis.lpush key(klass, :avail), resource.to_s
|
42
58
|
end
|
43
59
|
|
44
60
|
# block to allocate a resource
|
45
|
-
def self.with_resource(
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
61
|
+
def self.with_resource(klass, host, port, db=nil)
|
62
|
+
a = Alloc8::Tor.new host, port, db
|
63
|
+
res = a.acquire(klass)
|
64
|
+
yield res
|
65
|
+
a.return(klass, res)
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def key(klass, suffix = nil)
|
70
|
+
"resource:#{klass}" << (suffix ? suffix.to_s : "")
|
50
71
|
end
|
51
72
|
end
|
52
73
|
end
|
data/lib/alloc8/version.rb
CHANGED
data/spec/alloc8_spec.rb
CHANGED
@@ -19,6 +19,11 @@ describe Alloc8 do
|
|
19
19
|
context "having a single resource" do
|
20
20
|
before { @allocator.create KIND, "a" }
|
21
21
|
|
22
|
+
it "can return a list of resources, available resources" do
|
23
|
+
@allocator.list(KIND).should eq(["a"])
|
24
|
+
@allocator.available(KIND).should eq(["a"])
|
25
|
+
end
|
26
|
+
|
22
27
|
it "can't allocate it again" do
|
23
28
|
@allocator.create(KIND, "a").should == nil
|
24
29
|
end
|
@@ -30,11 +35,21 @@ describe Alloc8 do
|
|
30
35
|
|
31
36
|
it "can purge resource class" do
|
32
37
|
@allocator.purge(KIND).should == true
|
38
|
+
@allocator.list(KIND).should eq([])
|
39
|
+
@allocator.available(KIND).should eq([])
|
33
40
|
end
|
34
41
|
|
35
42
|
it "can acquire and return a resource" do
|
36
43
|
@allocator.acquire(KIND).should == "a"
|
44
|
+
@allocator.available(KIND).should eq([])
|
45
|
+
|
37
46
|
@allocator.return(KIND, "a").should == 1
|
47
|
+
@allocator.list(KIND).should eq(["a"])
|
48
|
+
@allocator.available(KIND).should eq(["a"])
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can't return an invalid resource" do
|
52
|
+
lambda { @allocator.return(KIND, "foo") }.should raise_error
|
38
53
|
end
|
39
54
|
|
40
55
|
it "can acquire with a block" do
|
@@ -52,6 +67,13 @@ describe Alloc8 do
|
|
52
67
|
context "having multiple resources" do
|
53
68
|
before { ["a", "b", "c"].each {|r| @allocator.create KIND, r} }
|
54
69
|
|
70
|
+
it "can return a list of resources, available resources" do
|
71
|
+
@allocator.list(KIND).should include("a", "b", "c")
|
72
|
+
@allocator.list(KIND).should have(3).items
|
73
|
+
@allocator.available(KIND).should include("a", "b", "c")
|
74
|
+
@allocator.available(KIND).should have(3).items
|
75
|
+
end
|
76
|
+
|
55
77
|
it "can purge resource class" do
|
56
78
|
@allocator.purge(KIND).should == true
|
57
79
|
end
|
@@ -66,4 +88,4 @@ describe Alloc8 do
|
|
66
88
|
end
|
67
89
|
end
|
68
90
|
|
69
|
-
end
|
91
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alloc8
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ariel Salomon
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-05-
|
18
|
+
date: 2011-05-22 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -24,20 +24,33 @@ dependencies:
|
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
hash:
|
29
|
+
hash: 3
|
30
30
|
segments:
|
31
31
|
- 2
|
32
|
-
- 2
|
33
32
|
- 0
|
34
|
-
version: 2.
|
33
|
+
version: "2.0"
|
35
34
|
type: :runtime
|
36
35
|
version_requirements: *id001
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
37
|
+
name: thor
|
39
38
|
prerelease: false
|
40
39
|
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 3
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: rspec
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
54
|
none: false
|
42
55
|
requirements:
|
43
56
|
- - ~>
|
@@ -48,14 +61,14 @@ dependencies:
|
|
48
61
|
- 0
|
49
62
|
version: "2.0"
|
50
63
|
type: :development
|
51
|
-
version_requirements: *
|
64
|
+
version_requirements: *id003
|
52
65
|
description: |-
|
53
66
|
Simple distributed resource allocation using Redis.
|
54
67
|
Alloc8::Tor.with_resource do ...
|
55
68
|
email:
|
56
69
|
- ariel@oscillatory.org
|
57
|
-
executables:
|
58
|
-
|
70
|
+
executables:
|
71
|
+
- alloc8
|
59
72
|
extensions: []
|
60
73
|
|
61
74
|
extra_rdoc_files: []
|
@@ -66,6 +79,7 @@ files:
|
|
66
79
|
- README.md
|
67
80
|
- Rakefile
|
68
81
|
- alloc8.gemspec
|
82
|
+
- bin/alloc8
|
69
83
|
- lib/alloc8.rb
|
70
84
|
- lib/alloc8/version.rb
|
71
85
|
- spec/alloc8_spec.rb
|