evt-message_store-postgres 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 +7 -0
- data/database/clear-events-table.sh +40 -0
- data/database/extensions.sql +1 -0
- data/database/functions/category.sql +10 -0
- data/database/functions/stream-version.sql +13 -0
- data/database/functions/write-event.sql +55 -0
- data/database/indexes/events-category-global-position.sql +1 -0
- data/database/indexes/events-category.sql +1 -0
- data/database/indexes/events-id.sql +1 -0
- data/database/indexes/events-stream-name-position-uniq.sql +1 -0
- data/database/indexes/events-stream-name.sql +1 -0
- data/database/install.sh +103 -0
- data/database/list-events.sh +52 -0
- data/database/table/events-table.sql +19 -0
- data/database/test/write-event-expected-version.sql +1 -0
- data/database/test/write-event.sql +1 -0
- data/database/uninstall.sh +60 -0
- data/lib/message_store/postgres.rb +24 -0
- data/lib/message_store/postgres/controls.rb +6 -0
- data/lib/message_store/postgres/controls/category.rb +34 -0
- data/lib/message_store/postgres/controls/message_data.rb +7 -0
- data/lib/message_store/postgres/controls/put.rb +26 -0
- data/lib/message_store/postgres/controls/stream_name.rb +22 -0
- data/lib/message_store/postgres/get.rb +91 -0
- data/lib/message_store/postgres/get/last.rb +111 -0
- data/lib/message_store/postgres/get/last/select_statement.rb +47 -0
- data/lib/message_store/postgres/get/select_statement.rb +88 -0
- data/lib/message_store/postgres/log.rb +11 -0
- data/lib/message_store/postgres/put.rb +145 -0
- data/lib/message_store/postgres/read.rb +12 -0
- data/lib/message_store/postgres/read/iterator.rb +17 -0
- data/lib/message_store/postgres/session.rb +128 -0
- data/lib/message_store/postgres/settings.rb +30 -0
- data/lib/message_store/postgres/stream_name.rb +52 -0
- data/lib/message_store/postgres/write.rb +46 -0
- data/scripts/evt-pg-create-db +7 -0
- data/scripts/evt-pg-delete-db +7 -0
- data/scripts/evt-pg-list-events +7 -0
- data/scripts/evt-pg-recreate-db +11 -0
- data/scripts/scripts_init.rb +12 -0
- metadata +156 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
module MessageStore
|
2
|
+
module Postgres
|
3
|
+
module Controls
|
4
|
+
module Put
|
5
|
+
def self.call(instances: nil, stream_name: nil, message: nil, category: nil)
|
6
|
+
instances ||= 1
|
7
|
+
stream_name ||= StreamName.example(category: category)
|
8
|
+
|
9
|
+
message_specified = !message.nil?
|
10
|
+
|
11
|
+
message ||= MessageData::Write.example
|
12
|
+
|
13
|
+
instances.times do
|
14
|
+
MessageStore::Postgres::Put.(message, stream_name)
|
15
|
+
|
16
|
+
unless message_specified
|
17
|
+
message.id = MessageData::Write.id
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
stream_name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# module MessageStore
|
2
|
+
# module Postgres
|
3
|
+
# module Controls
|
4
|
+
# StreamName = MessageStore::Controls::StreamName
|
5
|
+
# end
|
6
|
+
# end
|
7
|
+
# end
|
8
|
+
|
9
|
+
module MessageStore
|
10
|
+
module Postgres
|
11
|
+
module Controls
|
12
|
+
module StreamName
|
13
|
+
def self.example(category: nil, id: nil, type: nil, types: nil, randomize_category: nil)
|
14
|
+
category ||= Category.example(category: category, randomize_category: randomize_category)
|
15
|
+
id ||= Identifier::UUID.random
|
16
|
+
|
17
|
+
MessageStore::Postgres::StreamName.stream_name(category, id, type: type, types: types)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module MessageStore
|
2
|
+
module Postgres
|
3
|
+
class Get
|
4
|
+
include MessageStore::Get
|
5
|
+
|
6
|
+
initializer :batch_size
|
7
|
+
|
8
|
+
dependency :session, Session
|
9
|
+
|
10
|
+
def self.build(batch_size: nil, session: nil)
|
11
|
+
new(batch_size).tap do |instance|
|
12
|
+
instance.configure(session: session)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.configure(receiver, attr_name: nil, position: nil, batch_size: nil, session: nil)
|
17
|
+
attr_name ||= :get
|
18
|
+
instance = build(batch_size: batch_size, session: session)
|
19
|
+
receiver.public_send "#{attr_name}=", instance
|
20
|
+
end
|
21
|
+
|
22
|
+
def configure(session: nil)
|
23
|
+
Session.configure self, session: session
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.call(stream_name, position: nil, batch_size: nil, session: nil)
|
27
|
+
instance = build(batch_size: batch_size, session: session)
|
28
|
+
instance.(stream_name, position: position)
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(stream_name, position: nil)
|
32
|
+
logger.trace { "Getting message data (Position: #{position.inspect}, Stream Name: #{stream_name}, Batch Size: #{batch_size.inspect})" }
|
33
|
+
|
34
|
+
records = get_records(stream_name, position)
|
35
|
+
|
36
|
+
messages = convert(records)
|
37
|
+
|
38
|
+
logger.info { "Finished getting message data (Count: #{messages.length}, Position: #{position.inspect}, Stream Name: #{stream_name}, Batch Size: #{batch_size.inspect})" }
|
39
|
+
logger.info(tags: [:data, :message_data]) { messages.pretty_inspect }
|
40
|
+
|
41
|
+
messages
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_records(stream_name, position)
|
45
|
+
logger.trace { "Getting records (Stream: #{stream_name}, Position: #{position.inspect}, Batch Size: #{batch_size.inspect})" }
|
46
|
+
|
47
|
+
select_statement = SelectStatement.build(stream_name, position: position, batch_size: batch_size)
|
48
|
+
|
49
|
+
records = session.execute(select_statement.sql)
|
50
|
+
|
51
|
+
logger.debug { "Finished getting records (Count: #{records.ntuples}, Stream: #{stream_name}, Position: #{position.inspect}, Batch Size: #{batch_size.inspect})" }
|
52
|
+
|
53
|
+
records
|
54
|
+
end
|
55
|
+
|
56
|
+
def convert(records)
|
57
|
+
logger.trace { "Converting records to message data (Records Count: #{records.ntuples})" }
|
58
|
+
|
59
|
+
messages = records.map do |record|
|
60
|
+
record['data'] = Deserialize.data(record['data'])
|
61
|
+
record['metadata'] = Deserialize.metadata(record['metadata'])
|
62
|
+
record['time'] = Time.utc_coerced(record['time'])
|
63
|
+
|
64
|
+
MessageData::Read.build record
|
65
|
+
end
|
66
|
+
|
67
|
+
logger.debug { "Converted records to message data (Message Data Count: #{messages.length})" }
|
68
|
+
|
69
|
+
messages
|
70
|
+
end
|
71
|
+
|
72
|
+
module Deserialize
|
73
|
+
def self.data(serialized_data)
|
74
|
+
return nil if serialized_data.nil?
|
75
|
+
Transform::Read.(serialized_data, MessageData::Hash, :json)
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.metadata(serialized_metadata)
|
79
|
+
return nil if serialized_metadata.nil?
|
80
|
+
Transform::Read.(serialized_metadata, MessageData::Hash, :json)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
module Time
|
85
|
+
def self.utc_coerced(local_time)
|
86
|
+
Clock::UTC.coerce(local_time)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module MessageStore
|
2
|
+
module Postgres
|
3
|
+
class Get
|
4
|
+
class Last
|
5
|
+
include Log::Dependency
|
6
|
+
|
7
|
+
dependency :session, Session
|
8
|
+
|
9
|
+
def self.build(session: nil)
|
10
|
+
new.tap do |instance|
|
11
|
+
instance.configure(session: session)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.configure(receiver, attr_name: nil, session: nil)
|
16
|
+
attr_name ||= :get_last
|
17
|
+
instance = build(session: session)
|
18
|
+
receiver.public_send "#{attr_name}=", instance
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure(session: nil)
|
22
|
+
Session.configure self, session: session
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.call(stream_name, session: nil)
|
26
|
+
instance = build(session: session)
|
27
|
+
instance.(stream_name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(stream_name)
|
31
|
+
logger.trace { "Getting last message data (Stream Name: #{stream_name})" }
|
32
|
+
|
33
|
+
record = get_record(stream_name)
|
34
|
+
|
35
|
+
return nil if record.nil?
|
36
|
+
|
37
|
+
message_data = convert(record)
|
38
|
+
|
39
|
+
logger.info { "Finished getting message data (Stream Name: #{stream_name})" }
|
40
|
+
logger.info(tags: [:data, :message_data]) { message_data.pretty_inspect }
|
41
|
+
|
42
|
+
message_data
|
43
|
+
end
|
44
|
+
|
45
|
+
def get_record(stream_name)
|
46
|
+
logger.trace { "Getting last record (Stream: #{stream_name})" }
|
47
|
+
|
48
|
+
select_statement = SelectStatement.build(stream_name)
|
49
|
+
|
50
|
+
records = session.execute(select_statement.sql)
|
51
|
+
|
52
|
+
logger.debug { "Finished getting record (Stream: #{stream_name})" }
|
53
|
+
|
54
|
+
return nil if records.ntuples == 0
|
55
|
+
|
56
|
+
records[0]
|
57
|
+
end
|
58
|
+
|
59
|
+
def convert(record)
|
60
|
+
logger.trace { "Converting record to message data" }
|
61
|
+
|
62
|
+
record['data'] = Deserialize.data(record['data'])
|
63
|
+
record['metadata'] = Deserialize.metadata(record['metadata'])
|
64
|
+
record['time'] = Time.utc_coerced(record['time'])
|
65
|
+
|
66
|
+
message_data = MessageData::Read.build(record)
|
67
|
+
|
68
|
+
logger.debug { "Converted record to message data" }
|
69
|
+
|
70
|
+
message_data
|
71
|
+
end
|
72
|
+
|
73
|
+
def __convert(records)
|
74
|
+
logger.trace { "Converting records to message data (Records Count: #{records.ntuples})" }
|
75
|
+
|
76
|
+
messages = records.map do |record|
|
77
|
+
record['data'] = Deserialize.data(record['data'])
|
78
|
+
record['metadata'] = Deserialize.metadata(record['metadata'])
|
79
|
+
record['time'] = Time.utc_coerced(record['time'])
|
80
|
+
|
81
|
+
MessageData::Read.build record
|
82
|
+
|
83
|
+
break
|
84
|
+
end
|
85
|
+
|
86
|
+
logger.debug { "Converted records to message data (Message Data Count: #{messages.length})" }
|
87
|
+
|
88
|
+
messages
|
89
|
+
end
|
90
|
+
|
91
|
+
module Deserialize
|
92
|
+
def self.data(serialized_data)
|
93
|
+
return nil if serialized_data.nil?
|
94
|
+
Transform::Read.(serialized_data, MessageData::Hash, :json)
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.metadata(serialized_metadata)
|
98
|
+
return nil if serialized_metadata.nil?
|
99
|
+
Transform::Read.(serialized_metadata, MessageData::Hash, :json)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
module Time
|
104
|
+
def self.utc_coerced(local_time)
|
105
|
+
Clock::UTC.coerce(local_time)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module MessageStore
|
2
|
+
module Postgres
|
3
|
+
class Get
|
4
|
+
class Last
|
5
|
+
class SelectStatement
|
6
|
+
include Log::Dependency
|
7
|
+
|
8
|
+
initializer :stream_name
|
9
|
+
|
10
|
+
def self.build(stream_name)
|
11
|
+
new(stream_name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def sql
|
15
|
+
logger.trace(tag: :sql) { "Composing select statement (Stream: #{stream_name})" }
|
16
|
+
|
17
|
+
statement = <<-SQL
|
18
|
+
SELECT
|
19
|
+
id::varchar,
|
20
|
+
stream_name::varchar,
|
21
|
+
position::int,
|
22
|
+
type::varchar,
|
23
|
+
global_position::bigint,
|
24
|
+
data::varchar,
|
25
|
+
metadata::varchar,
|
26
|
+
time::timestamp
|
27
|
+
FROM
|
28
|
+
events
|
29
|
+
WHERE
|
30
|
+
stream_name = '#{stream_name}'
|
31
|
+
ORDER BY
|
32
|
+
position DESC
|
33
|
+
LIMIT
|
34
|
+
1
|
35
|
+
;
|
36
|
+
SQL
|
37
|
+
|
38
|
+
logger.debug(tag: :sql) { "Composed select statement (Stream: #{stream_name})" }
|
39
|
+
logger.debug(tags: [:data, :sql]) { "Statement: #{statement}" }
|
40
|
+
|
41
|
+
statement
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module MessageStore
|
2
|
+
module Postgres
|
3
|
+
class Get
|
4
|
+
class SelectStatement
|
5
|
+
include Log::Dependency
|
6
|
+
|
7
|
+
initializer :stream_name, w(:position), w(:batch_size)
|
8
|
+
|
9
|
+
def position
|
10
|
+
@position ||= Defaults.position
|
11
|
+
end
|
12
|
+
|
13
|
+
def batch_size
|
14
|
+
@batch_size ||= Defaults.batch_size
|
15
|
+
end
|
16
|
+
|
17
|
+
def stream_type_list
|
18
|
+
@stream_type ||= StreamName.get_type_list(stream_name)
|
19
|
+
end
|
20
|
+
|
21
|
+
def category_stream?
|
22
|
+
is_category_stream ||= StreamName.category?(stream_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.build(stream_name, position: nil, batch_size: nil)
|
26
|
+
new(stream_name, position, batch_size)
|
27
|
+
end
|
28
|
+
|
29
|
+
def sql
|
30
|
+
logger.trace(tag: :sql) { "Composing select statement (Stream: #{stream_name}, Category: #{category_stream?}, Types: #{stream_type_list.inspect}, Position: #{position}, Batch Size: #{batch_size})" }
|
31
|
+
|
32
|
+
statement = <<-SQL
|
33
|
+
SELECT
|
34
|
+
id::varchar,
|
35
|
+
stream_name::varchar,
|
36
|
+
position::int,
|
37
|
+
type::varchar,
|
38
|
+
global_position::bigint,
|
39
|
+
data::varchar,
|
40
|
+
metadata::varchar,
|
41
|
+
time::timestamp
|
42
|
+
FROM
|
43
|
+
events
|
44
|
+
WHERE
|
45
|
+
#{where_clause_field} = '#{stream_name}' AND
|
46
|
+
#{position_field} >= #{position}
|
47
|
+
ORDER BY
|
48
|
+
#{position_field} ASC
|
49
|
+
LIMIT
|
50
|
+
#{batch_size}
|
51
|
+
;
|
52
|
+
SQL
|
53
|
+
|
54
|
+
logger.debug(tag: :sql) { "Composed select statement (Stream: #{stream_name}, Category: #{category_stream?}, Types: #{stream_type_list.inspect}, Position: #{position}, Batch Size: #{batch_size})" }
|
55
|
+
logger.debug(tags: [:data, :sql]) { "Statement: #{statement}" }
|
56
|
+
|
57
|
+
statement
|
58
|
+
end
|
59
|
+
|
60
|
+
def where_clause_field
|
61
|
+
unless category_stream?
|
62
|
+
'stream_name'
|
63
|
+
else
|
64
|
+
'category(stream_name)'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def position_field
|
69
|
+
unless category_stream?
|
70
|
+
'position'
|
71
|
+
else
|
72
|
+
'global_position'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
module Defaults
|
77
|
+
def self.position
|
78
|
+
0
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.batch_size
|
82
|
+
1000
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module MessageStore
|
2
|
+
module Postgres
|
3
|
+
class Put
|
4
|
+
include Log::Dependency
|
5
|
+
|
6
|
+
dependency :session, Session
|
7
|
+
dependency :identifier, Session
|
8
|
+
|
9
|
+
def self.build(session: nil)
|
10
|
+
new.tap do |instance|
|
11
|
+
instance.configure(session: session)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def configure(session: nil)
|
16
|
+
Session.configure(self, session: session)
|
17
|
+
Identifier::UUID::Random.configure(self)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.configure(receiver, session: nil, attr_name: nil)
|
21
|
+
attr_name ||= :put
|
22
|
+
instance = build(session: session)
|
23
|
+
receiver.public_send "#{attr_name}=", instance
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.call(write_message, stream_name, expected_version: nil, session: nil)
|
27
|
+
instance = build(session: session)
|
28
|
+
instance.(write_message, stream_name, expected_version: expected_version)
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(write_message, stream_name, expected_version: nil)
|
32
|
+
logger.trace { "Putting message data (Stream Name: #{stream_name}, Type: #{write_message.type}, Expected Version: #{expected_version.inspect})" }
|
33
|
+
logger.trace(tags: [:data, :message_data]) { write_message.pretty_inspect }
|
34
|
+
|
35
|
+
write_message.id ||= identifier.get
|
36
|
+
|
37
|
+
id, type, data, metadata = destructure_message(write_message)
|
38
|
+
expected_version = ExpectedVersion.canonize(expected_version)
|
39
|
+
|
40
|
+
insert_message(id, stream_name, type, data, metadata, expected_version).tap do |position|
|
41
|
+
logger.info { "Put message data (Position: #{position}, Stream Name: #{stream_name}, Type: #{write_message.type}, Expected Version: #{expected_version.inspect}, ID: #{id.inspect})" }
|
42
|
+
logger.info(tags: [:data, :message_data]) { write_message.pretty_inspect }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def destructure_message(write_message)
|
47
|
+
id = write_message.id
|
48
|
+
type = write_message.type
|
49
|
+
data = write_message.data
|
50
|
+
metadata = write_message.metadata
|
51
|
+
|
52
|
+
logger.debug(tags: [:data, :message_data]) { "ID: #{id.pretty_inspect}" }
|
53
|
+
logger.debug(tags: [:data, :message_data]) { "Type: #{type.pretty_inspect}" }
|
54
|
+
logger.debug(tags: [:data, :message_data]) { "Data: #{data.pretty_inspect}" }
|
55
|
+
logger.debug(tags: [:data, :message_data]) { "Metadata: #{metadata.pretty_inspect}" }
|
56
|
+
|
57
|
+
return id, type, data, metadata
|
58
|
+
end
|
59
|
+
|
60
|
+
def insert_message(id, stream_name, type, data, metadata, expected_version)
|
61
|
+
serialized_data = serialized_data(data)
|
62
|
+
serialized_metadata = serialized_metadata(metadata)
|
63
|
+
records = execute_query(id, stream_name, type, serialized_data, serialized_metadata, expected_version)
|
64
|
+
position(records)
|
65
|
+
end
|
66
|
+
|
67
|
+
def execute_query(id, stream_name, type, serialized_data, serialized_metadata, expected_version)
|
68
|
+
logger.trace { "Executing insert (Stream Name: #{stream_name}, Type: #{type}, Expected Version: #{expected_version.inspect}, ID: #{id.inspect})" }
|
69
|
+
|
70
|
+
params = [
|
71
|
+
id,
|
72
|
+
stream_name,
|
73
|
+
type,
|
74
|
+
serialized_data,
|
75
|
+
serialized_metadata,
|
76
|
+
expected_version
|
77
|
+
]
|
78
|
+
|
79
|
+
begin
|
80
|
+
records = session.execute(self.class.statement, params)
|
81
|
+
rescue PG::RaiseException => e
|
82
|
+
raise_error e
|
83
|
+
end
|
84
|
+
|
85
|
+
logger.debug { "Executed insert (Stream Name: #{stream_name}, Type: #{type}, Expected Version: #{expected_version.inspect}, ID: #{id.inspect})" }
|
86
|
+
|
87
|
+
records
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.statement
|
91
|
+
@statement ||= "SELECT write_event($1::varchar, $2::varchar, $3::varchar, $4::jsonb, $5::jsonb, $6::int);"
|
92
|
+
end
|
93
|
+
|
94
|
+
def serialized_data(data)
|
95
|
+
serialized_data = nil
|
96
|
+
|
97
|
+
if data.is_a?(Hash) && data.empty?
|
98
|
+
data = nil
|
99
|
+
end
|
100
|
+
|
101
|
+
unless data.nil?
|
102
|
+
serializable_data = MessageData::Hash[data]
|
103
|
+
serialized_data = Transform::Write.(serializable_data, :json)
|
104
|
+
end
|
105
|
+
|
106
|
+
logger.debug(tags: [:data, :serialize]) { "Serialized Data: #{serialized_data.inspect}" }
|
107
|
+
serialized_data
|
108
|
+
end
|
109
|
+
|
110
|
+
def serialized_metadata(metadata)
|
111
|
+
serialized_metadata = nil
|
112
|
+
|
113
|
+
if metadata.is_a?(Hash) && metadata.empty?
|
114
|
+
metadata = nil
|
115
|
+
end
|
116
|
+
|
117
|
+
unless metadata.nil?
|
118
|
+
serializable_metadata = MessageData::Hash[metadata]
|
119
|
+
serialized_metadata = Transform::Write.(serializable_metadata, :json)
|
120
|
+
end
|
121
|
+
|
122
|
+
logger.debug(tags: [:data, :serialize]) { "Serialized Metadata: #{serialized_metadata.inspect}" }
|
123
|
+
serialized_metadata
|
124
|
+
end
|
125
|
+
|
126
|
+
def position(records)
|
127
|
+
position = nil
|
128
|
+
unless records[0].nil?
|
129
|
+
position = records[0].values[0]
|
130
|
+
end
|
131
|
+
position
|
132
|
+
end
|
133
|
+
|
134
|
+
def raise_error(pg_error)
|
135
|
+
error_message = pg_error.message
|
136
|
+
if error_message.include? 'Wrong expected version'
|
137
|
+
error_message.gsub!('ERROR:', '').strip!
|
138
|
+
logger.error { error_message }
|
139
|
+
raise ExpectedVersion::Error, error_message
|
140
|
+
end
|
141
|
+
raise pg_error
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|