alephant-sequencer 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Guardfile +6 -0
- data/lib/alephant/sequencer/sequence_table.rb +30 -8
- data/lib/alephant/sequencer/sequencer.rb +28 -10
- data/lib/alephant/sequencer/version.rb +1 -1
- data/spec/sequencer_spec.rb +17 -3
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f3a700631c4ac5a7dcbb393c5b646c94ff570507
|
4
|
+
data.tar.gz: 231923e71aa7e8f0d4af03e5f3088b14d8c365d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6ee44b240e0007b839b23069601ace6a2221991f12ca560cdc6ca6c372c9ab20db526f7545a06a56ff337a433fe6fd44cce7b3c8d1a91a03ca26d1e9513104bf
|
7
|
+
data.tar.gz: a34a2e07fe1b5184ca238a385e29dbbc17a90bc99de6251bffd7a37952500e6549bbe3c1431dc3e153d1fedb2f6bf356ce23d335720d2df674845d96e6daa971
|
data/Guardfile
ADDED
@@ -2,9 +2,13 @@ require 'aws-sdk'
|
|
2
2
|
require 'thread'
|
3
3
|
require 'timeout'
|
4
4
|
|
5
|
+
require 'alephant/logger'
|
6
|
+
|
5
7
|
module Alephant
|
6
8
|
module Sequencer
|
7
9
|
class SequenceTable
|
10
|
+
include ::Alephant::Logger
|
11
|
+
|
8
12
|
attr_reader :table_name
|
9
13
|
|
10
14
|
TIMEOUT = 120
|
@@ -37,19 +41,25 @@ module Alephant
|
|
37
41
|
@table ||= @dynamo_db.tables[@table_name]
|
38
42
|
end
|
39
43
|
|
44
|
+
def sequence_exists(ident)
|
45
|
+
!(table.items.where(:key => ident) == 0)
|
46
|
+
end
|
47
|
+
|
40
48
|
def sequence_for(ident)
|
41
49
|
rows = batch_get_value_for(ident)
|
42
|
-
rows.count >= 1 ? rows.first['value'].to_i :
|
50
|
+
rows.count >= 1 ? rows.first['value'].to_i : nil
|
43
51
|
end
|
44
52
|
|
45
|
-
def set_sequence_for(ident,value)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
53
|
+
def set_sequence_for(ident, value, last_seen_check = nil)
|
54
|
+
begin
|
55
|
+
@mutex.synchronize do
|
56
|
+
table.items.put(
|
57
|
+
{:key => ident, :value => value },
|
58
|
+
put_condition(last_seen_check)
|
51
59
|
)
|
52
|
-
|
60
|
+
end
|
61
|
+
rescue AWS::DynamoDB::Errors::ConditionalCheckFailedException => e
|
62
|
+
logger.warn("SequenceTable#set_sequence_for: #{e.message}")
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
@@ -58,10 +68,22 @@ module Alephant
|
|
58
68
|
end
|
59
69
|
|
60
70
|
private
|
71
|
+
def put_condition(last_seen_check)
|
72
|
+
last_seen_check.nil? ? unless_exists(:key) : if_value(last_seen_check)
|
73
|
+
end
|
74
|
+
|
61
75
|
def batch_get_value_for(ident)
|
62
76
|
table.batch_get(['value'],[ident],batch_get_opts)
|
63
77
|
end
|
64
78
|
|
79
|
+
def unless_exists(key)
|
80
|
+
{ :unless_exists => key }
|
81
|
+
end
|
82
|
+
|
83
|
+
def if_value(value)
|
84
|
+
{ :if => { :value => value.to_i } }
|
85
|
+
end
|
86
|
+
|
65
87
|
def batch_get_opts
|
66
88
|
{ :consistent_read => true }
|
67
89
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'jsonpath'
|
2
|
+
|
2
3
|
require 'alephant/logger'
|
3
4
|
|
4
5
|
module Alephant
|
@@ -8,28 +9,45 @@ module Alephant
|
|
8
9
|
attr_reader :ident, :jsonpath
|
9
10
|
|
10
11
|
def initialize(sequence_table, id, sequence_path)
|
11
|
-
@mutex = Mutex.new
|
12
12
|
@sequence_table = sequence_table
|
13
|
+
@sequence_table.create
|
14
|
+
|
15
|
+
@exists = exists?
|
13
16
|
@jsonpath = sequence_path
|
14
17
|
@ident = id
|
15
|
-
|
16
|
-
@sequence_table.create
|
17
18
|
end
|
18
19
|
|
19
20
|
def sequential?(msg)
|
20
|
-
get_last_seen < sequence_id_from(msg)
|
21
|
+
(get_last_seen || 0) < sequence_id_from(msg)
|
22
|
+
end
|
23
|
+
|
24
|
+
def exists?
|
25
|
+
@exists || @sequence_table.sequence_exists(ident)
|
26
|
+
end
|
27
|
+
|
28
|
+
def sequence(msg, &block)
|
29
|
+
last_seen_id = get_last_seen
|
30
|
+
block.call(msg)
|
31
|
+
|
32
|
+
if sequential?(msg)
|
33
|
+
set_last_seen(msg, last_seen_id)
|
34
|
+
end
|
21
35
|
end
|
22
36
|
|
23
37
|
def delete!
|
24
|
-
logger.info("Sequencer
|
38
|
+
logger.info("Sequencer#delete!: #{ident}")
|
39
|
+
@exists = false
|
25
40
|
@sequence_table.delete_item!(ident)
|
26
41
|
end
|
27
42
|
|
28
|
-
def set_last_seen(msg)
|
29
|
-
|
30
|
-
logger.info("Sequencer
|
43
|
+
def set_last_seen(msg, last_seen_check = nil)
|
44
|
+
seen_id = sequence_id_from(msg)
|
45
|
+
logger.info("Sequencer#set_last_seen: #{seen_id}")
|
31
46
|
|
32
|
-
@sequence_table.set_sequence_for(
|
47
|
+
@sequence_table.set_sequence_for(
|
48
|
+
ident, seen_id,
|
49
|
+
(exists? ? last_seen_check : nil)
|
50
|
+
)
|
33
51
|
end
|
34
52
|
|
35
53
|
def get_last_seen
|
@@ -37,7 +55,7 @@ module Alephant
|
|
37
55
|
end
|
38
56
|
|
39
57
|
def sequence_id_from(msg)
|
40
|
-
JsonPath.on(msg.body, jsonpath).first
|
58
|
+
JsonPath.on(msg.body, jsonpath).first.to_i
|
41
59
|
end
|
42
60
|
end
|
43
61
|
end
|
data/spec/sequencer_spec.rb
CHANGED
@@ -14,17 +14,28 @@ describe Alephant::Sequencer do
|
|
14
14
|
describe Alephant::Sequencer::Sequencer do
|
15
15
|
let(:data) { double() }
|
16
16
|
let(:last_seen) { 42 }
|
17
|
-
|
18
|
-
|
17
|
+
|
18
|
+
def sequence_table
|
19
|
+
table = double()
|
20
|
+
table.stub(:create)
|
21
|
+
table.stub(:sequence_exists)
|
22
|
+
table.stub(:sequence_for)
|
23
|
+
table.stub(:set_sequence_for)
|
24
|
+
|
25
|
+
table
|
26
|
+
end
|
19
27
|
|
20
28
|
describe "#initialize(opts, id)" do
|
21
29
|
it "sets @jsonpath, @ident" do
|
30
|
+
subject = Alephant::Sequencer::Sequencer.new(sequence_table, ident, jsonpath)
|
31
|
+
|
22
32
|
expect(subject.jsonpath).to eq(jsonpath)
|
23
33
|
expect(subject.ident).to eq(ident)
|
24
34
|
end
|
25
35
|
|
26
36
|
it "calls create on sequence_table" do
|
27
37
|
table = double()
|
38
|
+
table.stub(:sequence_exists)
|
28
39
|
table.should_receive(:create)
|
29
40
|
|
30
41
|
Alephant::Sequencer::Sequencer.new(table, ident, jsonpath)
|
@@ -34,6 +45,7 @@ describe Alephant::Sequencer do
|
|
34
45
|
describe "#get_last_seen" do
|
35
46
|
it "returns sequence_table.sequence_for(ident)" do
|
36
47
|
table = double()
|
48
|
+
table.stub(:sequence_exists)
|
37
49
|
table.stub(:create)
|
38
50
|
table.should_receive(:sequence_for).with(ident).and_return(:expected_value)
|
39
51
|
|
@@ -50,8 +62,10 @@ describe Alephant::Sequencer do
|
|
50
62
|
|
51
63
|
it "calls set_sequence_for(ident, last_seen)" do
|
52
64
|
table = double()
|
65
|
+
table.stub(:sequence_exists)
|
53
66
|
table.stub(:create)
|
54
|
-
table.
|
67
|
+
table.stub(:sequence_for)
|
68
|
+
table.should_receive(:set_sequence_for).with(ident, last_seen, nil)
|
55
69
|
|
56
70
|
Alephant::Sequencer::Sequencer.new(table, ident, jsonpath).set_last_seen(data)
|
57
71
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alephant-sequencer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Kenny
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -188,6 +188,7 @@ files:
|
|
188
188
|
- .gitignore
|
189
189
|
- .travis.yml
|
190
190
|
- Gemfile
|
191
|
+
- Guardfile
|
191
192
|
- LICENSE.txt
|
192
193
|
- README.md
|
193
194
|
- Rakefile
|