riaq 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/LICENSE +19 -0
- data/README.md +91 -0
- data/Rakefile +5 -0
- data/lib/riaq.rb +92 -0
- data/riaq.gemspec +22 -0
- data/test/riaq_test.rb +85 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
ZWI0ODkwNGRhMWFjNjRhNzM3OGJiMTRjOWNjZGZlM2FhYTY2NTVkYg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OWQ2MjZiYTcwZWEyMjk2OGY3NmM2NjlhZGNmMTU1M2ZhZTYzZmUyNg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
M2YwNjgwMDc3NDM5NWUxOGNhZWQ3ODU3NGUwMWE5OTFkZTQyZGFkMmRkYTNl
|
10
|
+
NmExMDM4NmI3YTJiMzE0OWU1OGZmYzZiYThlOTU4YmZmYmZiZjg5MjA3YjAx
|
11
|
+
ZGZhNjYyYjgxYTNjNmQxNzZkNmRjNTc4YjdjOGZkNTkxM2U5Zjc=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
MGE3YWY4OGQyMGEyNzg4MTYzYTc3OWZkNGQwNWIxNjEzYTA5ZmQ2NmQ4MGQx
|
14
|
+
N2E2MTg4YjA2OGM5OGUwZmIwY2VmODJhZGYzMTE2NGJiNjFmODM5YzNmOTdl
|
15
|
+
YjJkMGMzZWNjMmY4YjVlODI5M2MzN2MwNjNkYjk0MTFjYWM0YmM=
|
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2014 Matías Flores
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# Riaq
|
2
|
+
|
3
|
+
Experimental attempt of providing Riak based queues and workers,
|
4
|
+
heavily inspired by [Ost](https://github.com/soveran/ost).
|
5
|
+
|
6
|
+
Due to Riak's distributed capabilities and lack of atomic operations,
|
7
|
+
as soon as you launch more than one worker there's no guarantee that
|
8
|
+
each item added to the queue will be processed just once. If you can't
|
9
|
+
live with this limitation, then this tool is not for you.
|
10
|
+
|
11
|
+
## Description
|
12
|
+
|
13
|
+
*Riaq* makes it easy to enqueue object ids and process them with
|
14
|
+
workers.
|
15
|
+
|
16
|
+
Say you want to process video uploads. In your application you will
|
17
|
+
have something like this:
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
Riaq[:videos_to_process].push(@video.id)
|
21
|
+
```
|
22
|
+
|
23
|
+
Then, you will have a worker that will look like this:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require "riaq"
|
27
|
+
|
28
|
+
Riaq[:videos_to_process].each do |id|
|
29
|
+
# Do something with it!
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
*Riaq* connects to Riak automatically with the default options.
|
36
|
+
|
37
|
+
You can customize the connection by calling `connect`.
|
38
|
+
|
39
|
+
Then you only need to refer to a queue for it to pop into existence:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
Riaq[:rss_feeds] << @feed.id
|
43
|
+
```
|
44
|
+
|
45
|
+
A worker is a Ruby file with this basic code:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require "riaq"
|
49
|
+
|
50
|
+
Riaq[:rss_feeds].each do |id|
|
51
|
+
# ...
|
52
|
+
end
|
53
|
+
```
|
54
|
+
|
55
|
+
It will pop items from the queue as soon as they become available.
|
56
|
+
|
57
|
+
Note that in these examples we are pushing numbers to the queue. As
|
58
|
+
we have unlimited queues, each queue should be specialized and the
|
59
|
+
workers must be smart enough to know what to do with the numbers they
|
60
|
+
pop.
|
61
|
+
|
62
|
+
### Available methods
|
63
|
+
|
64
|
+
`Riaq.connect`: configure the connection to Riak. It accepts
|
65
|
+
the same options as [the Riak Ruby client](https://github.com/basho/riak-ruby-client).
|
66
|
+
|
67
|
+
`Riaq.stop`: halt processing for all queues.
|
68
|
+
|
69
|
+
`Riaq[:example].push item`, `Riaq[:some_queue] << item`: add `item` to
|
70
|
+
the `:example` queue.
|
71
|
+
|
72
|
+
`Riaq[:example].each { |item| ... }`: consume `item` from the `:example` queue.
|
73
|
+
|
74
|
+
`Riaq[:example].stop`: halt processing for the `example` queue.
|
75
|
+
|
76
|
+
## Priorities
|
77
|
+
|
78
|
+
There's no concept of priorities, as each queue is specialized and you
|
79
|
+
can create as many as you want. For example, nothing prevents the
|
80
|
+
creation of the `:example_high_priority` or the
|
81
|
+
`:example_low_priority` queues.
|
82
|
+
|
83
|
+
## Installation
|
84
|
+
|
85
|
+
$ gem install riaq
|
86
|
+
|
87
|
+
## License
|
88
|
+
|
89
|
+
Distributed under the terms of the MIT license.
|
90
|
+
See bundled [LICENSE](https://github.com/matflores/riaq/blob/master/LICENSE)
|
91
|
+
file for more info.
|
data/Rakefile
ADDED
data/lib/riaq.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "riak"
|
2
|
+
|
3
|
+
module Riaq
|
4
|
+
PENDING = 0
|
5
|
+
PROCESSING = 1
|
6
|
+
|
7
|
+
class Queue
|
8
|
+
attr :bucket
|
9
|
+
|
10
|
+
def initialize(name)
|
11
|
+
@bucket = riak.bucket("riaq:#{name}")
|
12
|
+
end
|
13
|
+
|
14
|
+
def push(value)
|
15
|
+
item = @bucket.new(Time.now.to_f)
|
16
|
+
item.content_type = "text/plain"
|
17
|
+
item.data = value
|
18
|
+
item.indexes = { status_int: PENDING }
|
19
|
+
item.store
|
20
|
+
end
|
21
|
+
|
22
|
+
def each(&block)
|
23
|
+
@stopping = false
|
24
|
+
|
25
|
+
loop do
|
26
|
+
break if @stopping
|
27
|
+
|
28
|
+
key = bucket.get_index("status_int", PENDING, max_results: 1).first
|
29
|
+
|
30
|
+
next unless key
|
31
|
+
|
32
|
+
item = @bucket.get(key)
|
33
|
+
item.indexes = { status_int: PROCESSING }
|
34
|
+
item.store
|
35
|
+
|
36
|
+
block.call(item.data)
|
37
|
+
|
38
|
+
item.delete
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def flush
|
43
|
+
bucket.get_index("$bucket", @bucket.name).each do |key|
|
44
|
+
@bucket.delete(key)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def stop
|
49
|
+
@stopping = true
|
50
|
+
end
|
51
|
+
|
52
|
+
def items
|
53
|
+
Riak::MapReduce.new(riak).index(@bucket.name, "status_int", PENDING).map("Riak.mapValues", keep: true).run
|
54
|
+
end
|
55
|
+
|
56
|
+
def size
|
57
|
+
bucket.get_index("status_int", PENDING).size
|
58
|
+
end
|
59
|
+
|
60
|
+
def empty?
|
61
|
+
size == 0
|
62
|
+
end
|
63
|
+
|
64
|
+
alias << push
|
65
|
+
|
66
|
+
def riak
|
67
|
+
@riak ||= Riak::Client.new(Riaq.options)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
@queues = Hash.new do |hash, key|
|
72
|
+
hash[key] = Queue.new(key)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.[](queue)
|
76
|
+
@queues[queue]
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.stop
|
80
|
+
@queues.each { |_, queue| queue.stop }
|
81
|
+
end
|
82
|
+
|
83
|
+
@options = nil
|
84
|
+
|
85
|
+
def self.connect(options = {})
|
86
|
+
@options = options
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.options
|
90
|
+
@options || {}
|
91
|
+
end
|
92
|
+
end
|
data/riaq.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "riaq"
|
3
|
+
s.version = "0.0.1"
|
4
|
+
s.summary = "Riak based queues and workers, inspired by Ost."
|
5
|
+
s.description = "Riaq lets you manage queues and workers with Riak."
|
6
|
+
s.authors = ["Matías Flores"]
|
7
|
+
s.email = ["flores.matias@gmail.com"]
|
8
|
+
s.homepage = "http://github.com/soveran/ost"
|
9
|
+
s.license = "MIT"
|
10
|
+
|
11
|
+
s.files = Dir[
|
12
|
+
"LICENSE",
|
13
|
+
"README.md",
|
14
|
+
"Rakefile",
|
15
|
+
"lib/**/*.rb",
|
16
|
+
"*.gemspec",
|
17
|
+
"test/*.*"
|
18
|
+
]
|
19
|
+
|
20
|
+
s.add_dependency "riak-client", "~> 1.4.3"
|
21
|
+
s.add_development_dependency "protest", "~> 0.5.1"
|
22
|
+
end
|
data/test/riaq_test.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require "protest"
|
2
|
+
require_relative "../lib/riaq"
|
3
|
+
|
4
|
+
Protest.context "Riaq" do
|
5
|
+
setup do
|
6
|
+
Riaq[:test].flush
|
7
|
+
end
|
8
|
+
|
9
|
+
test "access queued items" do
|
10
|
+
push "1"
|
11
|
+
|
12
|
+
assert_equal ["1"], Riaq[:test].items
|
13
|
+
end
|
14
|
+
|
15
|
+
test "query the number of queued items" do
|
16
|
+
push "1"
|
17
|
+
|
18
|
+
assert_equal 1, Riaq[:test].size
|
19
|
+
end
|
20
|
+
|
21
|
+
test "check queue emptiness" do
|
22
|
+
assert Riaq[:test].empty?
|
23
|
+
|
24
|
+
push "1"
|
25
|
+
|
26
|
+
assert !Riaq[:test].empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
test "process items from the queue in order" do |redis|
|
30
|
+
%w(1 2 3).each { |i| push i }
|
31
|
+
|
32
|
+
results = []
|
33
|
+
|
34
|
+
process do |item|
|
35
|
+
results << item
|
36
|
+
end
|
37
|
+
|
38
|
+
assert Riaq[:test].empty?
|
39
|
+
assert_equal ["1", "2", "3"], results
|
40
|
+
end
|
41
|
+
|
42
|
+
test "halt processing a queue" do
|
43
|
+
Thread.new do
|
44
|
+
sleep 0.5
|
45
|
+
Riaq[:always_empty].stop
|
46
|
+
end
|
47
|
+
|
48
|
+
Riaq[:always_empty].each { }
|
49
|
+
|
50
|
+
assert true
|
51
|
+
end
|
52
|
+
|
53
|
+
test "halt processing all queues" do
|
54
|
+
Thread.new do
|
55
|
+
sleep 0.5
|
56
|
+
Riaq.stop
|
57
|
+
end
|
58
|
+
|
59
|
+
t1 = Thread.new { Riaq[:always_empty].each { } }
|
60
|
+
t2 = Thread.new { Riaq[:always_empty_too].each { } }
|
61
|
+
|
62
|
+
t1.join
|
63
|
+
t2.join
|
64
|
+
|
65
|
+
assert true
|
66
|
+
end
|
67
|
+
|
68
|
+
def push(id)
|
69
|
+
Riaq[:test].push(id)
|
70
|
+
end
|
71
|
+
|
72
|
+
def process(&job)
|
73
|
+
thread = Thread.new do
|
74
|
+
Riaq[:test].each do |item|
|
75
|
+
begin
|
76
|
+
yield(item)
|
77
|
+
ensure
|
78
|
+
thread.kill if Riaq[:test].empty?
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
thread.join
|
84
|
+
end
|
85
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: riaq
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matías Flores
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: riak-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.4.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: protest
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.5.1
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.5.1
|
41
|
+
description: Riaq lets you manage queues and workers with Riak.
|
42
|
+
email:
|
43
|
+
- flores.matias@gmail.com
|
44
|
+
executables: []
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- LICENSE
|
49
|
+
- README.md
|
50
|
+
- Rakefile
|
51
|
+
- lib/riaq.rb
|
52
|
+
- riaq.gemspec
|
53
|
+
- test/riaq_test.rb
|
54
|
+
homepage: http://github.com/soveran/ost
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.0.3
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Riak based queues and workers, inspired by Ost.
|
78
|
+
test_files: []
|
79
|
+
has_rdoc:
|