evt-message_store-postgres 1.2.0.0 → 2.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77c708beeefed6f49a2a8df231fc7d8bb84ef2dd75982dc602cb5b6893662869
4
- data.tar.gz: 3255fa00e94215b04d61fac3054ad4db43e64813c266232cf333e79345d7f49d
3
+ metadata.gz: 8c3e7d86d082e713d0debacaf4eeb24634c60e841ae3cc91f1ceccd09bce6ecc
4
+ data.tar.gz: 1aea92a3b91743c6e4b0b77fc7c18820f390fb65b52afeef6e76f734584f6f7b
5
5
  SHA512:
6
- metadata.gz: 6b1e8f43a95d701db50f9c21964a52acebe8c435b11c91befb6a0e1c1cdf25b8a33f50d0457f1a4af0f34cfd6d426eb2bd918fef8c953af4deabd861a45ee0a4
7
- data.tar.gz: 5e63109d9eb4a60f9c2af6c50ee4adca1929fd224defbe558d47e96c5264ebb884553235cbf5962f9f3d1575fefa9f49ec58d10f4795143ba160a94a9dad67a4
6
+ metadata.gz: 62925f4b042b580ffa05ff79f2e23a71f8db57bb815bc906fe287964095695406ba0c2e5a94ba950b29f51c420d29118484c86b62568db2713f78d590fbddbd1
7
+ data.tar.gz: 07cb98b54f68eec14673b87382a4affb49ea59bfbddc1c2b1f6984aa5ea15c60194e62637dce6774893037580133ed306b83b493d6031b648d8fdbad34235117
@@ -15,7 +15,10 @@ require 'message_store/postgres/put'
15
15
  require 'message_store/postgres/write'
16
16
 
17
17
  require 'message_store/postgres/get'
18
+ require 'message_store/postgres/get/condition'
18
19
  require 'message_store/postgres/get/stream'
19
- require 'message_store/postgres/get/category'
20
20
  require 'message_store/postgres/get/stream/last'
21
+ require 'message_store/postgres/get/category'
22
+ require 'message_store/postgres/get/category/correlation'
23
+ require 'message_store/postgres/get/category/consumer_group'
21
24
  require 'message_store/postgres/read'
@@ -1,25 +1,7 @@
1
1
  module MessageStore
2
2
  module Postgres
3
3
  module Controls
4
- module Category
5
- def self.example(category: nil, randomize_category: nil)
6
- if randomize_category.nil?
7
- if !category.nil?
8
- randomize_category = false
9
- end
10
- end
11
-
12
- randomize_category = true if randomize_category.nil?
13
-
14
- category ||= 'test'
15
-
16
- if randomize_category
17
- category = "#{category}#{SecureRandom.hex(16)}XX"
18
- end
19
-
20
- category
21
- end
22
- end
4
+ Category = MessageStore::Controls::Category
23
5
  end
24
6
  end
25
7
  end
@@ -2,20 +2,21 @@ module MessageStore
2
2
  module Postgres
3
3
  module Controls
4
4
  module Put
5
- def self.call(instances: nil, stream_name: nil, message: nil, category: nil)
5
+ def self.call(instances: nil, stream_name: nil, message_data: nil, message: nil, category: nil)
6
6
  instances ||= 1
7
7
  stream_name ||= StreamName.example(category: category)
8
+ message_data ||= message
8
9
 
9
- message_specified = !message.nil?
10
+ message_specified = !message_data.nil?
10
11
 
11
- message ||= MessageData::Write.example
12
+ message_data ||= MessageData::Write.example
12
13
 
13
14
  position = nil
14
15
  instances.times do
15
- position = MessageStore::Postgres::Put.(message, stream_name)
16
+ position = MessageStore::Postgres::Put.(message_data, stream_name)
16
17
 
17
18
  unless message_specified
18
- message.id = MessageData::Write.id
19
+ message_data.id = MessageData::Write.id
19
20
  end
20
21
  end
21
22
 
@@ -4,14 +4,22 @@ module MessageStore
4
4
  def self.included(cls)
5
5
  cls.class_exec do
6
6
  include MessageStore::Get
7
+
7
8
  prepend Call
8
9
  prepend BatchSize
9
10
 
10
- extend SQLCommand
11
-
12
11
  dependency :session, Session
13
12
 
14
- initializer :stream_name, na(:batch_size), :condition
13
+ abstract :configure
14
+ abstract :stream_name
15
+ abstract :sql_command
16
+ abstract :parameters
17
+ abstract :parameter_values
18
+ abstract :last_position
19
+ abstract :log_text
20
+
21
+ virtual :specialize_error
22
+ virtual :assure
15
23
  end
16
24
  end
17
25
 
@@ -21,40 +29,49 @@ module MessageStore
21
29
  end
22
30
  end
23
31
 
24
- def self.build(stream_name, batch_size: nil, session: nil, condition: nil)
32
+ def self.build(stream_name, **args)
25
33
  cls = specialization(stream_name)
26
34
 
27
- cls.new(stream_name, batch_size, condition).tap do |instance|
35
+ session = args.delete(:session)
36
+
37
+ cls.build(stream_name, **args).tap do |instance|
28
38
  instance.configure(session: session)
29
39
  end
30
40
  end
31
41
 
32
- def self.configure(receiver, stream_name, attr_name: nil, batch_size: nil, condition: nil, session: nil)
42
+ def self.configure(receiver, stream_name, **args)
43
+ attr_name = args.delete(:attr_name)
33
44
  attr_name ||= :get
34
- instance = build(stream_name, batch_size: batch_size, condition: condition, session: session)
35
- receiver.public_send "#{attr_name}=", instance
45
+
46
+ instance = build(stream_name, **args)
47
+ receiver.public_send("#{attr_name}=", instance)
36
48
  end
37
49
 
38
50
  def configure(session: nil)
39
- Session.configure self, session: session
51
+ Session.configure(self, session: session)
40
52
  end
41
53
 
42
- def self.call(stream_name, position: nil, batch_size: nil, condition: nil, session: nil)
43
- instance = build(stream_name, batch_size: batch_size, condition: condition, session: session)
54
+ def self.call(stream_name, **args)
55
+ position = args.delete(:position)
56
+ instance = build(stream_name, **args)
44
57
  instance.(position)
45
58
  end
46
59
 
47
60
  module Call
48
- def call(position)
49
- logger.trace(tag: :get) { "Getting message data (Stream Name: #{stream_name}, Position: #{position.inspect}, Batch Size: #{batch_size.inspect})" }
61
+ def call(position=nil, stream_name: nil)
62
+ position ||= self.class::Defaults.position
63
+
64
+ stream_name ||= self.stream_name
50
65
 
51
- position ||= Defaults.position
66
+ assure
67
+
68
+ logger.trace(tag: :get) { "Getting message data (#{log_text(stream_name, position)})" }
52
69
 
53
70
  result = get_result(stream_name, position)
54
71
 
55
72
  message_data = convert(result)
56
73
 
57
- logger.info(tag: :get) { "Finished getting message data (Count: #{message_data.length}, Stream Name: #{stream_name}, Position: #{position.inspect}, Batch Size: #{batch_size.inspect})" }
74
+ logger.info(tag: :get) { "Finished getting message data (Count: #{message_data.length}, #{log_text(stream_name, position)})" }
58
75
  logger.info(tags: [:data, :message_data]) { message_data.pretty_inspect }
59
76
 
60
77
  message_data
@@ -62,53 +79,60 @@ module MessageStore
62
79
  end
63
80
 
64
81
  def get_result(stream_name, position)
65
- logger.trace(tag: :get) { "Getting result (Stream Name: #{stream_name}, Position: #{position.inspect}, Batch Size: #{batch_size.inspect}, Condition: #{condition || '(none)'})" }
66
-
67
- sql_command = self.class.sql_command(stream_name, position, batch_size, condition)
82
+ logger.trace(tag: :get) { "Getting result (#{log_text(stream_name, position)})" }
68
83
 
69
- cond = Get.constrain_condition(condition)
84
+ parameter_values = parameter_values(stream_name, position)
70
85
 
71
- params = [
72
- stream_name,
73
- position,
74
- batch_size,
75
- cond
76
- ]
77
-
78
- result = session.execute(sql_command, params)
86
+ begin
87
+ result = session.execute(sql_command, parameter_values)
88
+ rescue PG::RaiseException => e
89
+ raise_error(e)
90
+ end
79
91
 
80
- logger.debug(tag: :get) { "Finished getting result (Count: #{result.ntuples}, Stream Name: #{stream_name}, Position: #{position.inspect}, Batch Size: #{batch_size.inspect}, Condition: #{condition || '(none)'})" }
92
+ logger.debug(tag: :get) { "Finished getting result (Count: #{result.ntuples}, #{log_text(stream_name, position)})" }
81
93
 
82
94
  result
83
95
  end
84
96
 
85
- def self.constrain_condition(condition)
86
- return nil if condition.nil?
97
+ def convert(result)
98
+ logger.trace(tag: :get) { "Converting result to message data (Result Count: #{result.ntuples})" }
99
+
100
+ message_data = result.map do |record|
101
+ Get.message_data(record)
102
+ end
103
+
104
+ logger.debug(tag: :get) { "Converted result to message data (Message Data Count: #{message_data.length})" }
87
105
 
88
- "(#{condition})"
106
+ message_data
89
107
  end
90
108
 
91
- module SQLCommand
92
- def sql_command(stream_name, position, batch_size, condition)
93
- parameters = '$1::varchar, $2::bigint, $3::bigint, $4::varchar'
94
- command_text(parameters)
95
- end
109
+ def self.message_data(record)
110
+ record['data'] = Get::Deserialize.data(record['data'])
111
+ record['metadata'] = Get::Deserialize.metadata(record['metadata'])
112
+ record['time'] = Get::Time.utc_coerced(record['time'])
113
+
114
+ MessageData::Read.build(record)
96
115
  end
97
116
 
98
- def convert(result)
99
- logger.trace(tag: :get) { "Converting result to message data (Result Count: #{result.ntuples})" }
117
+ def raise_error(pg_error)
118
+ error_message = Get.error_message(pg_error)
100
119
 
101
- message_data = result.map do |record|
102
- record['data'] = Deserialize.data(record['data'])
103
- record['metadata'] = Deserialize.metadata(record['metadata'])
104
- record['time'] = Time.utc_coerced(record['time'])
120
+ error = Condition.error(error_message)
105
121
 
106
- MessageData::Read.build(record)
122
+ if error.nil?
123
+ error = specialize_error(error_message)
107
124
  end
108
125
 
109
- logger.debug(tag: :get) { "Converted result to message data (Message Data Count: #{message_data.length})" }
126
+ if not error.nil?
127
+ logger.error { error_message }
128
+ raise error
129
+ end
110
130
 
111
- message_data
131
+ raise pg_error
132
+ end
133
+
134
+ def self.error_message(pg_error)
135
+ pg_error.message.gsub('ERROR:', '').strip
112
136
  end
113
137
 
114
138
  def self.specialization(stream_name)
@@ -138,10 +162,6 @@ module MessageStore
138
162
  end
139
163
 
140
164
  module Defaults
141
- def self.position
142
- 0
143
- end
144
-
145
165
  def self.batch_size
146
166
  1000
147
167
  end
@@ -2,15 +2,83 @@ module MessageStore
2
2
  module Postgres
3
3
  module Get
4
4
  class Category
5
+ Error = Class.new(RuntimeError)
6
+
5
7
  include Get
6
8
 
7
- def self.command_text(parameters)
9
+ initializer :category, na(:batch_size), :correlation, :consumer_group_member, :consumer_group_size, :condition
10
+ alias :stream_name :category
11
+
12
+ def self.call(category, position: nil, batch_size: nil, correlation: nil, consumer_group_member: nil, consumer_group_size: nil, condition: nil, session: nil)
13
+ instance = build(category, batch_size: batch_size, correlation: correlation, consumer_group_member: consumer_group_member, consumer_group_size: consumer_group_size, condition: condition, session: session)
14
+ instance.(position)
15
+ end
16
+
17
+ def self.build(category, batch_size: nil, correlation: nil, consumer_group_member: nil, consumer_group_size: nil, condition: nil, session: nil)
18
+ instance = new(category, batch_size, correlation, consumer_group_member, consumer_group_size, condition)
19
+ instance.configure(session: session)
20
+ instance
21
+ end
22
+
23
+ def self.configure(receiver, category, attr_name: nil, batch_size: nil, correlation: nil, consumer_group_member: nil, consumer_group_size: nil, condition: nil, session: nil)
24
+ attr_name ||= :get
25
+ instance = build(category, batch_size: batch_size, correlation: correlation, consumer_group_member: consumer_group_member, consumer_group_size: consumer_group_size, condition: condition, session: session)
26
+ receiver.public_send("#{attr_name}=", instance)
27
+ end
28
+
29
+ def configure(session: nil)
30
+ Session.configure(self, session: session)
31
+ end
32
+
33
+ def sql_command
8
34
  "SELECT * FROM get_category_messages(#{parameters});"
9
35
  end
10
36
 
37
+ def parameters
38
+ '$1::varchar, $2::bigint, $3::bigint, $4::varchar, $5::bigint, $6::bigint, $7::varchar'
39
+ end
40
+
41
+ def parameter_values(category, position)
42
+ [
43
+ category,
44
+ position,
45
+ batch_size,
46
+ correlation,
47
+ consumer_group_member,
48
+ consumer_group_size,
49
+ condition
50
+ ]
51
+ end
52
+
11
53
  def last_position(batch)
12
54
  batch.last.global_position
13
55
  end
56
+
57
+ def specialize_error(error_message)
58
+ error = Correlation.error(error_message)
59
+
60
+ if error.nil?
61
+ error = ConsumerGroup.error(error_message)
62
+ end
63
+
64
+ error
65
+ end
66
+
67
+ def log_text(category, position)
68
+ "Category: #{category}, Position: #{position.inspect}, Batch Size: #{batch_size.inspect}, Correlation: #{correlation.inspect}, Consumer Group Member: #{consumer_group_member.inspect}, Consumer Group Size: #{consumer_group_size.inspect}, Condition: #{condition.inspect})"
69
+ end
70
+
71
+ def assure
72
+ if not MessageStore::StreamName.category?(category)
73
+ raise Error, "Must be a category (Stream Name: #{category})"
74
+ end
75
+ end
76
+
77
+ module Defaults
78
+ def self.position
79
+ 1
80
+ end
81
+ end
14
82
  end
15
83
  end
16
84
  end
@@ -0,0 +1,20 @@
1
+ module MessageStore
2
+ module Postgres
3
+ module Get
4
+ class Category
5
+ module ConsumerGroup
6
+ Error = Class.new(RuntimeError)
7
+
8
+ def self.error(error_message)
9
+ if error_message.start_with?('Consumer group size must not be less than 1') ||
10
+ error_message.start_with?('Consumer group member must be less than the group size') ||
11
+ error_message.start_with?('Consumer group member must not be less than 0') ||
12
+ error_message.start_with?('Consumer group member and size must be specified')
13
+ Error.new(error_message)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,17 @@
1
+ module MessageStore
2
+ module Postgres
3
+ module Get
4
+ class Category
5
+ module Correlation
6
+ Error = Class.new(RuntimeError)
7
+
8
+ def self.error(error_message)
9
+ if error_message.start_with?('Correlation must be a category')
10
+ Error.new(error_message)
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ module MessageStore
2
+ module Postgres
3
+ module Get
4
+ module Condition
5
+ Error = Class.new(RuntimeError)
6
+
7
+ def self.error(error_message)
8
+ if error_message.start_with?('Retrieval with SQL condition is not activated')
9
+ Get::Condition::Error.new(error_message)
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,15 +2,69 @@ module MessageStore
2
2
  module Postgres
3
3
  module Get
4
4
  class Stream
5
+ Error = Class.new(RuntimeError)
6
+
5
7
  include Get
6
8
 
7
- def self.command_text(parameters)
9
+ initializer :stream_name, na(:batch_size), :condition
10
+
11
+ def self.call(stream_name, position: nil, batch_size: nil, condition: nil, session: nil)
12
+ instance = build(stream_name, batch_size: batch_size, condition: condition, session: session)
13
+ instance.(position)
14
+ end
15
+
16
+ def self.build(stream_name, batch_size: nil, condition: nil, session: nil)
17
+ instance = new(stream_name, batch_size, condition)
18
+ instance.configure(session: session)
19
+ instance
20
+ end
21
+
22
+ def self.configure(receiver, stream_name, attr_name: nil, batch_size: nil, condition: nil, session: nil)
23
+ attr_name ||= :get
24
+ instance = build(stream_name, batch_size: batch_size, condition: condition, session: session)
25
+ receiver.public_send("#{attr_name}=", instance)
26
+ end
27
+
28
+ def configure(session: nil)
29
+ Session.configure(self, session: session)
30
+ end
31
+
32
+ def sql_command
8
33
  "SELECT * FROM get_stream_messages(#{parameters});"
9
34
  end
10
35
 
36
+ def parameters
37
+ '$1::varchar, $2::bigint, $3::bigint, $4::varchar'
38
+ end
39
+
40
+ def parameter_values(stream_name, position)
41
+ [
42
+ stream_name,
43
+ position,
44
+ batch_size,
45
+ condition
46
+ ]
47
+ end
48
+
11
49
  def last_position(batch)
12
50
  batch.last.position
13
51
  end
52
+
53
+ def log_text(stream_name, position)
54
+ "Stream Name: #{stream_name}, Position: #{position.inspect}, Batch Size: #{batch_size.inspect}, Correlation: #{correlation.inspect}, Condition: #{condition.inspect})"
55
+ end
56
+
57
+ def assure
58
+ if MessageStore::StreamName.category?(stream_name)
59
+ raise Error, "Must be a stream name (Category: #{stream_name})"
60
+ end
61
+ end
62
+
63
+ module Defaults
64
+ def self.position
65
+ 0
66
+ end
67
+ end
14
68
  end
15
69
  end
16
70
  end
@@ -31,11 +31,11 @@ module MessageStore
31
31
 
32
32
  sql_command = self.class.sql_command(stream_name)
33
33
 
34
- params = [
34
+ parameter_values = [
35
35
  stream_name
36
36
  ]
37
37
 
38
- result = session.execute(sql_command, params)
38
+ result = session.execute(sql_command, parameter_values)
39
39
 
40
40
  logger.debug(tag: :get) { "Finished getting result (Count: #{result.ntuples}, Stream: #{stream_name}" }
41
41
 
@@ -47,40 +47,18 @@ module MessageStore
47
47
  def self.sql_command(stream_name)
48
48
  parameters = '$1::varchar'
49
49
 
50
- "SELECT * FROM get_last_message(#{parameters});"
50
+ "SELECT * FROM get_last_stream_message(#{parameters});"
51
51
  end
52
52
 
53
53
  def convert(record)
54
54
  logger.trace(tag: :get) { "Converting record to message data" }
55
55
 
56
- record['data'] = Deserialize.data(record['data'])
57
- record['metadata'] = Deserialize.metadata(record['metadata'])
58
- record['time'] = Time.utc_coerced(record['time'])
59
-
60
- message_data = MessageData::Read.build(record)
56
+ message_data = Get.message_data(record)
61
57
 
62
58
  logger.debug(tag: :get) { "Converted record to message data" }
63
59
 
64
60
  message_data
65
61
  end
66
-
67
- module Deserialize
68
- def self.data(serialized_data)
69
- return nil if serialized_data.nil?
70
- Transform::Read.(serialized_data, :json, MessageData::Hash)
71
- end
72
-
73
- def self.metadata(serialized_metadata)
74
- return nil if serialized_metadata.nil?
75
- Transform::Read.(serialized_metadata, :json, MessageData::Hash)
76
- end
77
- end
78
-
79
- module Time
80
- def self.utc_coerced(local_time)
81
- Clock::UTC.coerce(local_time)
82
- end
83
- end
84
62
  end
85
63
  end
86
64
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: evt-message_store-postgres
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0.0
4
+ version: 2.3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Eventide Project
8
8
  autorequire:
9
9
  bindir: scripts
10
10
  cert_chain: []
11
- date: 2019-11-01 00:00:00.000000000 Z
11
+ date: 2019-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: evt-message_store
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: evt-message_store-postgres-database
28
+ name: evt-log
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: evt-log
42
+ name: evt-settings
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: evt-settings
56
+ name: message-db
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -137,6 +137,9 @@ files:
137
137
  - lib/message_store/postgres/controls/stream_name.rb
138
138
  - lib/message_store/postgres/get.rb
139
139
  - lib/message_store/postgres/get/category.rb
140
+ - lib/message_store/postgres/get/category/consumer_group.rb
141
+ - lib/message_store/postgres/get/category/correlation.rb
142
+ - lib/message_store/postgres/get/condition.rb
140
143
  - lib/message_store/postgres/get/stream.rb
141
144
  - lib/message_store/postgres/get/stream/last.rb
142
145
  - lib/message_store/postgres/log.rb