evt-entity_store 0.3.2.0
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 +7 -0
- data/lib/entity_store.rb +6 -0
- data/lib/entity_store/controls.rb +14 -0
- data/lib/entity_store/controls/category.rb +5 -0
- data/lib/entity_store/controls/entity.rb +54 -0
- data/lib/entity_store/controls/entity_store.rb +60 -0
- data/lib/entity_store/controls/id.rb +5 -0
- data/lib/entity_store/controls/message.rb +23 -0
- data/lib/entity_store/controls/projection.rb +14 -0
- data/lib/entity_store/controls/reader.rb +13 -0
- data/lib/entity_store/controls/snapshot.rb +7 -0
- data/lib/entity_store/controls/snapshot_interval.rb +11 -0
- data/lib/entity_store/controls/stream_name.rb +5 -0
- data/lib/entity_store/controls/version.rb +27 -0
- data/lib/entity_store/entity_store.rb +224 -0
- data/lib/entity_store/log.rb +9 -0
- data/lib/entity_store/substitute.rb +37 -0
- data/lib/loader.rb +1 -0
- metadata +102 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: '09d77f9286b431a0b97ec389c2b2947c15121fd5'
|
4
|
+
data.tar.gz: ca49812c868ff10f425bef7aed92d9c83a24f76a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ea8c3e111aad9eca62a0be47fea1268dbcaf115daf8c88d25e2f593b2fea094536b37c570ddd31d55763ad2b0250a32728560c540d497362f732c64de2718444
|
7
|
+
data.tar.gz: 926e7cd6460e7240e5877f7d5f3b2d6005643f6c2759455e1dc4bb5200a78dfac213ebe6e98d75af08bc61b75d0633fa0e89e1f1acd5edbfd1f2c7e4082567cc
|
data/lib/entity_store.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'entity_projection/controls'
|
2
|
+
require 'entity_cache/controls'
|
3
|
+
|
4
|
+
require 'entity_store/controls/id'
|
5
|
+
require 'entity_store/controls/category'
|
6
|
+
require 'entity_store/controls/stream_name'
|
7
|
+
require 'entity_store/controls/version'
|
8
|
+
require 'entity_store/controls/message'
|
9
|
+
require 'entity_store/controls/entity'
|
10
|
+
require 'entity_store/controls/projection'
|
11
|
+
require 'entity_store/controls/snapshot_interval'
|
12
|
+
require 'entity_store/controls/snapshot'
|
13
|
+
require 'entity_store/controls/reader'
|
14
|
+
require 'entity_store/controls/entity_store'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module EntityStore
|
2
|
+
module Controls
|
3
|
+
module Entity
|
4
|
+
def self.example
|
5
|
+
Current.example
|
6
|
+
end
|
7
|
+
|
8
|
+
class Example
|
9
|
+
include Schema::DataStructure
|
10
|
+
|
11
|
+
attribute :sum
|
12
|
+
|
13
|
+
module Transformer
|
14
|
+
def self.raw_data(instance)
|
15
|
+
instance.to_h
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.instance(raw_data)
|
19
|
+
Example.build(raw_data)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
module Cached
|
25
|
+
def self.example
|
26
|
+
Example.build :sum => sum
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.add(id, store)
|
30
|
+
entity = self.example
|
31
|
+
version = Version::Cached.example
|
32
|
+
|
33
|
+
store.cache.add(id, entity, version, persisted_version: version)
|
34
|
+
|
35
|
+
return entity, version
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.sum
|
39
|
+
1
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module Current
|
44
|
+
def self.example
|
45
|
+
Example.build :sum => sum
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.sum
|
49
|
+
12
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module EntityStore
|
2
|
+
module Controls
|
3
|
+
module EntityStore
|
4
|
+
def self.example(category: nil, entity_class: nil, projection_class: nil, reader_class: nil, snapshot_class: nil, snapshot_interval: nil)
|
5
|
+
if category.nil? && entity_class.nil? && projection_class.nil? && reader_class.nil? && snapshot_class.nil? && snapshot_interval.nil?
|
6
|
+
store_class = Example
|
7
|
+
else
|
8
|
+
store_class = example_class(category: category, entity_class: entity_class, projection_class: projection_class, reader_class: reader_class, snapshot_class: snapshot_class, snapshot_interval: snapshot_interval)
|
9
|
+
end
|
10
|
+
|
11
|
+
instance = store_class.build
|
12
|
+
instance
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.example_class(category: nil, entity_class: nil, projection_class: nil, reader_class: nil, snapshot_class: nil, snapshot_interval: nil)
|
16
|
+
if category == :none
|
17
|
+
category = nil
|
18
|
+
else
|
19
|
+
category ||= Controls::Category.example
|
20
|
+
end
|
21
|
+
|
22
|
+
if entity_class == :none
|
23
|
+
entity_class = nil
|
24
|
+
else
|
25
|
+
entity_class ||= Controls::Entity::Example
|
26
|
+
end
|
27
|
+
|
28
|
+
if projection_class == :none
|
29
|
+
projection_class = nil
|
30
|
+
else
|
31
|
+
projection_class ||= Controls::Projection::Example
|
32
|
+
end
|
33
|
+
|
34
|
+
if reader_class == :none
|
35
|
+
reader_class = nil
|
36
|
+
else
|
37
|
+
reader_class ||= Controls::Reader::Example
|
38
|
+
end
|
39
|
+
|
40
|
+
Class.new do
|
41
|
+
include ::EntityStore
|
42
|
+
|
43
|
+
category category
|
44
|
+
entity entity_class
|
45
|
+
projection projection_class
|
46
|
+
reader reader_class
|
47
|
+
snapshot snapshot_class, snapshot_interval
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module Category
|
52
|
+
def self.example
|
53
|
+
:some_category
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
Example = self.example_class
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module EntityStore
|
2
|
+
module Controls
|
3
|
+
module Message
|
4
|
+
def self.example
|
5
|
+
first
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.first
|
9
|
+
Example.build :number => 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.second
|
13
|
+
Example.build :number => 11
|
14
|
+
end
|
15
|
+
|
16
|
+
class Example
|
17
|
+
include Messaging::Message
|
18
|
+
|
19
|
+
attribute :number
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module EntityStore
|
2
|
+
module Controls
|
3
|
+
module Version
|
4
|
+
def self.example
|
5
|
+
Current.example
|
6
|
+
end
|
7
|
+
|
8
|
+
module NotCached
|
9
|
+
def self.example
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Cached
|
15
|
+
def self.example
|
16
|
+
0
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
module Current
|
21
|
+
def self.example
|
22
|
+
1
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
module EntityStore
|
2
|
+
Error = Class.new(RuntimeError)
|
3
|
+
|
4
|
+
def self.included(cls)
|
5
|
+
cls.class_exec do
|
6
|
+
include Log::Dependency
|
7
|
+
include Messaging::StreamName
|
8
|
+
|
9
|
+
substitute_class = Class.new(Substitute)
|
10
|
+
|
11
|
+
substitute_class.send :define_method, :entity_class do
|
12
|
+
cls.entity_class
|
13
|
+
end
|
14
|
+
|
15
|
+
const_set :Substitute, substitute_class
|
16
|
+
|
17
|
+
attr_accessor :session
|
18
|
+
attr_accessor :new_entity_probe
|
19
|
+
|
20
|
+
dependency :cache, EntityCache
|
21
|
+
|
22
|
+
configure :store
|
23
|
+
|
24
|
+
virtual :category
|
25
|
+
virtual :reader_class
|
26
|
+
virtual :projection_class
|
27
|
+
virtual :snapshot_class
|
28
|
+
virtual :snapshot_interval
|
29
|
+
|
30
|
+
extend Build
|
31
|
+
extend EntityMacro
|
32
|
+
extend ProjectionMacro
|
33
|
+
extend ReaderMacro
|
34
|
+
extend SnapshotMacro
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
module Build
|
39
|
+
def build(snapshot_interval: nil, session: nil)
|
40
|
+
instance = new
|
41
|
+
|
42
|
+
Build.assure(instance)
|
43
|
+
|
44
|
+
instance.session = session
|
45
|
+
|
46
|
+
EntityCache.configure(
|
47
|
+
instance,
|
48
|
+
entity_class,
|
49
|
+
persistent_store: instance.snapshot_class,
|
50
|
+
persist_interval: instance.snapshot_interval,
|
51
|
+
session: session
|
52
|
+
)
|
53
|
+
|
54
|
+
instance
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.assure(instance)
|
58
|
+
if instance.category.nil?
|
59
|
+
raise Error, "Category is not declared"
|
60
|
+
end
|
61
|
+
|
62
|
+
if instance.entity_class.nil?
|
63
|
+
raise Error, "Entity is not declared"
|
64
|
+
end
|
65
|
+
|
66
|
+
if instance.projection_class.nil?
|
67
|
+
raise Error, "Reader is not declared"
|
68
|
+
end
|
69
|
+
|
70
|
+
if instance.reader_class.nil?
|
71
|
+
raise Error, "Reader is not declared"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def get(id, include: nil, &probe_action)
|
77
|
+
logger.trace { "Getting entity (ID: #{id.inspect}, Entity Class: #{entity_class.name}, Include: #{include.inspect})" }
|
78
|
+
|
79
|
+
record = cache.get id
|
80
|
+
|
81
|
+
if record
|
82
|
+
entity = record.entity
|
83
|
+
version = record.version
|
84
|
+
persisted_version = record.persisted_version
|
85
|
+
persisted_time = record.persisted_time
|
86
|
+
else
|
87
|
+
entity = new_entity
|
88
|
+
end
|
89
|
+
|
90
|
+
current_version = refresh(entity, id, version, &probe_action)
|
91
|
+
|
92
|
+
unless current_version.nil?
|
93
|
+
record = cache.put(
|
94
|
+
id,
|
95
|
+
entity,
|
96
|
+
current_version,
|
97
|
+
persisted_version,
|
98
|
+
persisted_time
|
99
|
+
)
|
100
|
+
end
|
101
|
+
|
102
|
+
logger.info { "Get entity done (ID: #{id.inspect}, Entity Class: #{entity_class.name}, Include: #{include.inspect}, Version: #{record&.version.inspect}, Time: #{record&.time.inspect})" }
|
103
|
+
logger.info(tags: [:data, :entity]) { entity.pretty_inspect }
|
104
|
+
|
105
|
+
if record
|
106
|
+
record.destructure include
|
107
|
+
else
|
108
|
+
EntityCache::Record::NoStream.destructure include
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def refresh(entity, id, current_position, &probe_action)
|
113
|
+
logger.trace { "Refreshing (ID: #{id.inspect}, Entity Class: #{entity_class.name}, Current Position #{current_position.inspect})" }
|
114
|
+
logger.trace(tags: [:data, :entity]) { entity.pretty_inspect }
|
115
|
+
|
116
|
+
stream_name = self.stream_name(id)
|
117
|
+
|
118
|
+
start_position = next_position(current_position)
|
119
|
+
|
120
|
+
project = projection_class.build(entity)
|
121
|
+
|
122
|
+
logger.trace { "Reading (Stream Name: #{stream_name}, Position: #{current_position}" }
|
123
|
+
reader_class.(stream_name, position: start_position, session: session) do |event_data|
|
124
|
+
project.(event_data)
|
125
|
+
current_position = event_data.position
|
126
|
+
|
127
|
+
unless probe_action.nil?
|
128
|
+
probe_action.(event_data)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
logger.debug { "Read (Stream Name: #{stream_name}, Position: #{current_position}" }
|
132
|
+
|
133
|
+
logger.debug { "Refreshed (ID: #{id.inspect}, Entity Class: #{entity_class.name}, Current Position: #{current_position.inspect})" }
|
134
|
+
logger.debug(tags: [:data, :entity]) { entity.pretty_inspect }
|
135
|
+
|
136
|
+
current_position
|
137
|
+
end
|
138
|
+
|
139
|
+
def next_position(position)
|
140
|
+
unless position.nil?
|
141
|
+
position + 1
|
142
|
+
else
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def get_version(id)
|
148
|
+
_, version = get id, include: :version
|
149
|
+
version
|
150
|
+
end
|
151
|
+
|
152
|
+
def fetch(id, include: nil)
|
153
|
+
res = get(id, include: include)
|
154
|
+
|
155
|
+
if res.nil?
|
156
|
+
res = new_entity
|
157
|
+
end
|
158
|
+
|
159
|
+
if res.is_a?(Array) && res[0].nil?
|
160
|
+
res[0] = new_entity
|
161
|
+
end
|
162
|
+
|
163
|
+
res
|
164
|
+
end
|
165
|
+
|
166
|
+
def new_entity
|
167
|
+
entity = nil
|
168
|
+
if entity_class.respond_to? :build
|
169
|
+
entity = entity_class.build
|
170
|
+
else
|
171
|
+
entity = entity_class.new
|
172
|
+
end
|
173
|
+
|
174
|
+
unless new_entity_probe.nil?
|
175
|
+
new_entity_probe.(entity)
|
176
|
+
end
|
177
|
+
|
178
|
+
entity
|
179
|
+
end
|
180
|
+
|
181
|
+
module EntityMacro
|
182
|
+
def entity_macro(cls)
|
183
|
+
define_singleton_method :entity_class do
|
184
|
+
cls
|
185
|
+
end
|
186
|
+
|
187
|
+
define_method :entity_class do
|
188
|
+
self.class.entity_class
|
189
|
+
end
|
190
|
+
end
|
191
|
+
alias_method :entity, :entity_macro
|
192
|
+
end
|
193
|
+
|
194
|
+
module ProjectionMacro
|
195
|
+
def projection_macro(cls)
|
196
|
+
define_method :projection_class do
|
197
|
+
cls
|
198
|
+
end
|
199
|
+
end
|
200
|
+
alias_method :projection, :projection_macro
|
201
|
+
end
|
202
|
+
|
203
|
+
module ReaderMacro
|
204
|
+
def reader_macro(cls)
|
205
|
+
define_method :reader_class do
|
206
|
+
cls
|
207
|
+
end
|
208
|
+
end
|
209
|
+
alias_method :reader, :reader_macro
|
210
|
+
end
|
211
|
+
|
212
|
+
module SnapshotMacro
|
213
|
+
def snapshot_macro(cls, interval)
|
214
|
+
define_method :snapshot_class do
|
215
|
+
cls
|
216
|
+
end
|
217
|
+
|
218
|
+
define_method :snapshot_interval do
|
219
|
+
interval
|
220
|
+
end
|
221
|
+
end
|
222
|
+
alias_method :snapshot, :snapshot_macro
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module EntityStore
|
2
|
+
class Substitute
|
3
|
+
include EntityStore
|
4
|
+
|
5
|
+
def self.build
|
6
|
+
new
|
7
|
+
end
|
8
|
+
|
9
|
+
def get(id, include: nil)
|
10
|
+
record = records[id]
|
11
|
+
|
12
|
+
if record
|
13
|
+
record.destructure include
|
14
|
+
else
|
15
|
+
EntityCache::Record::NoStream.destructure include
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_version(id)
|
20
|
+
_, version = get id, include: :version
|
21
|
+
version
|
22
|
+
end
|
23
|
+
|
24
|
+
def add(id, entity, version=nil)
|
25
|
+
version ||= 0
|
26
|
+
|
27
|
+
record = EntityCache::Record.new id, entity, version
|
28
|
+
|
29
|
+
records[id] = record
|
30
|
+
end
|
31
|
+
alias :put :add
|
32
|
+
|
33
|
+
def records
|
34
|
+
@records ||= {}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/loader.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
entity_store.rb
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: evt-entity_store
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- The Eventide Project
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-12-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: entity_projection
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: entity_cache
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: test_bench
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: " "
|
56
|
+
email: opensource@eventide-project.org
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- lib/entity_store.rb
|
62
|
+
- lib/entity_store/controls.rb
|
63
|
+
- lib/entity_store/controls/category.rb
|
64
|
+
- lib/entity_store/controls/entity.rb
|
65
|
+
- lib/entity_store/controls/entity_store.rb
|
66
|
+
- lib/entity_store/controls/id.rb
|
67
|
+
- lib/entity_store/controls/message.rb
|
68
|
+
- lib/entity_store/controls/projection.rb
|
69
|
+
- lib/entity_store/controls/reader.rb
|
70
|
+
- lib/entity_store/controls/snapshot.rb
|
71
|
+
- lib/entity_store/controls/snapshot_interval.rb
|
72
|
+
- lib/entity_store/controls/stream_name.rb
|
73
|
+
- lib/entity_store/controls/version.rb
|
74
|
+
- lib/entity_store/entity_store.rb
|
75
|
+
- lib/entity_store/log.rb
|
76
|
+
- lib/entity_store/substitute.rb
|
77
|
+
- lib/loader.rb
|
78
|
+
homepage: https://github.com/eventide-project/entity-store
|
79
|
+
licenses:
|
80
|
+
- MIT
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: 2.3.3
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 2.5.2
|
99
|
+
signing_key:
|
100
|
+
specification_version: 4
|
101
|
+
summary: Store of entities that are projected from streams
|
102
|
+
test_files: []
|