evt-message_store 0.1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cbb27c84708165c4c45115a2c898b13c961ac316
4
+ data.tar.gz: 5903ed1eaccc4ecd8887a29892ddeff5f9919f33
5
+ SHA512:
6
+ metadata.gz: 222bf221662fb048aa8c9bfc19f3e83781eaae32e6fc64e8b18eebb38e7af5361db242ff1de48bd99d3aa49dd62c6f4e891c5e5d4da9f37c4160c689b955344e
7
+ data.tar.gz: 1381711997c88044b183228967802ce5825b4c819b291d6e632de9e49b060475ec12562cc9c6a7f95feaff2aa3617d1ec077d3083c9c70a92aeb9c95397b1838
@@ -0,0 +1,25 @@
1
+ require 'pp'
2
+ require 'json'
3
+
4
+ require 'casing'
5
+ require 'identifier/uuid'
6
+ require 'schema'
7
+ require 'initializer'; Initializer.activate
8
+ require 'transform'
9
+ require 'virtual'; Virtual.activate
10
+ require 'async_invocation'
11
+
12
+ require 'message_store/expected_version'
13
+ require 'message_store/no_stream'
14
+ require 'message_store/message_data'
15
+ require 'message_store/message_data/hash'
16
+ require 'message_store/message_data/write'
17
+ require 'message_store/message_data/read'
18
+ require 'message_store/stream_name'
19
+
20
+ require 'message_store/log'
21
+
22
+ require 'message_store/get'
23
+ require 'message_store/read/iterator'
24
+ require 'message_store/read'
25
+ require 'message_store/write'
@@ -0,0 +1,18 @@
1
+ require 'securerandom'
2
+
3
+ require 'identifier/uuid/controls'
4
+
5
+ require 'message_store/controls/random_value'
6
+ require 'message_store/controls/time'
7
+ require 'message_store/controls/id'
8
+ require 'message_store/controls/category'
9
+ require 'message_store/controls/stream_name'
10
+ require 'message_store/controls/read'
11
+ require 'message_store/controls/message_data'
12
+ require 'message_store/controls/message_data/hash'
13
+ require 'message_store/controls/message_data/metadata'
14
+ require 'message_store/controls/message_data/write'
15
+ require 'message_store/controls/message_data/read'
16
+ require 'message_store/controls/write'
17
+ require 'message_store/controls/get'
18
+ require 'message_store/controls/iterator'
@@ -0,0 +1,23 @@
1
+ module MessageStore
2
+ module Controls
3
+ module Category
4
+ def self.example(category: nil, randomize_category: nil)
5
+ if randomize_category.nil?
6
+ if !category.nil?
7
+ randomize_category = false
8
+ end
9
+ end
10
+
11
+ randomize_category = true if randomize_category.nil?
12
+
13
+ category ||= 'test'
14
+
15
+ if randomize_category
16
+ category = "#{category}#{SecureRandom.hex(16)}XX"
17
+ end
18
+
19
+ category
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,25 @@
1
+ module MessageStore
2
+ module Controls
3
+ module Get
4
+ def self.example(batch_size: nil, count: nil, global_position_offset: nil)
5
+ batch_size ||= 1
6
+ count ||= 1
7
+ global_position_offset ||= -> (x) { x ** 2 }
8
+
9
+ get = MessageStore::Get::Substitute.build(batch_size: batch_size)
10
+
11
+ elements = (0..(count - 1)).to_a
12
+
13
+ elements.each do |e|
14
+ message_data = MessageData::Read.example
15
+ message_data.position = e
16
+ message_data.global_position = global_position_offset.(message_data.position)
17
+
18
+ get.items << message_data
19
+ end
20
+
21
+ get
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,11 @@
1
+ module MessageStore
2
+ module Controls
3
+ module ID
4
+ def self.example(i=nil, increment: nil, sample: nil)
5
+ Identifier::UUID::Controls::Incrementing.example(i=nil, increment: nil, sample: nil)
6
+ end
7
+
8
+ Random = Identifier::UUID::Controls::Random
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ module MessageStore
2
+ module Controls
3
+ module Iterator
4
+ def self.example(stream_name: nil, position: nil)
5
+ stream_name ||= StreamName.example
6
+ Example.build(stream_name, position: position)
7
+ end
8
+
9
+ class Example
10
+ include MessageStore::Read::Iterator
11
+
12
+ def last_position
13
+ unless self.class.category?(stream_name)
14
+ batch.last.position
15
+ else
16
+ batch.last.global_position
17
+ end
18
+ end
19
+
20
+ def self.category?(stream_name)
21
+ !stream_name.include?('-')
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,17 @@
1
+ module MessageStore
2
+ module Controls
3
+ module MessageData
4
+ def self.id
5
+ ID::Random.example
6
+ end
7
+
8
+ def self.type
9
+ 'SomeType'
10
+ end
11
+
12
+ def self.data
13
+ { :attribute => RandomValue.example }
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,28 @@
1
+ module MessageStore
2
+ module Controls
3
+ module MessageData
4
+ module Hash
5
+ def self.data
6
+ {
7
+ some_attribute: 'some value'
8
+ }
9
+ end
10
+
11
+ def self.example
12
+ MessageStore::MessageData::Hash[data]
13
+ end
14
+
15
+ module JSON
16
+ def self.data(id=nil)
17
+ data = Hash.data
18
+ Casing::Camel.(data, symbol_to_string: true)
19
+ end
20
+
21
+ def self.text
22
+ ::JSON.generate(data)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ module MessageStore
2
+ module Controls
3
+ module MessageData
4
+ module Metadata
5
+ def self.data
6
+ {
7
+ meta_attribute: RandomValue.example
8
+ }
9
+ end
10
+
11
+ module JSON
12
+ def self.data(id=nil)
13
+ data = Metadata.data
14
+ Casing::Camel.(data, symbol_to_string: true)
15
+ end
16
+
17
+ def self.text
18
+ data.to_json
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,74 @@
1
+ module MessageStore
2
+ module Controls
3
+ module MessageData
4
+ module Read
5
+ def self.example(id: nil, type: nil, data: nil, metadata: nil)
6
+ if id == :none
7
+ id = nil
8
+ else
9
+ id ||= self.id
10
+ end
11
+
12
+ type ||= self.type
13
+
14
+ if data == :none
15
+ data = nil
16
+ else
17
+ data ||= self.data
18
+ end
19
+
20
+ if metadata == :none
21
+ metadata = nil
22
+ else
23
+ metadata ||= self.metadata
24
+ end
25
+
26
+ message_data = MessageStore::MessageData::Read.build
27
+
28
+ message_data.id = id
29
+ message_data.type = type
30
+ message_data.data = data
31
+ message_data.metadata = metadata
32
+ message_data.position = position
33
+ message_data.global_position = global_position
34
+ message_data.time = time
35
+ message_data.stream_name = stream_name
36
+
37
+ message_data
38
+ end
39
+
40
+ def self.id
41
+ MessageData.id
42
+ end
43
+
44
+ def self.type
45
+ MessageData.type
46
+ end
47
+
48
+ def self.data
49
+ MessageData.data
50
+ end
51
+
52
+ def self.metadata
53
+ MessageData::Metadata.data
54
+ end
55
+
56
+ def self.position
57
+ 1
58
+ end
59
+
60
+ def self.global_position
61
+ 111
62
+ end
63
+
64
+ def self.time
65
+ Time::Raw.example
66
+ end
67
+
68
+ def self.stream_name
69
+ StreamName.example
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,54 @@
1
+ module MessageStore
2
+ module Controls
3
+ module MessageData
4
+ module Write
5
+ def self.example(id: nil, type: nil, data: nil, metadata: nil)
6
+ if id == :none
7
+ id = nil
8
+ else
9
+ id ||= self.id
10
+ end
11
+
12
+ type ||= self.type
13
+
14
+ if data == :none
15
+ data = nil
16
+ else
17
+ data ||= self.data
18
+ end
19
+
20
+ if metadata == :none
21
+ metadata = nil
22
+ else
23
+ metadata ||= self.metadata
24
+ end
25
+
26
+ message_data = MessageStore::MessageData::Write.build
27
+
28
+ message_data.id = id
29
+ message_data.type = type
30
+ message_data.data = data
31
+ message_data.metadata = metadata
32
+
33
+ message_data
34
+ end
35
+
36
+ def self.id
37
+ MessageData.id
38
+ end
39
+
40
+ def self.type
41
+ MessageData.type
42
+ end
43
+
44
+ def self.data
45
+ MessageData.data
46
+ end
47
+
48
+ def self.metadata
49
+ MessageData::Metadata.data
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,9 @@
1
+ module MessageStore
2
+ module Controls
3
+ module RandomValue
4
+ def self.example
5
+ SecureRandom.hex
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,16 @@
1
+ module MessageStore
2
+ module Controls
3
+ module Read
4
+ def self.example(stream_name: nil)
5
+ stream_name ||= StreamName.example
6
+ Example.build(stream_name)
7
+ end
8
+
9
+ class Example
10
+ include MessageStore::Read
11
+
12
+ def configure(*); end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ module MessageStore
2
+ module Controls
3
+ module StreamName
4
+ def self.example(category: nil, id: nil, type: nil, types: nil, randomize_category: nil)
5
+ category ||= Category.example(category: category, randomize_category: randomize_category)
6
+ id ||= Identifier::UUID.random
7
+
8
+ stream_name(category, id, type: type, types: types)
9
+ end
10
+
11
+ def self.stream_name(category_name, id=nil, type: nil, types: nil)
12
+ types = Array(types)
13
+ types.unshift(type) unless type.nil?
14
+
15
+ type_list = nil
16
+ type_list = types.join('+') unless types.empty?
17
+
18
+ stream_name = category_name
19
+ stream_name = "#{stream_name}:#{type_list}" unless type_list.nil?
20
+ stream_name = "#{stream_name}-#{id}" unless id.nil?
21
+
22
+ stream_name
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+
29
+
@@ -0,0 +1,60 @@
1
+ module MessageStore
2
+ module Controls
3
+ module Time
4
+ def self.example(time=nil)
5
+ time ||= Raw.example
6
+ ISO8601.example(time)
7
+ end
8
+
9
+ module Raw
10
+ def self.example
11
+ time = ::Time.parse("Jan 1 00:00:00 UTC 2000")
12
+ Clock::UTC.now(time)
13
+ end
14
+ end
15
+
16
+ module ISO8601
17
+ def self.example(time=nil)
18
+ time ||= Raw.example
19
+ Clock::UTC.iso8601(time)
20
+ end
21
+ end
22
+
23
+ module Processed
24
+ def self.example(time=nil, offset_milliseconds: nil)
25
+ time ||= Time::Raw.example
26
+ time = Raw.example(time, offset_milliseconds: offset_milliseconds)
27
+ ISO8601.example(time)
28
+ end
29
+
30
+ module Raw
31
+ def self.example(time=nil, offset_milliseconds: nil)
32
+ time ||= Time::Raw.example
33
+ offset_milliseconds ||= 11
34
+ offset = Rational(offset_milliseconds, 1000)
35
+ time += offset
36
+ time
37
+ end
38
+ end
39
+ end
40
+
41
+ module Effective
42
+ def self.example(time=nil, offset_milliseconds: nil)
43
+ time ||= Time::Raw.example
44
+ time = Raw.example(time, offset_milliseconds: offset_milliseconds)
45
+ ISO8601.example(time)
46
+ end
47
+
48
+ module Raw
49
+ def self.example(time=nil, offset_milliseconds: nil)
50
+ time ||= Time::Raw.example
51
+ offset_milliseconds ||= 1
52
+ offset = Rational(offset_milliseconds, 1000)
53
+ time += offset
54
+ time
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,23 @@
1
+ module MessageStore
2
+ module Controls
3
+ module Write
4
+ def self.example
5
+ Example.build
6
+ end
7
+
8
+ class Example
9
+ include MessageStore::Write
10
+
11
+ def configure(*)
12
+ end
13
+
14
+ def write(batch, stream_name, expected_version: nil)
15
+ logger.trace { "Writing batch (Stream Name: #{stream_name}, Number of Events: #{batch.length}, Expected Version: #{expected_version.inspect})" }
16
+ logger.debug { "Wrote batch (Stream Name: #{stream_name}, Number of Events: #{batch.length}, Expected Version: #{expected_version.inspect})" }
17
+
18
+ nil
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ module MessageStore
2
+ module ExpectedVersion
3
+ class Error < RuntimeError; end
4
+
5
+ def self.canonize(expected_version)
6
+ return nil if expected_version.nil?
7
+ return expected_version unless expected_version == NoStream.name
8
+ NoStream.version
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,65 @@
1
+ module MessageStore
2
+ module Get
3
+ def self.included(cls)
4
+ cls.class_exec do
5
+ include Log::Dependency
6
+
7
+ abstract :call
8
+ end
9
+ end
10
+
11
+ class Substitute
12
+ include Get
13
+
14
+ initializer na(:batch_size)
15
+
16
+ def batch_size
17
+ @batch_size ||= 1
18
+ end
19
+
20
+ def items
21
+ @items ||= []
22
+ end
23
+
24
+ def self.build(batch_size: nil, session: nil)
25
+ new(batch_size)
26
+ end
27
+
28
+ def call(stream_name=nil, position: nil)
29
+ position ||= 0
30
+
31
+ logger.trace(tag: :control) { "Getting (Position: #{position}, Batch Size: #{batch_size}, Stream Name: #{stream_name.inspect})" }
32
+
33
+ logger.debug(tags: [:control, :data]) { "Items: \n#{items.pretty_inspect}" }
34
+ logger.debug(tag: :control) { "Position: #{position.inspect}" }
35
+ logger.debug(tag: :control) { "Batch Size: #{batch_size.inspect}" }
36
+
37
+ unless self.class.category?(stream_name)
38
+ index = (items.index { |i| i.position >= position })
39
+ else
40
+ index = (items.index { |i| i.global_position >= position })
41
+ end
42
+
43
+ logger.debug(tag: :control) { "Index: #{index.inspect}" }
44
+
45
+ if index.nil?
46
+ items = []
47
+ else
48
+ range = index..(index + batch_size - 1)
49
+ logger.debug(tag: :control) { "Range: #{range.pretty_inspect}" }
50
+
51
+ items = self.items[range]
52
+ end
53
+
54
+ logger.info(tags: [:control, :data]) { "Got: \n#{items.pretty_inspect}" }
55
+ logger.info(tag: :control) { "Finished getting (Position: #{position}, Stream Name: #{stream_name.inspect})" }
56
+
57
+ items
58
+ end
59
+
60
+ def self.category?(stream_name)
61
+ !stream_name.include?('-')
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,9 @@
1
+ module MessageStore
2
+ class Log < ::Log
3
+ def tag!(tags)
4
+ tags << :message_store
5
+ tags << :library
6
+ tags << :verbose
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ module MessageStore
2
+ module MessageData
3
+ def self.included(cls)
4
+ cls.class_exec do
5
+ include Schema::DataStructure
6
+
7
+ attribute :id, String
8
+ attribute :type, String
9
+ attribute :data
10
+ attribute :metadata
11
+
12
+ def ===(other)
13
+ type == other
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,31 @@
1
+ module MessageStore
2
+ module MessageData
3
+ class Hash < ::Hash
4
+ module Transformer
5
+ def self.json
6
+ JSON
7
+ end
8
+
9
+ def self.instance(raw_data)
10
+ Hash[raw_data]
11
+ end
12
+
13
+ def self.raw_data(instance)
14
+ Hash[instance]
15
+ end
16
+
17
+ module JSON
18
+ def self.write(raw_hash_data)
19
+ json_formatted_data = Casing::Camel.(raw_hash_data)
20
+ ::JSON.generate(json_formatted_data)
21
+ end
22
+
23
+ def self.read(text)
24
+ json_formatted_data = ::JSON.parse(text, :symbolize_names => true)
25
+ Casing::Underscore.(json_formatted_data)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,12 @@
1
+ module MessageStore
2
+ module MessageData
3
+ class Read
4
+ include MessageData
5
+
6
+ attribute :stream_name, String
7
+ attribute :position, Integer
8
+ attribute :global_position, Integer
9
+ attribute :time, Time
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ module MessageStore
2
+ module MessageData
3
+ class Write
4
+ include MessageData
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ module MessageStore
2
+ module NoStream
3
+ def self.name
4
+ :no_stream
5
+ end
6
+
7
+ def self.version
8
+ -1
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,76 @@
1
+ module MessageStore
2
+ module Read
3
+ def self.included(cls)
4
+ cls.class_exec do
5
+ include Log::Dependency
6
+
7
+ cls.extend Build
8
+ cls.extend Call
9
+ cls.extend Configure
10
+
11
+ dependency :iterator, Iterator
12
+
13
+ initializer :stream_name, :position, :batch_size
14
+
15
+ abstract :configure
16
+ end
17
+ end
18
+
19
+ class Error < RuntimeError; end
20
+
21
+ module Build
22
+ def build(stream_name, position: nil, batch_size: nil, session: nil)
23
+ new(stream_name, position, batch_size).tap do |instance|
24
+ instance.configure(session: session)
25
+ end
26
+ end
27
+ end
28
+
29
+ module Call
30
+ def call(stream_name, position: nil, batch_size: nil, session: nil, &action)
31
+ instance = build(stream_name, position: position, batch_size: batch_size, session: session)
32
+ instance.(&action)
33
+ end
34
+ end
35
+
36
+ module Configure
37
+ def configure(receiver, stream_name, attr_name: nil, position: nil, batch_size: nil, session: nil)
38
+ attr_name ||= :read
39
+ instance = build(stream_name, position: position, batch_size: batch_size, session: session)
40
+ receiver.public_send "#{attr_name}=", instance
41
+ end
42
+ end
43
+
44
+ def call(&action)
45
+ logger.trace { "Reading (Stream Name: #{stream_name})" }
46
+
47
+ if action.nil?
48
+ error_message = "Reader must be actuated with a block"
49
+ logger.error error_message
50
+ raise Error, error_message
51
+ end
52
+
53
+ enumerate_message_data(&action)
54
+
55
+ logger.info { "Reading completed (Stream Name: #{stream_name})" }
56
+
57
+ return AsyncInvocation::Incorrect
58
+ end
59
+
60
+ def enumerate_message_data(&action)
61
+ logger.trace { "Enumerating (Stream Name: #{stream_name})" }
62
+
63
+ message_data = nil
64
+
65
+ loop do
66
+ message_data = iterator.next
67
+
68
+ break if message_data.nil?
69
+
70
+ action.(message_data)
71
+ end
72
+
73
+ logger.debug { "Enumerated (Stream Name: #{stream_name})" }
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,143 @@
1
+ module MessageStore
2
+ module Read
3
+ module Iterator
4
+ def self.included(cls)
5
+ cls.class_exec do
6
+ cls.extend Build
7
+ cls.extend Configure
8
+
9
+ include Log::Dependency
10
+
11
+ dependency :get, Get
12
+
13
+ initializer :stream_name
14
+
15
+ abstract :last_position
16
+ end
17
+ end
18
+
19
+ attr_accessor :starting_position
20
+ attr_accessor :batch
21
+
22
+ def batch_index
23
+ @batch_index ||= 0
24
+ end
25
+ attr_writer :batch_index
26
+
27
+ module Build
28
+ def build(stream_name, position: nil)
29
+ new(stream_name).tap do |instance|
30
+ instance.starting_position = position
31
+ Log.get(self).debug { "Built Iterator (Stream Name: #{stream_name}, Starting Position: #{position.inspect})" }
32
+ end
33
+ end
34
+ end
35
+
36
+ module Configure
37
+ def configure(receiver, stream_name, attr_name: nil, position: nil)
38
+ attr_name ||= :iterator
39
+ instance = build(stream_name, position: position)
40
+ receiver.public_send "#{attr_name}=", instance
41
+ end
42
+ end
43
+
44
+ def next
45
+ logger.trace { "Getting next event data (Batch Length: #{(batch &.length).inspect}, Batch Index: #{batch_index})" }
46
+
47
+ resupply if batch_depleted?
48
+
49
+ message_data = batch[batch_index]
50
+
51
+ logger.debug(tags: [:data, :message_data]) { "Next event data: #{message_data.pretty_inspect}" }
52
+ logger.debug { "Done getting next event data (Batch Length: #{(batch &.length).inspect}, Batch Index: #{batch_index})" }
53
+
54
+ advance_batch_index
55
+
56
+ message_data
57
+ end
58
+
59
+ def advance_batch_index
60
+ logger.trace { "Advancing batch index (Batch Index: #{batch_index})" }
61
+ self.batch_index += 1
62
+ logger.debug { "Advanced batch index (Batch Index: #{batch_index})" }
63
+ end
64
+
65
+ def batch_depleted?
66
+ if batch.nil?
67
+ logger.debug { "Batch is depleted (Batch is nil)" }
68
+ return true
69
+ end
70
+
71
+ if batch.empty?
72
+ logger.debug { "Batch is depleted (Batch is empty)" }
73
+ return true
74
+ end
75
+
76
+ if batch_index == batch.length
77
+ logger.debug { "Batch is depleted (Batch Index: #{batch_index}, Batch Length: #{batch.length})" }
78
+ return true
79
+ end
80
+
81
+ false
82
+ end
83
+
84
+ def resupply
85
+ logger.trace { "Resupplying batch (Current Batch Length: #{(batch &.length).inspect})" }
86
+
87
+ batch = get_batch
88
+ reset(batch)
89
+
90
+ logger.debug { "Batch resupplied (Next Batch Length: #{(batch &.length).inspect})" }
91
+ end
92
+
93
+ def get_batch
94
+ position = next_batch_starting_position
95
+
96
+ logger.trace "Getting batch (Position: #{position.inspect})"
97
+
98
+ batch = []
99
+ if position.nil? || position >= 0
100
+ batch = get.(stream_name, position: position)
101
+ end
102
+
103
+ logger.debug { "Finished getting batch (Count: #{batch.length}, Position: #{position.inspect})" }
104
+
105
+ batch
106
+ end
107
+
108
+ def next_batch_starting_position
109
+ if batch.nil?
110
+ logger.debug { "Batch is nil (Next batch starting position: #{starting_position.inspect})" }
111
+ return starting_position
112
+ end
113
+
114
+ previous_position = last_position
115
+ next_position = previous_position + 1
116
+ logger.debug { "End of batch (Next starting position: #{next_position}, Previous Position: #{previous_position})" }
117
+
118
+ next_position
119
+ end
120
+
121
+ def reset(batch)
122
+ logger.trace { "Resetting batch" }
123
+
124
+ self.batch = batch
125
+ self.batch_index = 0
126
+
127
+ logger.debug(tags: [:data, :batch]) { "Batch set to: \n#{batch.pretty_inspect}" }
128
+ logger.debug(tags: [:data, :batch]) { "Batch position set to: #{batch_index.inspect}" }
129
+ logger.debug { "Done resetting batch" }
130
+ end
131
+
132
+ class Substitute
133
+ include Read::Iterator
134
+
135
+ initializer :stream_name
136
+
137
+ def self.build()
138
+ new('some_stream_name')
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,50 @@
1
+ module MessageStore
2
+ module StreamName
3
+ def self.stream_name(category_name, id=nil, type: nil, types: nil)
4
+ types = Array(types)
5
+ types.unshift(type) unless type.nil?
6
+
7
+ type_list = nil
8
+ type_list = types.join('+') unless types.empty?
9
+
10
+ stream_name = category_name
11
+ stream_name = "#{stream_name}:#{type_list}" unless type_list.nil?
12
+ stream_name = "#{stream_name}-#{id}" unless id.nil?
13
+
14
+ stream_name
15
+ end
16
+
17
+ def self.get_id(stream_name)
18
+ id = stream_name.partition('-').last
19
+ id.empty? ? nil : id
20
+ end
21
+
22
+ def self.get_category(stream_name)
23
+ stream_name.split('-').first
24
+ end
25
+
26
+ def self.category?(stream_name)
27
+ !stream_name.include?('-')
28
+ end
29
+
30
+ def self.get_type_list(stream_name)
31
+ type = stream_name.split(':').last.split('-').first
32
+
33
+ return nil if stream_name.start_with?(type)
34
+
35
+ type
36
+ end
37
+
38
+ def self.get_types(stream_name)
39
+ type_list = get_type_list(stream_name)
40
+
41
+ return [] if type_list.nil?
42
+
43
+ type_list.split('+')
44
+ end
45
+
46
+ def self.get_entity_name(stream_name)
47
+ get_category(stream_name).split(':').first
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,66 @@
1
+ module MessageStore
2
+ module Write
3
+ def self.included(cls)
4
+ cls.class_exec do
5
+ include Log::Dependency
6
+
7
+ cls.extend Build
8
+ cls.extend Call
9
+ cls.extend Configure
10
+
11
+ dependency :identifier, Identifier::UUID::Random
12
+
13
+ abstract :configure
14
+ abstract :write
15
+ end
16
+ end
17
+
18
+ module Build
19
+ def build(session: nil)
20
+ instance = new
21
+ Identifier::UUID::Random.configure(instance)
22
+ instance.configure(session: session)
23
+ instance
24
+ end
25
+ end
26
+
27
+ module Configure
28
+ def configure(receiver, session: nil, attr_name: nil)
29
+ attr_name ||= :write
30
+ instance = build(session: session)
31
+ receiver.public_send "#{attr_name}=", instance
32
+ end
33
+ end
34
+
35
+ module Call
36
+ def call(message_data, stream_name, expected_version: nil, session: nil)
37
+ instance = build(session: session)
38
+ instance.(message_data, stream_name, expected_version: expected_version)
39
+ end
40
+ end
41
+
42
+ def call(message_data, stream_name, expected_version: nil)
43
+ logger.trace(tag: :write) { "Writing event data (Stream Name: #{stream_name}, Expected Version: #{expected_version.inspect})" }
44
+ logger.trace(tags: [:data, :message_data, :write]) { message_data.pretty_inspect }
45
+
46
+ batch = Array(message_data)
47
+
48
+ set_ids(batch)
49
+
50
+ position = write(batch, stream_name, expected_version: expected_version)
51
+
52
+ logger.info(tag: :write) { "Wrote event data (Stream Name: #{stream_name}, Expected Version: #{expected_version.inspect})" }
53
+ logger.info(tags: [:data, :message_data, :write]) { message_data.pretty_inspect }
54
+
55
+ position
56
+ end
57
+
58
+ def set_ids(batch)
59
+ batch.each do |message_data|
60
+ if message_data.id.nil?
61
+ message_data.id = identifier.get
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: evt-message_store
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - The Eventide Project
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: evt-casing
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: evt-schema
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: evt-initializer
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: evt-identifier-uuid
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: evt-transform
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: evt-virtual
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: evt-async_invocation
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: test_bench
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: " "
126
+ email: opensource@eventide-project.org
127
+ executables: []
128
+ extensions: []
129
+ extra_rdoc_files: []
130
+ files:
131
+ - lib/message_store.rb
132
+ - lib/message_store/controls.rb
133
+ - lib/message_store/controls/category.rb
134
+ - lib/message_store/controls/get.rb
135
+ - lib/message_store/controls/id.rb
136
+ - lib/message_store/controls/iterator.rb
137
+ - lib/message_store/controls/message_data.rb
138
+ - lib/message_store/controls/message_data/hash.rb
139
+ - lib/message_store/controls/message_data/metadata.rb
140
+ - lib/message_store/controls/message_data/read.rb
141
+ - lib/message_store/controls/message_data/write.rb
142
+ - lib/message_store/controls/random_value.rb
143
+ - lib/message_store/controls/read.rb
144
+ - lib/message_store/controls/stream_name.rb
145
+ - lib/message_store/controls/time.rb
146
+ - lib/message_store/controls/write.rb
147
+ - lib/message_store/expected_version.rb
148
+ - lib/message_store/get.rb
149
+ - lib/message_store/log.rb
150
+ - lib/message_store/message_data.rb
151
+ - lib/message_store/message_data/hash.rb
152
+ - lib/message_store/message_data/read.rb
153
+ - lib/message_store/message_data/write.rb
154
+ - lib/message_store/no_stream.rb
155
+ - lib/message_store/read.rb
156
+ - lib/message_store/read/iterator.rb
157
+ - lib/message_store/stream_name.rb
158
+ - lib/message_store/write.rb
159
+ homepage: https://github.com/eventide-project/message-store
160
+ licenses:
161
+ - MIT
162
+ metadata: {}
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: 2.4.0
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements: []
178
+ rubyforge_project:
179
+ rubygems_version: 2.6.11
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: Common primitives for platform-specific message store implementations
183
+ test_files: []