hubbado-idempotence-reservation 2.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
+ SHA256:
3
+ metadata.gz: 9bac8d6a56f3ecf2241b64c925acc2c7351eef692a7f3aa58f7899739decc189
4
+ data.tar.gz: d685f8f302b9f0b5465de6d36cb2eec7df82412b9ee54be2751dc27f187eb566
5
+ SHA512:
6
+ metadata.gz: 580a113f600505e7cc24190c957fc15158f4e99b4e2828110de0347a192acd565bb085b8caa4261c4ee299bac8cd4327f208a6abbdbae0816a97cba2df810cdb
7
+ data.tar.gz: 4dfccb048328a36cee84c0dedaf05a5f760201b3f8a186b0c157be8c4ed00543b029bdd1afdd1c38517864536c51fbcadd0dbc43007218b514d763916403b5c5
@@ -0,0 +1,5 @@
1
+ module Idempotence
2
+ module Controls
3
+ Message = Messaging::Controls::Message
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ module Idempotence
2
+ module Controls
3
+ Metadata = Messaging::Controls::Metadata
4
+
5
+ module Metadata::Reserved
6
+ def self.example
7
+ metadata = Metadata::Random.example
8
+
9
+ metadata.local_properties[Reservation::METADATA_NAME] = :value
10
+
11
+ metadata
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ require 'messaging/controls'
2
+
3
+ require "idempotence/reservation/controls/message"
4
+ require "idempotence/reservation/controls/metadata"
@@ -0,0 +1,128 @@
1
+ module Idempotence
2
+ class Reservation
3
+ include Log::Dependency
4
+
5
+ METADATA_NAME = :reserved
6
+
7
+ dependency :write, Messaging::Postgres::Write
8
+
9
+ configure :reservation
10
+
11
+ def self.call(message, idempotence_key, session: nil)
12
+ instance = build(session: session)
13
+ instance.(message, idempotence_key)
14
+ end
15
+
16
+ def self.build(session: nil)
17
+ instance = new
18
+ instance.configure(session: session)
19
+ instance
20
+ end
21
+
22
+ def configure(session: nil)
23
+ Messaging::Postgres::Write.configure(self, session: session)
24
+ end
25
+
26
+ def call(message, idempotence_key, &block)
27
+ logger.trace(
28
+ "Handling reservation idempotence for message #{message.class.name} #{message.metadata.global_position}",
29
+ tag: :reservation
30
+ )
31
+
32
+ if reserved?(message)
33
+ handle_reserved_message(message, &block)
34
+ else
35
+ reserve_message(message, idempotence_key)
36
+ end
37
+
38
+ logger.info(
39
+ "Handled reservation idempotence for #{message.class.name} #{message.metadata.global_position}",
40
+ tag: :reservation
41
+ )
42
+ end
43
+
44
+ def handle_reserved_message(message, &block)
45
+ logger.trace(
46
+ "Handling reserved message #{message.class.name} #{message.metadata.global_position}",
47
+ tag: :reservation
48
+ )
49
+
50
+ yield message
51
+
52
+ logger.info(
53
+ "Handled reserved message #{message.class.name} #{message.metadata.global_position}",
54
+ tag: :reservation
55
+ )
56
+ end
57
+
58
+ private
59
+
60
+ def reserved?(message)
61
+ !!message.metadata.get_local_property(METADATA_NAME)
62
+ end
63
+
64
+ def reserve_message(message, idempotence_key)
65
+ logger.trace(
66
+ "Reserving #{message.class.name} #{message.metadata.global_position}, Idempotence Key: #{idempotence_key}",
67
+ tag: :reservation
68
+ )
69
+
70
+ reservation_message = message.class.follow(message)
71
+ reservation_message.metadata.set_local_property(METADATA_NAME, message.id)
72
+ origin_stream_name = message.metadata.stream_name
73
+
74
+ category = Messaging::StreamName.get_category(origin_stream_name)
75
+ origin_ids = Messaging::StreamName.get_ids(origin_stream_name)
76
+
77
+ ids = origin_ids + [idempotence_key]
78
+
79
+ stream_name = MessageStore::StreamName.stream_name(category, ids)
80
+
81
+ result = Try.(MessageStore::ExpectedVersion::Error) do
82
+ write.initial(reservation_message, stream_name)
83
+ end
84
+
85
+ if result
86
+ logger.info(
87
+ "Reserved #{message.class.name} #{message.metadata.global_position}, Idempotence Key: #{idempotence_key}",
88
+ tag: :reservation
89
+ )
90
+ else
91
+ log_ignore(message, stream_name)
92
+ end
93
+ end
94
+
95
+ def log_ignore(message, stream_name)
96
+ logger.info(
97
+ "#{message.class.name} #{message.metadata.global_position} ignored, output stream #{stream_name} exists",
98
+ tags: %i[reservation ignored]
99
+ )
100
+ end
101
+
102
+ module Substitute
103
+ def self.build
104
+ Reservation.new
105
+ end
106
+
107
+ class Reservation
108
+ attr_reader :message
109
+ attr_reader :idempotence_key
110
+
111
+ def call(m, i_key, &block)
112
+ @message = m
113
+ @idempotence_key = i_key
114
+
115
+ yield message
116
+ end
117
+
118
+ def message?(value)
119
+ message == value
120
+ end
121
+
122
+ def idempotence_key?(value)
123
+ idempotence_key == value
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,8 @@
1
+ require "messaging/postgres"
2
+ require "message_store"
3
+ require "try"
4
+ require "log"
5
+ require "configure"; Configure.activate
6
+ require "dependency"; Dependency.activate
7
+
8
+ require "idempotence/reservation/reservation"
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hubbado-idempotence-reservation
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alfonso Uceda
8
+ - Sam Stickland
9
+ - Alexander Repnikov
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2023-03-29 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: evt-messaging-postgres
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: '0'
29
+ - !ruby/object:Gem::Dependency
30
+ name: evt-message_store
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: evt-configure
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :runtime
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: evt-dependency
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: evt-try
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: evt-log
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ type: :runtime
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ - !ruby/object:Gem::Dependency
100
+ name: hubbado-style
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ type: :development
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ - !ruby/object:Gem::Dependency
114
+ name: test_bench
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ type: :development
121
+ prerelease: false
122
+ version_requirements: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ - !ruby/object:Gem::Dependency
128
+ name: debug
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ description:
142
+ email:
143
+ - alfonso@hubbado.com
144
+ - sam@hubbado.com
145
+ - aleksander.repnikov@gmail.com
146
+ executables: []
147
+ extensions: []
148
+ extra_rdoc_files: []
149
+ files:
150
+ - lib/idempotence/reservation.rb
151
+ - lib/idempotence/reservation/controls.rb
152
+ - lib/idempotence/reservation/controls/message.rb
153
+ - lib/idempotence/reservation/controls/metadata.rb
154
+ - lib/idempotence/reservation/reservation.rb
155
+ homepage: https://github.com/hubbado/hubbado-idempotence-reservation
156
+ licenses:
157
+ - MIT
158
+ metadata:
159
+ homepage_uri: https://github.com/hubbado/hubbado-idempotence-reservation
160
+ source_code_uri: https://github.com/hubbado/hubbado-idempotence-reservation
161
+ github_repo: https://github.com/hubbado/hubbado-idempotence-reservation
162
+ post_install_message:
163
+ rdoc_options: []
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: 2.4.0
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubygems_version: 3.4.7
178
+ signing_key:
179
+ specification_version: 4
180
+ summary: Idempotence library to handle reservation pattern in eventide toolkit
181
+ test_files: []