alephant-sequencer 0.0.4 → 0.0.5
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.
- 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
|