evt-entity_store 0.3.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|