railway-ipc 0.1.3 → 0.1.4

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -0
  3. data/.tool-versions +1 -0
  4. data/Gemfile.lock +125 -1
  5. data/README.md +5 -0
  6. data/lib/railway_ipc.rb +28 -21
  7. data/lib/railway_ipc/base_message.pb.rb +21 -0
  8. data/lib/railway_ipc/consumer/consumer.rb +112 -0
  9. data/lib/railway_ipc/consumer/consumer_response_handlers.rb +14 -0
  10. data/lib/railway_ipc/errors.rb +1 -0
  11. data/lib/railway_ipc/handler.rb +2 -0
  12. data/lib/railway_ipc/handler_manifest.rb +10 -0
  13. data/lib/railway_ipc/handler_store.rb +21 -0
  14. data/lib/railway_ipc/models/consumed_message.rb +48 -0
  15. data/lib/railway_ipc/models/published_message.rb +27 -0
  16. data/lib/railway_ipc/null_message.rb +1 -1
  17. data/lib/railway_ipc/publisher.rb +9 -4
  18. data/lib/railway_ipc/rabbitmq/adapter.rb +93 -0
  19. data/lib/railway_ipc/rabbitmq/payload.rb +7 -3
  20. data/lib/railway_ipc/rpc/client/client.rb +104 -0
  21. data/lib/railway_ipc/rpc/client/client_response_handlers.rb +25 -0
  22. data/lib/railway_ipc/rpc/client/errors/timeout_error.rb +5 -0
  23. data/lib/railway_ipc/rpc/concerns/error_adapter_configurable.rb +13 -0
  24. data/lib/railway_ipc/rpc/concerns/message_observation_configurable.rb +18 -0
  25. data/lib/railway_ipc/rpc/concerns/publish_location_configurable.rb +13 -0
  26. data/lib/railway_ipc/rpc/rpc.rb +2 -0
  27. data/lib/railway_ipc/rpc/server/server.rb +89 -0
  28. data/lib/railway_ipc/rpc/server/server_response_handlers.rb +17 -0
  29. data/lib/railway_ipc/tasks/generate_migrations.rake +26 -0
  30. data/lib/railway_ipc/version.rb +1 -1
  31. data/priv/migrations/add_railway_ipc_consumed_messages.rb +19 -0
  32. data/priv/migrations/add_railway_ipc_published_messages.rb +18 -0
  33. data/railway_ipc.gemspec +25 -16
  34. metadata +123 -8
  35. data/lib/railway_ipc/client.rb +0 -87
  36. data/lib/railway_ipc/concerns/message_handling.rb +0 -118
  37. data/lib/railway_ipc/consumer.rb +0 -26
  38. data/lib/railway_ipc/rabbitmq/connection.rb +0 -55
  39. data/lib/railway_ipc/server.rb +0 -50
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e93883b1436475f8b412a9bb1b689adf4d912575e3ebc406bba614321df1f4c
4
- data.tar.gz: 42ba48cba7b1a384a3074715feae7d04b86012090e87b74a725925891214b238
3
+ metadata.gz: 945917b242216c009d199f73de3c559b16b005cdae28504273b2ee68d04ed8df
4
+ data.tar.gz: 39bc88b82f608a2a74de630c334bd6a7021a92666e8843fc4ba81e3f1b3a2b03
5
5
  SHA512:
6
- metadata.gz: 82a6d816b613df92db94065ce6c7027b44d49e8f8df91c59c82f2ddc3c6c0bd818ec8d2c8d511285acd393ee4624bb34f66ed1c39ed5a85be7f3779aac9900d0
7
- data.tar.gz: 128ea826e0036463fcb635685e28bbc58916d073c48b5ff0100aa196bd2b824eee5117921eb571d87110b0d29b210779295b0f0fcd6d7f798c3f91e4f617e3e7
6
+ metadata.gz: 42425f432289124825d92ec02bc3350875070da6554c824fc4cb9f802d961817ae65980b6011566be24696abbecf6613e48166373e5d6476e1cf6498ae64057a
7
+ data.tar.gz: 9d09e840a91d94a02e4551fa44f2d653e40e716e4606288649320709d54c47cccc8240268b38a550466b92ebd0882f4718bd271256ca520b735d283cbbcd3294
data/.gitignore CHANGED
@@ -9,3 +9,11 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+
13
+ # rails support app files
14
+ /spec/support/rails_app/.bundle
15
+ /spec/support/rails_app/log/*
16
+ /spec/support/rails_app/tmp/*
17
+ /spec/support/rails_app!/log/.keep
18
+ /spec/support/rails_app!/tmp/.keep
19
+ /spec/support/rails_app.byebug_history
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 2.6.3
data/Gemfile.lock CHANGED
@@ -1,28 +1,122 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- railway-ipc (0.1.3)
4
+ railway-ipc (0.1.4)
5
5
  bunny (~> 2.2.0)
6
6
  sneakers (~> 2.3.5)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
+ actioncable (5.0.7.2)
12
+ actionpack (= 5.0.7.2)
13
+ nio4r (>= 1.2, < 3.0)
14
+ websocket-driver (~> 0.6.1)
15
+ actionmailer (5.0.7.2)
16
+ actionpack (= 5.0.7.2)
17
+ actionview (= 5.0.7.2)
18
+ activejob (= 5.0.7.2)
19
+ mail (~> 2.5, >= 2.5.4)
20
+ rails-dom-testing (~> 2.0)
21
+ actionpack (5.0.7.2)
22
+ actionview (= 5.0.7.2)
23
+ activesupport (= 5.0.7.2)
24
+ rack (~> 2.0)
25
+ rack-test (~> 0.6.3)
26
+ rails-dom-testing (~> 2.0)
27
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
28
+ actionview (5.0.7.2)
29
+ activesupport (= 5.0.7.2)
30
+ builder (~> 3.1)
31
+ erubis (~> 2.7.0)
32
+ rails-dom-testing (~> 2.0)
33
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
34
+ activejob (5.0.7.2)
35
+ activesupport (= 5.0.7.2)
36
+ globalid (>= 0.3.6)
37
+ activemodel (5.0.7.2)
38
+ activesupport (= 5.0.7.2)
39
+ activerecord (5.0.7.2)
40
+ activemodel (= 5.0.7.2)
41
+ activesupport (= 5.0.7.2)
42
+ arel (~> 7.0)
43
+ activesupport (5.0.7.2)
44
+ concurrent-ruby (~> 1.0, >= 1.0.2)
45
+ i18n (>= 0.7, < 2)
46
+ minitest (~> 5.1)
47
+ tzinfo (~> 1.1)
11
48
  amq-protocol (2.3.0)
49
+ arel (7.1.4)
50
+ builder (3.2.4)
12
51
  bunny (2.2.2)
13
52
  amq-protocol (>= 2.0.1)
14
53
  byebug (9.1.0)
15
54
  coderay (1.1.2)
55
+ concurrent-ruby (1.1.5)
56
+ crass (1.0.5)
57
+ database_cleaner (1.7.0)
16
58
  diff-lcs (1.3)
59
+ erubis (2.7.0)
60
+ factory_bot (5.1.1)
61
+ activesupport (>= 4.2.0)
62
+ ffi (1.11.3)
63
+ globalid (0.4.2)
64
+ activesupport (>= 4.2.0)
17
65
  google-protobuf (3.9.2)
66
+ i18n (1.7.0)
67
+ concurrent-ruby (~> 1.0)
68
+ listen (3.0.8)
69
+ rb-fsevent (~> 0.9, >= 0.9.4)
70
+ rb-inotify (~> 0.9, >= 0.9.7)
71
+ loofah (2.4.0)
72
+ crass (~> 1.0.2)
73
+ nokogiri (>= 1.5.9)
74
+ mail (2.7.1)
75
+ mini_mime (>= 0.1.1)
18
76
  method_source (0.9.2)
77
+ mini_mime (1.0.2)
78
+ mini_portile2 (2.4.0)
79
+ minitest (5.13.0)
80
+ nio4r (2.5.2)
81
+ nokogiri (1.10.7)
82
+ mini_portile2 (~> 2.4.0)
83
+ pg (0.21.0)
19
84
  pry (0.12.2)
20
85
  coderay (~> 1.1.0)
21
86
  method_source (~> 0.9.0)
22
87
  pry-byebug (3.4.2)
23
88
  byebug (~> 9.0)
24
89
  pry (~> 0.10)
90
+ rack (2.0.7)
91
+ rack-test (0.6.3)
92
+ rack (>= 1.0)
93
+ rails (5.0.7.2)
94
+ actioncable (= 5.0.7.2)
95
+ actionmailer (= 5.0.7.2)
96
+ actionpack (= 5.0.7.2)
97
+ actionview (= 5.0.7.2)
98
+ activejob (= 5.0.7.2)
99
+ activemodel (= 5.0.7.2)
100
+ activerecord (= 5.0.7.2)
101
+ activesupport (= 5.0.7.2)
102
+ bundler (>= 1.3.0)
103
+ railties (= 5.0.7.2)
104
+ sprockets-rails (>= 2.0.0)
105
+ rails-dom-testing (2.0.3)
106
+ activesupport (>= 4.2.0)
107
+ nokogiri (>= 1.6)
108
+ rails-html-sanitizer (1.3.0)
109
+ loofah (~> 2.3)
110
+ railties (5.0.7.2)
111
+ actionpack (= 5.0.7.2)
112
+ activesupport (= 5.0.7.2)
113
+ method_source
114
+ rake (>= 0.8.7)
115
+ thor (>= 0.18.1, < 2.0)
25
116
  rake (13.0.0)
117
+ rb-fsevent (0.10.3)
118
+ rb-inotify (0.10.0)
119
+ ffi (~> 1.0)
26
120
  rspec (3.8.0)
27
121
  rspec-core (~> 3.8.0)
28
122
  rspec-expectations (~> 3.8.0)
@@ -35,28 +129,58 @@ GEM
35
129
  rspec-mocks (3.8.1)
36
130
  diff-lcs (>= 1.2.0, < 2.0)
37
131
  rspec-support (~> 3.8.0)
132
+ rspec-rails (3.8.3)
133
+ actionpack (>= 3.0)
134
+ activesupport (>= 3.0)
135
+ railties (>= 3.0)
136
+ rspec-core (~> 3.8.0)
137
+ rspec-expectations (~> 3.8.0)
138
+ rspec-mocks (~> 3.8.0)
139
+ rspec-support (~> 3.8.0)
38
140
  rspec-support (3.8.2)
39
141
  serverengine (1.5.11)
40
142
  sigdump (~> 0.2.2)
143
+ shoulda-matchers (4.2.0)
144
+ activesupport (>= 4.2.0)
41
145
  sigdump (0.2.4)
42
146
  sneakers (2.3.5)
43
147
  bunny (~> 2.2.0)
44
148
  serverengine (~> 1.5.11)
45
149
  thor
46
150
  thread (~> 0.1.7)
151
+ sprockets (4.0.0)
152
+ concurrent-ruby (~> 1.0)
153
+ rack (> 1, < 3)
154
+ sprockets-rails (3.2.1)
155
+ actionpack (>= 4.0)
156
+ activesupport (>= 4.0)
157
+ sprockets (>= 3.0.0)
47
158
  thor (0.20.3)
48
159
  thread (0.1.7)
160
+ thread_safe (0.3.6)
161
+ tzinfo (1.2.5)
162
+ thread_safe (~> 0.1)
163
+ websocket-driver (0.6.5)
164
+ websocket-extensions (>= 0.1.0)
165
+ websocket-extensions (0.1.4)
49
166
 
50
167
  PLATFORMS
51
168
  ruby
52
169
 
53
170
  DEPENDENCIES
54
171
  bundler (= 2.0.1)
172
+ database_cleaner (~> 1.7)
173
+ factory_bot (~> 5.1)
55
174
  google-protobuf (~> 3.9)
175
+ listen (~> 3.0.5)
176
+ pg (~> 0.18)
56
177
  pry-byebug (= 3.4.2)
178
+ rails (~> 5.0.7)
57
179
  railway-ipc!
58
180
  rake (>= 10.0.0)
59
181
  rspec (~> 3.0)
182
+ rspec-rails
183
+ shoulda-matchers (~> 4.2)
60
184
 
61
185
  BUNDLED WITH
62
186
  2.0.1
data/README.md CHANGED
@@ -35,7 +35,12 @@ require "railway_ipc"
35
35
  RABBITMQ_CONNECTION_URL=amqp://<railway_user>:<railway_password>@localhost:5672
36
36
  ```
37
37
 
38
+ * Load table migrations and migrate by executing:
38
39
 
40
+ ```bash
41
+ bundle exec rake railway_ipc:generate:migrations
42
+ bundle exec rake db:migrate
43
+ ```
39
44
 
40
45
  # Publish/Consume
41
46
 
data/lib/railway_ipc.rb CHANGED
@@ -1,26 +1,30 @@
1
- require "railway_ipc/version"
2
- require "sneakers"
3
- require "bunny"
4
- require "railway_ipc/version"
5
- require "railway_ipc/logger"
6
- require "railway_ipc/unhandled_message_error"
7
- require "railway_ipc/response"
8
- require "railway_ipc/rabbitmq/payload"
9
- require "railway_ipc/null_message"
10
- require "railway_ipc/concerns/message_handling"
11
- require "railway_ipc/rabbitmq/connection"
12
- require "railway_ipc/handler"
13
- require "railway_ipc/consumer"
14
- require "railway_ipc/publisher"
15
- require "railway_ipc/null_handler"
16
- require "railway_ipc/responder"
17
- require "railway_ipc/client"
18
- require "railway_ipc/server"
19
- require "railway_ipc/railtie" if defined?(Rails)
1
+ require 'railway_ipc/version'
2
+ require 'sneakers'
3
+ require 'bunny'
4
+ require 'active_record'
5
+ require 'railway_ipc/version'
6
+ require 'railway_ipc/errors'
7
+ require 'railway_ipc/logger'
8
+ require 'railway_ipc/unhandled_message_error'
9
+ require 'railway_ipc/response'
10
+ require 'railway_ipc/rabbitmq/payload'
11
+ require 'railway_ipc/null_message'
12
+ require 'railway_ipc/base_message.pb'
13
+ require 'railway_ipc/rabbitmq/adapter'
14
+ require 'railway_ipc/handler'
15
+ require 'railway_ipc/handler_store'
16
+ require 'railway_ipc/publisher'
17
+ require 'railway_ipc/null_handler'
18
+ require 'railway_ipc/responder'
19
+ require 'railway_ipc/rpc/rpc'
20
+ require 'railway_ipc/consumer/consumer'
21
+ require 'railway_ipc/models/published_message'
22
+ require 'railway_ipc/models/consumed_message'
23
+ require 'railway_ipc/railtie' if defined?(Rails)
20
24
 
21
25
  module RailwayIpc
22
26
  def self.start
23
- Rake::Task["sneakers:run"].invoke
27
+ Rake::Task['sneakers:run'].invoke
24
28
  end
25
29
 
26
30
  def self.configure(logger: ::Logger.new(STDOUT))
@@ -36,6 +40,9 @@ module RailwayIpc
36
40
  end
37
41
 
38
42
  def self.bunny_connection
39
- @bunny_connection ||= RailwayIpc::Rabbitmq::Connection.create_bunny_connection
43
+ @bunny_connection ||= RailwayIpc::Rabbitmq::Adapter.new(
44
+ exchange_name: 'default',
45
+ options: { automatic_recovery: true }
46
+ ).connection
40
47
  end
41
48
  end
@@ -0,0 +1,21 @@
1
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
2
+ # source: lib/src/events/base_message.proto
3
+
4
+ require 'google/protobuf'
5
+
6
+ Google::Protobuf::DescriptorPool.generated_pool.build do
7
+ add_message "railway_ipc.BaseMessage" do
8
+ optional :user_uuid, :string, 1
9
+ optional :correlation_id, :string, 2
10
+ optional :uuid, :string, 3
11
+ map :context, :string, :string, 4
12
+ optional :data, :message, 5, "railway_ipc.BaseMessage.Data"
13
+ end
14
+ add_message "railway_ipc.BaseMessage.Data" do
15
+ end
16
+ end
17
+
18
+ module RailwayIpc
19
+ BaseMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("railway_ipc.BaseMessage").msgclass
20
+ BaseMessage::Data = Google::Protobuf::DescriptorPool.generated_pool.lookup("railway_ipc.BaseMessage.Data").msgclass
21
+ end
@@ -0,0 +1,112 @@
1
+ require "json"
2
+ require "base64"
3
+ require "railway_ipc/consumer/consumer_response_handlers"
4
+
5
+ module RailwayIpc
6
+ class Consumer
7
+ include Sneakers::Worker
8
+ attr_reader :message, :handler, :protobuff_message, :delivery_info, :decoded_payload
9
+
10
+ def self.listen_to(queue:, exchange:)
11
+ from_queue queue,
12
+ exchange: exchange,
13
+ durable: true,
14
+ exchange_type: :fanout,
15
+ connection: RailwayIpc.bunny_connection
16
+ end
17
+
18
+ def self.handle(message_type, with:)
19
+ ConsumerResponseHandlers.instance.register(message: message_type, handler: with)
20
+ end
21
+
22
+ def registered_handlers
23
+ ConsumerResponseHandlers.instance.registered
24
+ end
25
+
26
+ def work_with_params(payload, delivery_info, _metadata)
27
+ @delivery_info = delivery_info
28
+ @decoded_payload = RailwayIpc::Rabbitmq::Payload.decode(payload)
29
+
30
+ case decoded_payload.type
31
+ when *registered_handlers
32
+ @handler = handler_for(decoded_payload)
33
+ message_klass = message_handler_for(decoded_payload)
34
+ @protobuff_message = message_klass.decode(decoded_payload.message)
35
+ process_known_message_type
36
+ else
37
+ @handler = RailwayIpc::NullHandler.new
38
+ @protobuff_message = RailwayIpc::BaseMessage.decode(decoded_payload.message)
39
+ process_unknown_message_type
40
+ end
41
+
42
+ rescue StandardError => e
43
+ RailwayIpc.logger.log_exception(
44
+ feature: "railway_consumer",
45
+ error: e.class,
46
+ error_message: e.message,
47
+ payload: payload,
48
+ )
49
+ raise e
50
+ end
51
+
52
+ private
53
+
54
+ def process_protobuff!(message)
55
+ if handler.handle(protobuff_message).success?
56
+ message.status = RailwayIpc::ConsumedMessage::STATUSES[:success]
57
+ else
58
+ message.status = RailwayIpc::ConsumedMessage::STATUSES[:failed_to_process]
59
+ end
60
+
61
+ message.save!
62
+ end
63
+
64
+ def process_known_message_type
65
+ message = RailwayIpc::ConsumedMessage.find_by(uuid: protobuff_message.uuid)
66
+
67
+ if message && message.processed?
68
+ handler.ack!
69
+ elsif message && !message.processed?
70
+ message.with_lock("FOR UPDATE NOWAIT") { process_protobuff!(message) }
71
+ else
72
+ message = create_message_with_status!(RailwayIpc::ConsumedMessage::STATUSES[:processing])
73
+ message.with_lock("FOR UPDATE NOWAIT") { process_protobuff!(message) }
74
+ end
75
+
76
+ nil
77
+ end
78
+
79
+ def process_unknown_message_type
80
+ handler.ack!
81
+
82
+ if RailwayIpc::ConsumedMessage.exists?(uuid: protobuff_message.uuid)
83
+ return
84
+ else
85
+ create_message_with_status!(RailwayIpc::ConsumedMessage::STATUSES[:unknown_message_type])
86
+ end
87
+
88
+ nil
89
+ end
90
+
91
+ def create_message_with_status!(status)
92
+ RailwayIpc::ConsumedMessage.create!(
93
+ uuid: protobuff_message.uuid,
94
+ status: status,
95
+ message_type: decoded_payload.type,
96
+ user_uuid: protobuff_message.user_uuid,
97
+ correlation_id: protobuff_message.correlation_id,
98
+ queue: delivery_info.consumer.queue.name,
99
+ exchange: delivery_info.exchange,
100
+ encoded_message: decoded_payload.message
101
+ )
102
+ end
103
+
104
+ def message_handler_for(decoded_payload)
105
+ ConsumerResponseHandlers.instance.get(decoded_payload.type).message
106
+ end
107
+
108
+ def handler_for(decoded_payload)
109
+ ConsumerResponseHandlers.instance.get(decoded_payload.type).handler.new
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,14 @@
1
+ require 'railway_ipc/handler_store'
2
+ module RailwayIpc
3
+ class ConsumerResponseHandlers
4
+ include Singleton
5
+ extend Forwardable
6
+ def_delegators :handler_store, :registered, :register, :get
7
+
8
+ private
9
+
10
+ def handler_store
11
+ @handler_store ||= RailwayIpc::HandlerStore.new
12
+ end
13
+ end
14
+ end
@@ -0,0 +1 @@
1
+ class RailwayIpc::InvalidProtobuf < StandardError; end
@@ -19,6 +19,8 @@ module RailwayIpc
19
19
  RailwayIpc.logger.error(message, "Failed to handle message")
20
20
  ack!
21
21
  end
22
+
23
+ response
22
24
  end
23
25
  end
24
26
  end