evt-message_store 0.1.0.0

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