strum-esb 0.2.0 → 0.3.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: 100cac09566f7c972a3ea3cb7005fc3c57ecc20cc7cb4e159b43dcf4b5d9bc24
4
- data.tar.gz: dd290413c6ae5f8cc50659a487bc656500c04cd27d289cf13f10eaea14e90343
3
+ metadata.gz: 115db6eaed48ee3c437b15fbf8103815214a5cdcc4d0d040960fc6ad73708190
4
+ data.tar.gz: dd0f567ec63c61781272ea0931a7348be7df38de6661b5d9da77ccf55e17855d
5
5
  SHA512:
6
- metadata.gz: c1a9a87ba8f0207f0de46d08f19229835e29ab844f2053f38a0eb484efc191460d83a6d5e87421d1d4df09152138e753f93705035b4866c6f0ff502b2cffdadf
7
- data.tar.gz: b3f3d16931dd745a09a7cfbe938b9170c8e4efb4bf511f7de796595ad43ec683cf72c4865cbfe838ee91005b5df1431b32fa12a09fa5426a176a2f99ede62bc3
6
+ metadata.gz: 3275b5108de6e8f5ac0bf8413d8fb53e0939855c9621fb1ac054b5ae9ecc693ff368a5d55d5e794956f75f038ba106eb4c3452c377b273eda7e064f713b6b605
7
+ data.tar.gz: 679fc2e04636143bbfcceb7fba20cb79972475313ed2731977035b1ceb21ca981d77247b03fc668c92d3e809894edeae16e5b74f92afbde55b2d21a77f287c4d
data/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
  # Changelog
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.3.0] - 2022-03-14
6
+ ### Added
7
+ - `content_type` option to send message by [@valeriia.kolisnyk]
8
+ - serialization/deserialization for protobuf by [@valeriia.kolisnyk]
9
+ - `json` and `protobuf_service` switchers for handler by [@valeriia.kolisnyk]
10
+
5
11
  ## [0.1.1] - 2021-06-01
6
12
  ### Added
7
13
  - `pre_publish_hooks` to configuration by [@Samuron]
data/Gemfile CHANGED
@@ -13,3 +13,4 @@ gem "rubocop-rspec", "~> 2.3.0"
13
13
  gem "debase", "~> 0.2.4"
14
14
  gem "ruby-debug-ide", "~> 0.7.2"
15
15
 
16
+ gem "dry-inflector", "~> 0.2.1"
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- strum-esb (0.2.0)
4
+ strum-esb (0.3.0)
5
5
  bunny (~> 2.15)
6
6
  connection_pool (~> 2.2.2)
7
7
  dry-configurable (~> 0.12.1)
8
+ dry-inflector (~> 0.2.1)
8
9
  json (~> 2.3)
9
10
  sneakers (~> 2.12)
10
11
 
@@ -27,13 +28,14 @@ GEM
27
28
  dry-core (~> 0.5, >= 0.5.0)
28
29
  dry-core (0.7.1)
29
30
  concurrent-ruby (~> 1.0)
30
- json (2.5.1)
31
+ dry-inflector (0.2.1)
32
+ json (2.6.1)
31
33
  parallel (1.20.1)
32
34
  parser (3.0.1.1)
33
35
  ast (~> 2.4.1)
34
36
  rainbow (3.0.0)
35
37
  rake (12.3.3)
36
- rbtree (0.4.4)
38
+ rbtree (0.4.5)
37
39
  regexp_parser (2.1.1)
38
40
  rexml (3.2.5)
39
41
  rspec (3.10.0)
@@ -68,7 +70,7 @@ GEM
68
70
  ruby-progressbar (1.11.0)
69
71
  serverengine (2.1.1)
70
72
  sigdump (~> 0.2.2)
71
- set (1.0.1)
73
+ set (1.0.2)
72
74
  sigdump (0.2.4)
73
75
  sneakers (2.12.0)
74
76
  bunny (~> 2.14)
@@ -79,7 +81,7 @@ GEM
79
81
  sorted_set (1.0.3)
80
82
  rbtree
81
83
  set (~> 1.0)
82
- thor (1.1.0)
84
+ thor (1.2.1)
83
85
  unicode-display_width (2.0.0)
84
86
 
85
87
  PLATFORMS
@@ -88,6 +90,7 @@ PLATFORMS
88
90
  DEPENDENCIES
89
91
  bundler (~> 2.1.4)
90
92
  debase (~> 0.2.4)
93
+ dry-inflector (~> 0.2.1)
91
94
  rspec (~> 3)
92
95
  rubocop (~> 1.15)
93
96
  rubocop-rspec (~> 2.3.0)
data/README.md CHANGED
@@ -94,6 +94,45 @@ module Queues
94
94
  end
95
95
  ```
96
96
 
97
+ ### Sending protobuf via strum-esb
98
+ 1. Encode your protobuf message using `encode` method to send it.
99
+ 2. Define `protobuf_service` in your handler, and disable `json`:
100
+
101
+ ```ruby
102
+ require "strum/esb"
103
+ require "contracts/test_pb"
104
+
105
+ module Queues
106
+ class Resource
107
+ include Strum::Esb::Handler
108
+
109
+ json false
110
+ protobuf_service Test::Router::Service
111
+ from_queue "resource-queue",
112
+ bindings: {
113
+ events: %w[user/create user/update],
114
+
115
+ }
116
+
117
+ def handler(payload)
118
+ # code here ...
119
+ end
120
+ end
121
+ end
122
+ ```
123
+
124
+ Your rpc action must have the same name as your method in queue class, for example: if method is `action_get_user`, rpc action needs to be `ActionGetUser`.
125
+
126
+ 3. Pass content type as additional param when you send Strum::Esb message:
127
+ ```ruby
128
+ Strum::Esb::Action.call("payload", "action", "resource", content_type: "application/x-protobuf")
129
+ ```
130
+ or add it as before_publish_hook:
131
+ ```ruby
132
+ Strum::Esb.config.before_publish_hooks << lambda { |_body, properties|
133
+ properties[:content_type] = "application/x-protobuf"
134
+ }
135
+ ```
97
136
 
98
137
  ## Development
99
138
 
@@ -30,12 +30,19 @@ module Strum
30
30
  def handlers
31
31
  @handlers || {}
32
32
  end
33
+
34
+ def protobuf_service(service)
35
+ Strum::Esb.config.protobuf_service = service
36
+ end
37
+
38
+ def json(switcher)
39
+ Strum::Esb.config.json = switcher
40
+ end
33
41
  end
34
42
 
35
43
  def work_with_params(deserialized_msg, delivery_info, metadata)
36
44
  Strum::Esb.config.before_handler_hooks.each { |hook| hook.call(deserialized_msg, delivery_info, metadata) }
37
45
 
38
- payload = JSON.parse(deserialized_msg)
39
46
  snake_case_modify = ->(string) { string.nil? ? nil : string&.to_s.gsub(/[^a-zA-Z0-9]/, "_")&.downcase }
40
47
  parse_header = ->(string) { metadata[:headers] && metadata[:headers][string] }
41
48
  header = parse_header >> snake_case_modify
@@ -64,6 +71,18 @@ module Strum
64
71
 
65
72
  method_name = ([*methods_names] << "handler").find { |n| respond_to?(n, include_all: true) }
66
73
 
74
+ unless Strum::Esb.config.serializer.enabled?(metadata[:content_type])
75
+ logger.error "Content type #{metadata[:content_type]} is disabled by handler. Message rejected #{metadata[:headers]} with payload #{deserialized_msg}"
76
+ return reject!
77
+ end
78
+
79
+ payload, valid_payload = Strum::Esb.config.serializer.deserialize(deserialized_msg, metadata[:content_type], method_name)
80
+
81
+ unless valid_payload
82
+ logger.error "Content type is invalid. Message rejected #{metadata[:headers]} with payload #{payload}"
83
+ return reject!
84
+ end
85
+
67
86
  unless method_name
68
87
  logger.error "Handler not found. Message rejected #{metadata[:headers]} with payload #{payload}"
69
88
  return reject!
@@ -83,7 +102,7 @@ module Strum
83
102
  error = e
84
103
  logger.error e
85
104
  reject!
86
- ensure
105
+ ensure
87
106
  Strum::Esb.config.after_handler_hooks.each { |hook| hook.call(deserialized_msg, delivery_info, metadata, payload, error) }
88
107
  end
89
108
 
@@ -5,11 +5,11 @@ module Strum
5
5
  # Strum Message
6
6
  class Message
7
7
  class << self
8
- def publish(exchange:, headers:, payload:)
8
+ def publish(exchange:, headers:, payload:, content_type: "application/json")
9
9
  rabbit_exchange ||= Strum::Esb.config.rabbit_channel_pool.with { |rabbit_channel| rabbit_channel.headers(exchange, durable: true) }
10
10
  properties = {
11
11
  headers: headers,
12
- content_type: "application/json"
12
+ content_type: content_type
13
13
  }
14
14
 
15
15
  Strum::Esb.config.before_publish_hooks.each { |hook| hook.call(payload, properties) }
@@ -21,8 +21,14 @@ module Strum
21
21
  payload["chain"] ||= chain
22
22
  headers["chain"] ||= chain
23
23
  end
24
-
25
- rabbit_exchange.publish(payload.to_json, **properties)
24
+
25
+ payload, valid_payload = Strum::Esb.config.serializer.serialize(payload, properties[:content_type])
26
+ unless valid_payload
27
+ Sneakers.logger.error "Content type is invalid. Message rejected #{properties[:headers]} with payload #{payload}"
28
+ return
29
+ end
30
+
31
+ rabbit_exchange.publish(payload, **properties)
26
32
  end
27
33
  end
28
34
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Strum
4
+ module Esb
5
+ # Payload serializer/deserializer
6
+ class Serializer
7
+ CONTENT_TYPES = %w[application/json application/x-protobuf].freeze
8
+
9
+ %i[serialize deserialize].each do |base_method|
10
+ define_method base_method do |payload, content_type, queue_method_name = nil|
11
+ return [payload, false] unless valid_content_type?(content_type)
12
+
13
+ perform_method_name = content_type_method_name(base_method, content_type)
14
+ payload = send(*[perform_method_name, payload, queue_method_name].compact)
15
+ [payload, true]
16
+ rescue StandardError
17
+ [payload, false]
18
+ end
19
+ end
20
+
21
+ def enabled?(content_type)
22
+ case data_type(content_type)
23
+ when "json"
24
+ Strum::Esb.config.json
25
+ when "protobuf"
26
+ Strum::Esb.config.protobuf_service
27
+ else
28
+ false
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def valid_content_type?(content_type)
35
+ CONTENT_TYPES.include?(content_type)
36
+ end
37
+
38
+ def content_type_method_name(action, content_type)
39
+ "#{action}_#{data_type(content_type)}"
40
+ end
41
+
42
+ def data_type(content_type)
43
+ content_type.gsub("-", "/").split("/").last
44
+ end
45
+
46
+ def deserialize_json(payload, _queue_method_name)
47
+ JSON.parse(payload)
48
+ end
49
+
50
+ def deserialize_protobuf(payload, queue_method_name)
51
+ action_name = inflector.camelize(queue_method_name)
52
+ rpc_struct = Strum::Esb.config.protobuf_service.rpc_descs[action_name.to_sym]
53
+ rpc_struct.input.decode(payload)
54
+ end
55
+
56
+ def serialize_json(payload)
57
+ payload.to_json
58
+ end
59
+
60
+ def serialize_protobuf(payload)
61
+ payload
62
+ end
63
+
64
+ def inflector
65
+ Dry::Inflector.new
66
+ end
67
+ end
68
+ end
69
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Strum
4
4
  module Esb
5
- VERSION = "0.2.0"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
data/lib/strum/esb.rb CHANGED
@@ -15,6 +15,8 @@ require "strum/esb/event"
15
15
  require "strum/esb/notice"
16
16
  require "strum/esb/info"
17
17
  require "dry/configurable"
18
+ require "dry/inflector"
19
+ require "strum/esb/serializer"
18
20
 
19
21
  module Strum
20
22
  module Esb
@@ -38,6 +40,9 @@ module Strum
38
40
  setting :before_publish_hooks, []
39
41
  setting :before_handler_hooks, []
40
42
  setting :after_handler_hooks, []
43
+ setting :serializer, Serializer.new
44
+ setting :protobuf_service, false
45
+ setting :json, true
41
46
 
42
47
  Strum::Esb.config.before_fork_hooks << proc { DB.disconnect } if defined?(DB)
43
48
 
data/strum-esb.gemspec CHANGED
@@ -31,6 +31,7 @@ Gem::Specification.new do |spec|
31
31
  spec.add_dependency "bunny", "~> 2.15"
32
32
  spec.add_dependency "connection_pool", "~> 2.2.2"
33
33
  spec.add_dependency "dry-configurable", "~> 0.12.1"
34
+ spec.add_dependency "dry-inflector", "~> 0.2.1"
34
35
  spec.add_dependency "json", "~> 2.3"
35
36
  spec.add_dependency "sneakers", "~> 2.12"
36
37
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strum-esb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Serhiy Nazarov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-26 00:00:00.000000000 Z
11
+ date: 2022-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bunny
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 0.12.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: dry-inflector
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.2.1
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: json
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -107,6 +121,7 @@ files:
107
121
  - lib/strum/esb/info.rb
108
122
  - lib/strum/esb/message.rb
109
123
  - lib/strum/esb/notice.rb
124
+ - lib/strum/esb/serializer.rb
110
125
  - lib/strum/esb/version.rb
111
126
  - lib/strum/patch/sneakers/queue_patch.rb
112
127
  - strum-esb.gemspec