eventus 0.3.1 → 0.3.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.
@@ -16,6 +16,18 @@ module Eventus
16
16
  def persistence
17
17
  @persistence ||= Eventus.persistence
18
18
  end
19
+
20
+ def conflicts(added = {})
21
+ @event_conflicts ||= {}
22
+ added.each do |k,v|
23
+ @event_conflicts[k.to_s] = v.respond_to?(:map) ? v.map{|e| e.to_s} : v.to_s
24
+ end
25
+ end
26
+
27
+ def conflict?(e1, e2)
28
+ return false unless @event_conflicts
29
+ @event_conflicts.fetch(e1,[]).include?(e2) || @event_conflicts.fetch(e2,[]).include?(e1)
30
+ end
19
31
  end
20
32
 
21
33
  module InstanceMethods
@@ -27,7 +39,15 @@ module Eventus
27
39
  end
28
40
 
29
41
  def save
42
+ version = @stream.version
30
43
  @stream.commit
44
+ true
45
+ rescue Eventus::ConcurrencyError
46
+ committed = @stream.committed_events[version-1..-1]
47
+ uncommitted = @stream.uncommitted_events
48
+ conflict = committed.any?{ |e| uncommitted.any? {|u| self.class.conflict?(e['name'], u['name'])} }
49
+ raise Eventus::ConflictError if conflict
50
+ false
31
51
  end
32
52
 
33
53
  protected
@@ -1,4 +1,5 @@
1
1
  module Eventus
2
2
  class ConcurrencyError < ::StandardError; end
3
+ class ConflictError < ::StandardError; end
3
4
  class ConnectionError < ::StandardError; end
4
5
  end
@@ -1,3 +1,3 @@
1
1
  module Eventus
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
@@ -5,6 +5,8 @@ class TestAgg
5
5
 
6
6
  attr_accessor :loaded
7
7
 
8
+ conflicts :cake_baked => :cake_baked
9
+
8
10
  def bake_cake
9
11
  apply_change :cake_baked, :flavor => 'strawberry'
10
12
  end
@@ -55,15 +57,29 @@ describe Eventus::AggregateRoot do
55
57
 
56
58
  describe "when saving" do
57
59
  let(:aggregate) { TestAgg.new }
58
- let(:stream) { stub(:stream, :committed_events => []) }
60
+ let(:stream) { stub(:stream, :committed_events => events, :version => events.length) }
61
+ let(:events) { [{'name' => 'cake_baked'}] }
59
62
 
60
63
  before do
61
64
  aggregate.populate(stream)
62
65
  end
63
66
 
64
- it "should commit stream" do
67
+ it "should return true when no concurrency error" do
65
68
  stream.should_receive(:commit)
66
- aggregate.save
69
+ aggregate.save.should == true
70
+ end
71
+
72
+ it "should return false if no conflict" do
73
+ stream.should_receive(:commit).and_raise(Eventus::ConcurrencyError)
74
+ stream.should_receive(:uncommitted_events).and_return([{'name' => 'coconut'}])
75
+
76
+ aggregate.save.should == false
77
+ end
78
+
79
+ it "should raise conflict error if conflict exists" do
80
+ stream.should_receive(:commit).and_raise(Eventus::ConcurrencyError)
81
+ stream.should_receive(:uncommitted_events).and_return([{'name' => 'cake_baked'}])
82
+ lambda {aggregate.save}.should raise_error(Eventus::ConflictError)
67
83
  end
68
84
  end
69
85
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-01-16 00:00:00.000000000Z
12
+ date: 2012-01-17 00:00:00.000000000Z
13
13
  dependencies: []
14
14
  description: An Event Store
15
15
  email:
@@ -57,7 +57,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
57
  version: '0'
58
58
  segments:
59
59
  - 0
60
- hash: 2674942126495806471
60
+ hash: 24983203454212459
61
61
  required_rubygems_version: !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
@@ -66,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
66
  version: '0'
67
67
  segments:
68
68
  - 0
69
- hash: 2674942126495806471
69
+ hash: 24983203454212459
70
70
  requirements: []
71
71
  rubyforge_project: eventus
72
72
  rubygems_version: 1.8.13