alloc8 0.0.1 → 0.0.2
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/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
|