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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c9469dfac1eb96f8c9386bf691836cf8f3017f59
4
- data.tar.gz: c97554d0a0b758413c9024f4ee4d2fd5f9167faf
3
+ metadata.gz: f3a700631c4ac5a7dcbb393c5b646c94ff570507
4
+ data.tar.gz: 231923e71aa7e8f0d4af03e5f3088b14d8c365d1
5
5
  SHA512:
6
- metadata.gz: 10ef0ab3836211d83e502690620f7d38b10c44761dd99abe9b43f47eca517de9908b54b971c3287ffecef54ef9b693c03837489e6a422e427d74d86d5c16b0c4
7
- data.tar.gz: be84f7081d5ab556ee69fe5fd96d6adb5db862e69ca6ea5b387db3b9915f812bde4df8e9dc5cf6c11fc96e1a2cbf6bb09f83fbe2c39ca4430b87525c525737f4
6
+ metadata.gz: 6ee44b240e0007b839b23069601ace6a2221991f12ca560cdc6ca6c372c9ab20db526f7545a06a56ff337a433fe6fd44cce7b3c8d1a91a03ca26d1e9513104bf
7
+ data.tar.gz: a34a2e07fe1b5184ca238a385e29dbbc17a90bc99de6251bffd7a37952500e6549bbe3c1431dc3e153d1fedb2f6bf356ce23d335720d2df674845d96e6daa971
@@ -0,0 +1,6 @@
1
+ guard 'rspec' do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/.+\.rb$})
4
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
5
+ watch('spec/spec_helper.rb') { "spec" }
6
+ end
@@ -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 : 0
50
+ rows.count >= 1 ? rows.first['value'].to_i : nil
43
51
  end
44
52
 
45
- def set_sequence_for(ident,value)
46
- @mutex.synchronize do
47
- AWS::DynamoDB::BatchWrite.new.tap { |batch|
48
- batch.put(
49
- table_name,
50
- [:key => ident,:value => value]
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
- }.process!
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.delete!: #{ident}")
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
- last_seen_id = sequence_id_from(msg)
30
- logger.info("Sequencer.set_last_seen: #{last_seen_id}")
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(ident, last_seen_id)
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
@@ -1,5 +1,5 @@
1
1
  module Alephant
2
2
  module Sequencer
3
- VERSION = "0.0.4"
3
+ VERSION = "0.0.5"
4
4
  end
5
5
  end
@@ -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
- let(:sequence_table) { double().tap { |o| o.stub(:create) } }
18
- subject { Alephant::Sequencer::Sequencer.new(sequence_table, ident, jsonpath) }
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.should_receive(:set_sequence_for).with(ident, last_seen)
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
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-02-17 00:00:00.000000000 Z
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