entity_store 0.0.7 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ module EntityStore
2
+ module Attributes
3
+ def self.included(klass)
4
+ klass.class_eval do
5
+ extend ClassMethods
6
+ end
7
+ end
8
+
9
+ module ClassMethods
10
+ def entity_value_attribute(name, klass)
11
+ define_method(name) { instance_variable_get("@#{name}") }
12
+ define_method("#{name}=") do |value|
13
+ instance_variable_set("@#{name}", value.is_a?(Hash) ? klass.new(value) : value)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -2,14 +2,10 @@ module EntityStore
2
2
  module Entity
3
3
  attr_accessor :id
4
4
 
5
- # Holds a reference to the store used to load this entity so the same store
6
- # can be used for related entities
7
- attr_accessor :related_entity_loader
8
-
9
- attr_writer :version
10
-
11
5
  def self.included(klass)
12
6
  klass.class_eval do
7
+ include HashSerialization
8
+ include Attributes
13
9
  extend ClassMethods
14
10
  end
15
11
  end
@@ -24,8 +20,8 @@ module EntityStore
24
20
 
25
21
  # lazy loader for related entity
26
22
  define_method(name) {
27
- if instance_variable_get("@#{name}_id") && related_entity_loader
28
- instance_variable_get("@_#{name}") || instance_variable_set("@_#{name}", related_entity_loader.get(instance_variable_get("@#{name}_id")))
23
+ if instance_variable_get("@#{name}_id") && @_related_entity_loader
24
+ instance_variable_get("@_#{name}") || instance_variable_set("@_#{name}", @_related_entity_loader.get(instance_variable_get("@#{name}_id")))
29
25
  end
30
26
  }
31
27
  end
@@ -37,22 +33,32 @@ module EntityStore
37
33
 
38
34
  end
39
35
 
40
- def initialize(attr={})
41
- attr.each_pair { |k,v| self.send("#{k}=", v) }
42
- end
43
-
44
36
  def type
45
37
  self.class.name
46
38
  end
47
39
 
48
40
  def version
49
- @version ||= 1
41
+ @_version ||= 1
50
42
  end
51
-
43
+
44
+ def version=(value)
45
+ @_version = value
46
+ end
47
+
48
+ # Holds a reference to the store used to load this entity so the same store
49
+ # can be used for related entities
50
+ def related_entity_loader=(value)
51
+ @_related_entity_loader = value
52
+ end
53
+
52
54
  def pending_events
53
55
  @pending_events ||= []
54
56
  end
55
57
 
58
+ def clear_pending_events
59
+ @pending_events = []
60
+ end
61
+
56
62
  def record_event(event)
57
63
  apply_event(event)
58
64
  pending_events<<event
@@ -61,5 +67,6 @@ module EntityStore
61
67
  def apply_event(event)
62
68
  event.apply(self)
63
69
  end
70
+
64
71
  end
65
72
  end
@@ -2,21 +2,11 @@ module EntityStore
2
2
  module EntityValue
3
3
  def self.included(klass)
4
4
  klass.class_eval do
5
- extend ClassMethods
5
+ include HashSerialization
6
+ include Attributes
6
7
  end
7
8
  end
8
9
 
9
- def initialize(attr={})
10
- attr.each_pair { |k,v| self.send("#{k}=", v) if self.respond_to? "#{k}=" }
11
- end
12
-
13
- def attributes
14
- Hash[*public_methods.select {|m| m =~ /\w\=$/}.collect do |m|
15
- attribute_name = m.to_s.chop.to_sym
16
- [attribute_name, send(attribute_name).respond_to?(:attributes) ? send(attribute_name).attributes : send(attribute_name)]
17
- end.flatten]
18
- end
19
-
20
10
  def ==(other)
21
11
  attributes.each_key do |attr|
22
12
  return false unless other.respond_to?(attr) && send(attr) == other.send(attr)
@@ -24,13 +14,5 @@ module EntityStore
24
14
  return true
25
15
  end
26
16
 
27
- module ClassMethods
28
- def entity_value_attribute(name, klass)
29
- define_method(name) { instance_variable_get("@#{name}") }
30
- define_method("#{name}=") do |value|
31
- instance_variable_set("@#{name}", value.is_a?(Hash) ? klass.new(value) : value)
32
- end
33
- end
34
- end
35
17
  end
36
18
  end
@@ -2,9 +2,11 @@ module EntityStore
2
2
  module Event
3
3
  attr_accessor :entity_id, :entity_version
4
4
 
5
- def initialize(attrs={})
6
- attrs.each_pair do |key, value|
7
- send("#{key}=", value) if respond_to?("#{key}=")
5
+ def self.included(klass)
6
+ klass.class_eval do
7
+ include Attributes
8
+ include HashSerialization
9
+ extend ClassMethods
8
10
  end
9
11
  end
10
12
 
@@ -17,19 +19,6 @@ module EntityStore
17
19
  downcase
18
20
  end
19
21
 
20
- def attributes
21
- Hash[*public_methods.select {|m| m =~ /\w\=$/}.collect do |m|
22
- attribute_name = m.to_s.chop.to_sym
23
- [attribute_name, send(attribute_name).respond_to?(:attributes) ? send(attribute_name).attributes : send(attribute_name)]
24
- end.flatten]
25
- end
26
-
27
- def self.included(klass)
28
- klass.class_eval do
29
- extend ClassMethods
30
- end
31
- end
32
-
33
22
  module ClassMethods
34
23
  def time_attribute(*names)
35
24
  class_eval do
@@ -0,0 +1,32 @@
1
+ module EntityStore
2
+ module HashSerialization
3
+
4
+ def initialize(attr={})
5
+ attr.each_pair { |k,v| send("#{k}=", v) if respond_to?("#{k}=") }
6
+ end
7
+
8
+ # Public - generate attributes hash
9
+ # did use flatten but this came a-cropper when the attribute value was an array
10
+ def attributes
11
+ attrs = {}
12
+ public_methods
13
+ .select { |m| m =~ /\w\=$/ }
14
+ .select { |m| respond_to?(m.to_s.chop) }
15
+ .collect { |m| m.to_s.chop.to_sym }
16
+ .collect { |m| [m, attribute_value(send(m))] }
17
+ .each do |item| attrs[item[0]] = item[1] end
18
+ attrs
19
+ end
20
+
21
+ def attribute_value(value)
22
+ if value.respond_to?(:attributes)
23
+ value.attributes
24
+ elsif value.respond_to?(:each)
25
+ value.collect { |v| attribute_value(v) }
26
+ else
27
+ value
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -28,7 +28,8 @@ module EntityStore
28
28
  end
29
29
 
30
30
  def ensure_indexes
31
- events_collection.ensure_index([['entity_id', Mongo::ASCENDING], ['_id', Mongo::ASCENDING]])
31
+ events.ensure_index([['entity_id', Mongo::ASCENDING], ['_id', Mongo::ASCENDING]])
32
+ events.ensure_index([['entity_id', Mongo::ASCENDING], ['entity_version', Mongo::ASCENDING], ['_id', Mongo::ASCENDING]])
32
33
  end
33
34
 
34
35
  def add_entity(entity)
@@ -39,6 +40,20 @@ module EntityStore
39
40
  entities.update({'_id' => BSON::ObjectId.from_string(entity.id)}, { '$set' => { 'version' => entity.version } })
40
41
  end
41
42
 
43
+ # Public - create a snapshot of the entity and store in the entities collection
44
+ #
45
+ def snapshot_entity(entity)
46
+ query = {'_id' => BSON::ObjectId.from_string(entity.id)}
47
+ updates = { '$set' => { 'snapshot' => entity.attributes } }
48
+ entities.update(query, updates, { :upsert => true} )
49
+ end
50
+
51
+ # Public - remove the snapshot for an entity
52
+ #
53
+ def remove_entity_snapshot(id)
54
+ entities.update({'_id' => BSON::ObjectId.from_string(id)}, { '$unset' => { 'snapshot' => 1}})
55
+ end
56
+
42
57
  def add_event(event)
43
58
  events.insert({'_type' => event.class.name, '_entity_id' => BSON::ObjectId.from_string(event.entity_id) }.merge(event.attributes) ).to_s
44
59
  end
@@ -47,28 +62,44 @@ module EntityStore
47
62
  get_entity(id, true)
48
63
  end
49
64
 
65
+ # Public - loads the entity from the store, including any available snapshots
66
+ # then loads the events to complete the state
67
+ #
68
+ # id - String representation of BSON::ObjectId
69
+ # raise_exception - Boolean indicating whether to raise an exception if not found (default=false)
70
+ #
71
+ # Returns an object of the entity type
50
72
  def get_entity(id, raise_exception=false)
51
- begin
52
- if attrs = entities.find('_id' => BSON::ObjectId.from_string(id)).first
53
- get_type_constant(attrs['_type']).new('id' => id, 'version' => attrs['version'])
54
- else
55
- if raise_exception
56
- raise NotFound.new(id)
57
- else
58
- return nil
59
- end
60
- end
61
- rescue BSON::InvalidObjectId
62
- if raise_exception
63
- raise NotFound.new(id)
64
- else
65
- return nil
73
+ if attrs = entities.find_one('_id' => BSON::ObjectId.from_string(id))
74
+ entity = get_type_constant(attrs['_type']).new(attrs['snapshot'] || {'id' => id, 'version' => attrs['version']})
75
+
76
+ since_version = attrs['snapshot'] ? attrs['snapshot']['version'] : nil
77
+
78
+ get_events(id, since_version).each do |e|
79
+ e.apply(entity)
80
+ entity.version = e.entity_version
66
81
  end
82
+
83
+ entity
84
+ else
85
+ raise NotFound.new(id) if raise_exception
86
+ nil
67
87
  end
88
+ rescue BSON::InvalidObjectId
89
+ raise NotFound.new(id) if raise_exception
90
+ nil
68
91
  end
69
92
 
70
- def get_events(id)
71
- events.find('_entity_id' => BSON::ObjectId.from_string(id)).collect do |attrs|
93
+ def get_events(id, since_version=nil)
94
+
95
+ query = { '_entity_id' => BSON::ObjectId.from_string(id) }
96
+ query['entity_version'] = { '$gt' => since_version } if since_version
97
+
98
+ options = {
99
+ :sort => [['entity_version', Mongo::ASCENDING], ['_id', Mongo::ASCENDING]]
100
+ }
101
+
102
+ events.find(query, options).collect do |attrs|
72
103
  begin
73
104
  get_type_constant(attrs['_type']).new(attrs)
74
105
  rescue => e
@@ -1,7 +1,7 @@
1
1
  module EntityStore
2
2
  class Store
3
3
  def storage_client
4
- @storage_client || MongoEntityStore.new
4
+ @_storage_client ||= MongoEntityStore.new
5
5
  end
6
6
 
7
7
  def add(entity)
@@ -29,6 +29,7 @@ module EntityStore
29
29
  entity.id = storage_client.add_entity(entity)
30
30
  end
31
31
  add_events(entity)
32
+ snapshot_entity(entity) if entity.version % EntityStore.snapshot_threshold == 0
32
33
  end
33
34
  entity
34
35
  rescue => e
@@ -36,6 +37,15 @@ module EntityStore
36
37
  raise e
37
38
  end
38
39
 
40
+ def snapshot_entity(entity)
41
+ EntityStore.logger.info { "Store#snapshot_entity : Snapshotting #{entity.id}"}
42
+ storage_client.snapshot_entity(entity)
43
+ end
44
+
45
+ def remove_entity_snapshot(id)
46
+ storage_client.remove_entity_snapshot(id)
47
+ end
48
+
39
49
  def add_events(entity)
40
50
  entity.pending_events.each do |e|
41
51
  e.entity_id = entity.id.to_s
@@ -43,6 +53,7 @@ module EntityStore
43
53
  storage_client.add_event(e)
44
54
  end
45
55
  entity.pending_events.each {|e| EventBus.publish(entity.type, e) }
56
+ entity.clear_pending_events
46
57
  end
47
58
 
48
59
  def get!(id)
@@ -51,7 +62,6 @@ module EntityStore
51
62
 
52
63
  def get(id, raise_exception=false)
53
64
  if entity = storage_client.get_entity(id, raise_exception)
54
- storage_client.get_events(id).each { |e| e.apply(entity) }
55
65
  # assign this entity loader to allow lazy loading of related entities
56
66
  entity.related_entity_loader = self
57
67
  end
@@ -64,7 +74,7 @@ module EntityStore
64
74
  def clear_all
65
75
  storage_client.entities.drop
66
76
  storage_client.events.drop
67
- @storage_client = nil
77
+ @_storage_client = nil
68
78
  end
69
79
 
70
80
  end
@@ -1,3 +1,3 @@
1
1
  module EntityStore
2
- VERSION = "0.0.7".freeze
2
+ VERSION = "0.0.8".freeze
3
3
  end
data/lib/entity_store.rb CHANGED
@@ -9,6 +9,8 @@ module EntityStore
9
9
  require 'entity_store/mongo_entity_store'
10
10
  require 'entity_store/event_bus'
11
11
  require 'entity_store/not_found'
12
+ require 'entity_store/hash_serialization'
13
+ require 'entity_store/attributes'
12
14
 
13
15
  class << self
14
16
  def setup
@@ -35,6 +37,16 @@ module EntityStore
35
37
  @_event_subscribers ||=[]
36
38
  end
37
39
 
40
+ # Public - indicates the version increment that is used to
41
+ # decided whether a snapshot of an entity should be created when it's saved
42
+ def snapshot_threshold
43
+ @_snapshot_threshold ||= 10
44
+ end
45
+
46
+ def snapshot_threshold=(value)
47
+ @_snapshot_threshold = value
48
+ end
49
+
38
50
  def log_level
39
51
  @_log_level ||= Logger::INFO
40
52
  end
@@ -5,6 +5,8 @@ class DummyEntity
5
5
 
6
6
  related_entities :club, :user
7
7
 
8
+ attr_accessor :name, :description, :members
9
+
8
10
  end
9
11
 
10
12
  describe Entity do
@@ -66,4 +68,18 @@ describe Entity do
66
68
  end
67
69
  end
68
70
  end
71
+
72
+ describe "#attributes" do
73
+ before(:each) do
74
+ @entity = DummyEntity.new(:id => @id = random_object_id, :club_id => @club_id = random_string,
75
+ :user_id => @user_id = random_string, :name => @name = random_string, :version => @version = random_integer,
76
+ :members => [])
77
+ end
78
+
79
+ subject { @entity.attributes }
80
+
81
+ it "returns a hash of the attributes" do
82
+ subject.should eq({:id => @id, :version => @version, :name => @name, :club_id => @club_id, :user_id => @user_id, :description => nil, :members => []})
83
+ end
84
+ end
69
85
  end
@@ -32,8 +32,11 @@ describe EntityValue do
32
32
  before(:each) do
33
33
  @value = DummyEntityValue.new(:name => @name, :home => @home)
34
34
  end
35
- it "should return hash of attributes" do
36
- @value.attributes.should eq({:name => @name, :home => @home})
35
+
36
+ subject { @value.attributes }
37
+
38
+ it "should return hash of attributes and type" do
39
+ subject.should eq({:name => @name, :home => @home})
37
40
  end
38
41
  context "nested attributes" do
39
42
  before(:each) do
@@ -42,8 +45,9 @@ describe EntityValue do
42
45
  @value.home = NestedEntityValue.new(:street => @street, :town => @town)
43
46
  end
44
47
  it "should return a hash containing the nested attribute" do
45
- @value.attributes.should eq({:name => @name, :home => {:street => @street, :town => @town}})
48
+ subject.should eq({:name => @name, :home => {:street => @street, :town => @town}})
46
49
  end
50
+
47
51
  end
48
52
 
49
53
  end
@@ -94,4 +94,5 @@ describe ExternalStore do
94
94
  end
95
95
 
96
96
  end
97
+
97
98
  end
@@ -7,12 +7,80 @@ module Level1
7
7
  end
8
8
  end
9
9
 
10
+ module MongoEntityStoreSpec
11
+ class DummyEntity
12
+ include Entity
13
+
14
+ attr_accessor :name, :description
15
+
16
+ end
17
+ end
18
+
10
19
  describe MongoEntityStore do
11
20
  before(:each) do
12
21
  EntityStore.connection_profile = "mongodb://localhost/entity_store_default"
13
22
  @store = MongoEntityStore.new
14
23
  end
24
+
25
+ describe "#get_entity" do
26
+ before(:each) do
27
+ @id = random_object_id
28
+ @attrs = {
29
+ '_type' => "MongoEntityStoreSpec::DummyEntity",
30
+ 'version' => @version = random_integer
31
+ }
32
+ @entity = MongoEntityStoreSpec::DummyEntity.new
33
+ MongoEntityStoreSpec::DummyEntity.stub(:new) { @entity }
34
+ @entities_collection = mock('MongoCollection', :find_one => @attrs)
35
+ @store.stub(:entities) { @entities_collection }
36
+ @events = [
37
+ mock('Event', :apply => true, :entity_version => random_integer), mock('Event', :apply => true, :entity_version => random_integer)
38
+ ]
39
+ @store.stub(:get_events) { @events }
40
+ end
41
+
42
+ subject { @store.get_entity(@id) }
43
+
44
+ it "should attempt to retrieve the entity record from the store" do
45
+ @entities_collection.should_receive(:find_one).with({'_id' => BSON::ObjectId.from_string(@id)})
46
+ subject
47
+ end
48
+ it "should construct a new entity" do
49
+ MongoEntityStoreSpec::DummyEntity.should_receive(:new).with({'id' => @id, 'version' => @version})
50
+ subject
51
+ end
52
+ it "should retrieve it's events" do
53
+ @store.should_receive(:get_events).with(@id, nil)
54
+ subject
55
+ end
56
+ it "should apply each event to the entity" do
57
+ @events.each do |event| event.should_receive(:apply).with(@entity) end
58
+ subject
59
+ end
60
+ it "should set the entity version to that of the last event" do
61
+ subject
62
+ @entity.version.should eq(@events.last.entity_version)
63
+ end
64
+ context "when a snapshot exists" do
65
+ before(:each) do
66
+ @attrs['snapshot'] = {
67
+ 'version' => @snapshot_version = random_integer,
68
+ 'name' => @name = random_string
69
+ }
70
+ end
71
+ it "should construct a new entity with from the snapshot" do
72
+ MongoEntityStoreSpec::DummyEntity.should_receive(:new).with(@attrs['snapshot'])
73
+ subject
74
+ end
75
+ it "should load the events since the snapshot version" do
76
+ @store.should_receive(:get_events).with(@id, @snapshot_version)
77
+ subject
78
+ end
79
+ end
80
+ end
81
+
15
82
  describe "#get_entity!" do
83
+
16
84
  context "when invalid id format passed" do
17
85
 
18
86
  subject { @store.get_entity!(random_string) }
@@ -22,9 +90,6 @@ describe MongoEntityStore do
22
90
  end
23
91
  end
24
92
  context "when valid id format passed but no object exists" do
25
- before(:each) do
26
- @store = MongoEntityStore.new
27
- end
28
93
 
29
94
  subject { @store.get_entity!(random_object_id) }
30
95
 
@@ -43,4 +108,21 @@ describe MongoEntityStore do
43
108
  subject.should eq(Level1::Level2::MyClass)
44
109
  end
45
110
  end
111
+
112
+ describe "#snapshot_entity" do
113
+ before(:each) do
114
+ @entity = MongoEntityStoreSpec::DummyEntity.new(:id => random_object_id, :version => random_integer, :name => random_string)
115
+ end
116
+
117
+ subject { @store.snapshot_entity(@entity) }
118
+
119
+ it "should add a snaphot to the entity record" do
120
+ subject
121
+ saved_entity = @store.entities.find_one({'_id' => BSON::ObjectId.from_string(@entity.id)})['snapshot']
122
+ saved_entity['id'].should eq(@entity.id)
123
+ saved_entity['version'].should eq(@entity.version)
124
+ saved_entity['name'].should eq(@entity.name)
125
+ saved_entity['description'].should eq(@entity.description)
126
+ end
127
+ end
46
128
  end
@@ -79,6 +79,7 @@ describe Store do
79
79
  context "when entity has related entities loaded" do
80
80
  before(:each) do
81
81
  @entity = DummyEntityForStore.new(:id => random_string)
82
+ @entity.version = random_integer * EntityStore.snapshot_threshold + 1
82
83
  @store = Store.new
83
84
  @related_entity = mock('Entity')
84
85
  @entity.stub(:loaded_related_entities) { [ @related_entity ] }
@@ -96,13 +97,13 @@ describe Store do
96
97
  subject
97
98
  end
98
99
  end
99
-
100
100
  end
101
101
 
102
102
  describe "#do_save" do
103
103
  before(:each) do
104
104
  @new_id = random_string
105
105
  @entity = DummyEntityForStore.new(:id => random_string)
106
+ @entity.version = random_integer * EntityStore.snapshot_threshold
106
107
  @storage_client = mock("StorageClient", :save_entity => true)
107
108
  @store = Store.new
108
109
  @store.stub(:add_events)
@@ -113,8 +114,7 @@ describe Store do
113
114
  subject { @store.do_save(@entity) }
114
115
 
115
116
  it "increments the entity version number" do
116
- @entity.should_receive(:version=).with(@entity.version + 1)
117
- subject
117
+ expect { subject }.to change { @entity.version }.by 1
118
118
  end
119
119
  it "save the new entity to the store" do
120
120
  @storage_client.should_receive(:save_entity).with(@entity)
@@ -127,6 +127,11 @@ describe Store do
127
127
  it "returns a reference to the entity" do
128
128
  subject.should eq(@entity)
129
129
  end
130
+ it "should not snapshot the entity" do
131
+ @store.should_not_receive(:snapshot_entity)
132
+ subject
133
+ end
134
+
130
135
  context "when no pending events" do
131
136
  before(:each) do
132
137
  @entity.stub(:pending_events) { [] }
@@ -140,6 +145,7 @@ describe Store do
140
145
  subject
141
146
  end
142
147
  end
148
+
143
149
  context "when entity doesn't have an id" do
144
150
  before(:each) do
145
151
  @entity.id = nil
@@ -151,13 +157,25 @@ describe Store do
151
157
  subject
152
158
  end
153
159
  end
160
+
161
+ context "when entity version is commensurate with snapshotting" do
162
+ before(:each) do
163
+ @entity.version = random_integer * EntityStore.snapshot_threshold - 1
164
+ end
165
+
166
+ it "should snapshot the entity" do
167
+ @storage_client.should_receive(:snapshot_entity).with(@entity)
168
+ subject
169
+ end
170
+ end
171
+
154
172
  end
155
173
 
156
174
  describe "#get" do
157
175
  before(:each) do
158
176
  @id = random_integer
159
177
  @entity = DummyEntityForStore.new
160
- DummyEntityForStore.stub(:new).and_return(@ride)
178
+ DummyEntityForStore.stub(:new).and_return(@entity)
161
179
  @events = [mock("Event", :apply => true), mock("Event", :apply => true)]
162
180
 
163
181
  @storage_client = mock("StorageClient", :get_entity => @entity, :get_events => @events)
@@ -171,18 +189,9 @@ describe Store do
171
189
  @storage_client.should_receive(:get_entity).with(@id, false)
172
190
  subject
173
191
  end
174
- it "should retrieve the events for the entity" do
175
- @storage_client.should_receive(:get_events).with(@id)
176
- subject
177
- end
178
- it "should apply each event" do
179
- @events.each do |e|
180
- e.should_receive(:apply).with(@entity)
181
- end
182
- subject
183
- end
184
192
  it "should assign itself as the related_entity_loader" do
185
- subject.related_entity_loader.should eq(@store)
193
+ @entity.should_receive(:related_entity_loader=).with(@store)
194
+ subject
186
195
  end
187
196
  it "should return a ride" do
188
197
  subject.should eq(@entity)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: entity_store
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
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-10-13 00:00:00.000000000 Z
12
+ date: 2012-10-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongo
@@ -49,6 +49,7 @@ executables: []
49
49
  extensions: []
50
50
  extra_rdoc_files: []
51
51
  files:
52
+ - lib/entity_store/attributes.rb
52
53
  - lib/entity_store/config.rb
53
54
  - lib/entity_store/entity.rb
54
55
  - lib/entity_store/entity_value.rb
@@ -56,6 +57,7 @@ files:
56
57
  - lib/entity_store/event_bus.rb
57
58
  - lib/entity_store/event_data_object.rb
58
59
  - lib/entity_store/external_store.rb
60
+ - lib/entity_store/hash_serialization.rb
59
61
  - lib/entity_store/mongo_entity_store.rb
60
62
  - lib/entity_store/not_found.rb
61
63
  - lib/entity_store/store.rb