munster 0.1.0 → 0.2.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 +4 -4
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +7 -0
- data/README.md +20 -0
- data/example/Gemfile +1 -1
- data/example/Gemfile.lock +87 -67
- data/example/app/webhooks/{test_handler.rb → webhook_test_handler.rb} +4 -13
- data/example/config/environments/production.rb +1 -1
- data/example/config/initializers/munster.rb +1 -1
- data/example/config/routes.rb +1 -1
- data/lib/munster/base_handler.rb +47 -52
- data/lib/munster/controllers/receive_webhooks_controller.rb +15 -13
- data/lib/munster/templates/munster.rb +26 -2
- data/lib/munster/version.rb +1 -1
- data/lib/munster.rb +2 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b1a49a264687c05fd36a4331d73d98218d8ff6fcf8f972384fe26db3182a2c5
|
4
|
+
data.tar.gz: 75102940fdd3d31b317f16fbe05ff8d9135aeed8229c45fb20445348719e7ccd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f61d40aa299eeed7a67f2998ed346f1655da7c2be4b87f3e2f7d4470b2e0c5eadee345a6fca3f98a2aa85d573ca079e8306b9b97dc2b96f260703159ac7e587c
|
7
|
+
data.tar.gz: d41554221b5c68ef67e8136bdf7904c6392466a79cf5d0f377e7f5bb8df37ae0b9311d0cbf34bdc5f44876c7e21cecb03e9311fac202d4b98b43a553e91f5e99
|
data/.rubocop.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
|
3
|
+
- Handler methods are now defined as instance methods for simplicity.
|
4
|
+
- Define service_id in initializer with active_handlers, instead of handler class.
|
5
|
+
- Use ruby 3.0 as a base for standard/rubocop, format all code according to it.
|
6
|
+
- Introduce Rails common error reporter ( https://guides.rubyonrails.org/error_reporting.html )
|
7
|
+
|
1
8
|
## 0.1.0
|
2
9
|
|
3
10
|
- Initial release
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# Munster
|
2
|
+
|
2
3
|
Munster is a Rails engine that provides a webhook endpoint for receiving and processing webhooks from various services. Engine stores received webhook first and later processes webhook in a separete async process.
|
3
4
|
|
4
5
|
Source code is extracted from https://cheddar.me/ main service to be used in internal microservices. Code here could be a subject to change while we flesh out details.
|
@@ -16,6 +17,7 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
16
17
|
$ gem install munster
|
17
18
|
|
18
19
|
## Usage
|
20
|
+
|
19
21
|
Generate migrations and initializer file.
|
20
22
|
|
21
23
|
`munster:install`
|
@@ -24,6 +26,24 @@ Mount munster engine in your routes.
|
|
24
26
|
|
25
27
|
`mount Munster::Engine, at: "/webhooks"`
|
26
28
|
|
29
|
+
## Requirements
|
30
|
+
|
31
|
+
This project depends on two dependencies:
|
32
|
+
|
33
|
+
- Ruby >= 3.0
|
34
|
+
- Rails >= 7.0
|
35
|
+
|
36
|
+
## Error reporter
|
37
|
+
|
38
|
+
This gem uses [Rails common error reporter](https://guides.rubyonrails.org/error_reporting.html) to report any possible error to services like Honeybadger, Appsignal, Sentry and etc. Most of those services already support this common interface, if not - it's not that hard to add this support on your own.
|
39
|
+
|
40
|
+
It's possible to provide additional context for every error. e.g.
|
41
|
+
```
|
42
|
+
Munster.configure do |config|
|
43
|
+
config.error_context = { appsignal: { namespace: "webhooks" } }
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
27
47
|
## Development
|
28
48
|
|
29
49
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/example/Gemfile
CHANGED
@@ -6,7 +6,7 @@ git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
|
6
6
|
ruby "3.2.2"
|
7
7
|
|
8
8
|
# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main"
|
9
|
-
gem "rails", "
|
9
|
+
gem "rails", ">= 7.0.8.1"
|
10
10
|
|
11
11
|
# The modern asset pipeline for Rails [https://github.com/rails/propshaft]
|
12
12
|
gem "propshaft"
|
data/example/Gemfile.lock
CHANGED
@@ -2,83 +2,96 @@ PATH
|
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
4
|
munster (0.1.0)
|
5
|
-
rails (~> 7.
|
5
|
+
rails (~> 7.1)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
actioncable (7.
|
11
|
-
actionpack (= 7.
|
12
|
-
activesupport (= 7.
|
10
|
+
actioncable (7.1.3.3)
|
11
|
+
actionpack (= 7.1.3.3)
|
12
|
+
activesupport (= 7.1.3.3)
|
13
13
|
nio4r (~> 2.0)
|
14
14
|
websocket-driver (>= 0.6.1)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
zeitwerk (~> 2.6)
|
16
|
+
actionmailbox (7.1.3.3)
|
17
|
+
actionpack (= 7.1.3.3)
|
18
|
+
activejob (= 7.1.3.3)
|
19
|
+
activerecord (= 7.1.3.3)
|
20
|
+
activestorage (= 7.1.3.3)
|
21
|
+
activesupport (= 7.1.3.3)
|
21
22
|
mail (>= 2.7.1)
|
22
23
|
net-imap
|
23
24
|
net-pop
|
24
25
|
net-smtp
|
25
|
-
actionmailer (7.
|
26
|
-
actionpack (= 7.
|
27
|
-
actionview (= 7.
|
28
|
-
activejob (= 7.
|
29
|
-
activesupport (= 7.
|
26
|
+
actionmailer (7.1.3.3)
|
27
|
+
actionpack (= 7.1.3.3)
|
28
|
+
actionview (= 7.1.3.3)
|
29
|
+
activejob (= 7.1.3.3)
|
30
|
+
activesupport (= 7.1.3.3)
|
30
31
|
mail (~> 2.5, >= 2.5.4)
|
31
32
|
net-imap
|
32
33
|
net-pop
|
33
34
|
net-smtp
|
34
|
-
rails-dom-testing (~> 2.
|
35
|
-
actionpack (7.
|
36
|
-
actionview (= 7.
|
37
|
-
activesupport (= 7.
|
38
|
-
|
35
|
+
rails-dom-testing (~> 2.2)
|
36
|
+
actionpack (7.1.3.3)
|
37
|
+
actionview (= 7.1.3.3)
|
38
|
+
activesupport (= 7.1.3.3)
|
39
|
+
nokogiri (>= 1.8.5)
|
40
|
+
racc
|
41
|
+
rack (>= 2.2.4)
|
42
|
+
rack-session (>= 1.0.1)
|
39
43
|
rack-test (>= 0.6.3)
|
40
|
-
rails-dom-testing (~> 2.
|
41
|
-
rails-html-sanitizer (~> 1.
|
42
|
-
actiontext (7.
|
43
|
-
actionpack (= 7.
|
44
|
-
activerecord (= 7.
|
45
|
-
activestorage (= 7.
|
46
|
-
activesupport (= 7.
|
44
|
+
rails-dom-testing (~> 2.2)
|
45
|
+
rails-html-sanitizer (~> 1.6)
|
46
|
+
actiontext (7.1.3.3)
|
47
|
+
actionpack (= 7.1.3.3)
|
48
|
+
activerecord (= 7.1.3.3)
|
49
|
+
activestorage (= 7.1.3.3)
|
50
|
+
activesupport (= 7.1.3.3)
|
47
51
|
globalid (>= 0.6.0)
|
48
52
|
nokogiri (>= 1.8.5)
|
49
|
-
actionview (7.
|
50
|
-
activesupport (= 7.
|
53
|
+
actionview (7.1.3.3)
|
54
|
+
activesupport (= 7.1.3.3)
|
51
55
|
builder (~> 3.1)
|
52
|
-
erubi (~> 1.
|
53
|
-
rails-dom-testing (~> 2.
|
54
|
-
rails-html-sanitizer (~> 1.
|
55
|
-
activejob (7.
|
56
|
-
activesupport (= 7.
|
56
|
+
erubi (~> 1.11)
|
57
|
+
rails-dom-testing (~> 2.2)
|
58
|
+
rails-html-sanitizer (~> 1.6)
|
59
|
+
activejob (7.1.3.3)
|
60
|
+
activesupport (= 7.1.3.3)
|
57
61
|
globalid (>= 0.3.6)
|
58
|
-
activemodel (7.
|
59
|
-
activesupport (= 7.
|
60
|
-
activerecord (7.
|
61
|
-
activemodel (= 7.
|
62
|
-
activesupport (= 7.
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
62
|
+
activemodel (7.1.3.3)
|
63
|
+
activesupport (= 7.1.3.3)
|
64
|
+
activerecord (7.1.3.3)
|
65
|
+
activemodel (= 7.1.3.3)
|
66
|
+
activesupport (= 7.1.3.3)
|
67
|
+
timeout (>= 0.4.0)
|
68
|
+
activestorage (7.1.3.3)
|
69
|
+
actionpack (= 7.1.3.3)
|
70
|
+
activejob (= 7.1.3.3)
|
71
|
+
activerecord (= 7.1.3.3)
|
72
|
+
activesupport (= 7.1.3.3)
|
68
73
|
marcel (~> 1.0)
|
69
|
-
|
70
|
-
|
74
|
+
activesupport (7.1.3.3)
|
75
|
+
base64
|
76
|
+
bigdecimal
|
71
77
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
78
|
+
connection_pool (>= 2.2.5)
|
79
|
+
drb
|
72
80
|
i18n (>= 1.6, < 2)
|
73
81
|
minitest (>= 5.1)
|
82
|
+
mutex_m
|
74
83
|
tzinfo (~> 2.0)
|
84
|
+
base64 (0.2.0)
|
85
|
+
bigdecimal (3.1.8)
|
75
86
|
builder (3.2.4)
|
76
87
|
concurrent-ruby (1.2.3)
|
88
|
+
connection_pool (2.4.1)
|
77
89
|
crass (1.0.6)
|
78
90
|
date (3.3.4)
|
79
91
|
debug (1.9.2)
|
80
92
|
irb (~> 1.10)
|
81
93
|
reline (>= 0.3.8)
|
94
|
+
drb (2.2.1)
|
82
95
|
erubi (1.12.0)
|
83
96
|
globalid (1.2.1)
|
84
97
|
activesupport (>= 6.1)
|
@@ -97,9 +110,9 @@ GEM
|
|
97
110
|
net-pop
|
98
111
|
net-smtp
|
99
112
|
marcel (1.0.4)
|
100
|
-
method_source (1.1.0)
|
101
113
|
mini_mime (1.1.5)
|
102
114
|
minitest (5.22.3)
|
115
|
+
mutex_m (0.2.0)
|
103
116
|
net-imap (0.4.11)
|
104
117
|
date
|
105
118
|
net-protocol
|
@@ -133,22 +146,27 @@ GEM
|
|
133
146
|
nio4r (~> 2.0)
|
134
147
|
racc (1.7.3)
|
135
148
|
rack (2.2.9)
|
149
|
+
rack-session (1.0.2)
|
150
|
+
rack (< 3)
|
136
151
|
rack-test (2.1.0)
|
137
152
|
rack (>= 1.3)
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
153
|
+
rackup (1.0.0)
|
154
|
+
rack (< 3)
|
155
|
+
webrick
|
156
|
+
rails (7.1.3.3)
|
157
|
+
actioncable (= 7.1.3.3)
|
158
|
+
actionmailbox (= 7.1.3.3)
|
159
|
+
actionmailer (= 7.1.3.3)
|
160
|
+
actionpack (= 7.1.3.3)
|
161
|
+
actiontext (= 7.1.3.3)
|
162
|
+
actionview (= 7.1.3.3)
|
163
|
+
activejob (= 7.1.3.3)
|
164
|
+
activemodel (= 7.1.3.3)
|
165
|
+
activerecord (= 7.1.3.3)
|
166
|
+
activestorage (= 7.1.3.3)
|
167
|
+
activesupport (= 7.1.3.3)
|
150
168
|
bundler (>= 1.15.0)
|
151
|
-
railties (= 7.
|
169
|
+
railties (= 7.1.3.3)
|
152
170
|
rails-dom-testing (2.2.0)
|
153
171
|
activesupport (>= 5.0.0)
|
154
172
|
minitest
|
@@ -156,13 +174,14 @@ GEM
|
|
156
174
|
rails-html-sanitizer (1.6.0)
|
157
175
|
loofah (~> 2.21)
|
158
176
|
nokogiri (~> 1.14)
|
159
|
-
railties (7.
|
160
|
-
actionpack (= 7.
|
161
|
-
activesupport (= 7.
|
162
|
-
|
177
|
+
railties (7.1.3.3)
|
178
|
+
actionpack (= 7.1.3.3)
|
179
|
+
activesupport (= 7.1.3.3)
|
180
|
+
irb
|
181
|
+
rackup (>= 1.0.0)
|
163
182
|
rake (>= 12.2)
|
164
|
-
thor (~> 1.0)
|
165
|
-
zeitwerk (~> 2.
|
183
|
+
thor (~> 1.0, >= 1.2.2)
|
184
|
+
zeitwerk (~> 2.6)
|
166
185
|
rake (13.2.1)
|
167
186
|
rdoc (6.6.3.1)
|
168
187
|
psych (>= 4.0.0)
|
@@ -179,6 +198,7 @@ GEM
|
|
179
198
|
timeout (0.4.1)
|
180
199
|
tzinfo (2.0.6)
|
181
200
|
concurrent-ruby (~> 1.0)
|
201
|
+
webrick (1.8.1)
|
182
202
|
websocket-driver (0.7.6)
|
183
203
|
websocket-extensions (>= 0.1.0)
|
184
204
|
websocket-extensions (0.1.5)
|
@@ -197,7 +217,7 @@ DEPENDENCIES
|
|
197
217
|
munster!
|
198
218
|
propshaft
|
199
219
|
puma (~> 5.0)
|
200
|
-
rails (
|
220
|
+
rails (>= 7.0.8.1)
|
201
221
|
sqlite3 (~> 1.4)
|
202
222
|
tzinfo-data
|
203
223
|
|
@@ -4,25 +4,16 @@
|
|
4
4
|
# if a banking provider test fails, indicating that the bank might be having an incident
|
5
5
|
|
6
6
|
class WebhookTestHandler < Munster::BaseHandler
|
7
|
-
def
|
8
|
-
true
|
9
|
-
end
|
7
|
+
def valid?(request) = true
|
10
8
|
|
11
|
-
def
|
9
|
+
def process(webhook)
|
12
10
|
return unless webhook.received?
|
13
11
|
webhook.update!(status: "processing")
|
14
|
-
wait(5)
|
15
12
|
webhook.update!(status: "processed")
|
16
13
|
rescue
|
17
|
-
webhook.update!(status: "
|
14
|
+
webhook.update!(status: "error")
|
18
15
|
raise
|
19
16
|
end
|
20
17
|
|
21
|
-
def
|
22
|
-
:test
|
23
|
-
end
|
24
|
-
|
25
|
-
def self.expose_errors_to_sender?
|
26
|
-
true
|
27
|
-
end
|
18
|
+
def expose_errors_to_sender? = true
|
28
19
|
end
|
@@ -61,7 +61,7 @@ Rails.application.configure do
|
|
61
61
|
# config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name")
|
62
62
|
|
63
63
|
if ENV["RAILS_LOG_TO_STDOUT"].present?
|
64
|
-
logger = ActiveSupport::Logger.new(
|
64
|
+
logger = ActiveSupport::Logger.new($stdout)
|
65
65
|
logger.formatter = config.log_formatter
|
66
66
|
config.logger = ActiveSupport::TaggedLogging.new(logger)
|
67
67
|
end
|
data/example/config/routes.rb
CHANGED
data/lib/munster/base_handler.rb
CHANGED
@@ -4,64 +4,59 @@ require_relative "jobs/processing_job"
|
|
4
4
|
|
5
5
|
module Munster
|
6
6
|
class BaseHandler
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def handle(action_dispatch_request)
|
12
|
-
binary_body_str = action_dispatch_request.body.read.force_encoding(Encoding::BINARY)
|
13
|
-
attrs = {
|
14
|
-
body: binary_body_str,
|
15
|
-
handler_module_name: name,
|
16
|
-
handler_event_id: extract_event_id_from_request(action_dispatch_request)
|
17
|
-
}
|
18
|
-
webhook = Munster::ReceivedWebhook.create!(**attrs)
|
19
|
-
|
20
|
-
Munster.configuration.processing_job_class.perform_later(webhook)
|
21
|
-
rescue ActiveRecord::RecordNotUnique # Deduplicated
|
22
|
-
nil
|
23
|
-
end
|
7
|
+
# Gets called from the background job
|
8
|
+
def self.process(...)
|
9
|
+
new.process(...)
|
10
|
+
end
|
24
11
|
|
25
|
-
|
26
|
-
|
27
|
-
|
12
|
+
# Reimplement this method, it's being used in WebhooksController to store incoming webhook.
|
13
|
+
# Also que for processing in the end.
|
14
|
+
# @return [void]
|
15
|
+
def handle(action_dispatch_request)
|
16
|
+
binary_body_str = action_dispatch_request.body.read.force_encoding(Encoding::BINARY)
|
17
|
+
attrs = {
|
18
|
+
body: binary_body_str,
|
19
|
+
handler_module_name: self.class.name,
|
20
|
+
handler_event_id: extract_event_id_from_request(action_dispatch_request)
|
21
|
+
}
|
22
|
+
webhook = Munster::ReceivedWebhook.create!(**attrs)
|
23
|
+
|
24
|
+
Munster.configuration.processing_job_class.perform_later(webhook)
|
25
|
+
rescue ActiveRecord::RecordNotUnique # Deduplicated
|
26
|
+
nil
|
27
|
+
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
# Please consider that this will be used in url, so don't use underscores or any other symbols that are not used in URL.
|
33
|
-
def service_id
|
34
|
-
:base
|
35
|
-
end
|
29
|
+
# This method will be used to process webhook by async worker.
|
30
|
+
def process(received_webhook)
|
31
|
+
end
|
36
32
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
33
|
+
# This method verifies that request actually comes from provider:
|
34
|
+
# signature validation, HTTP authentication, IP whitelisting and the like
|
35
|
+
def valid?(action_dispatch_request)
|
36
|
+
true
|
37
|
+
end
|
42
38
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
39
|
+
# Default implementation just generates UUID, but if the webhook sender sends us
|
40
|
+
# an event ID we use it for deduplication.
|
41
|
+
def extract_event_id_from_request(action_dispatch_request)
|
42
|
+
SecureRandom.uuid
|
43
|
+
end
|
48
44
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
45
|
+
# Webhook senders have varying retry behaviors, and often you want to "pretend"
|
46
|
+
# everything is fine even though there is an error so that they keep sending you
|
47
|
+
# data and do not disable your endpoint forcibly. We allow this to be configured
|
48
|
+
# on a per-handler basis - a better webhooks sender will be able to make out
|
49
|
+
# some sense of the errors.
|
50
|
+
def expose_errors_to_sender?
|
51
|
+
false
|
52
|
+
end
|
57
53
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
end
|
54
|
+
# Tells the controller whether this handler is active or not. This can be used
|
55
|
+
# to deactivate a particular handler via feature flags for example, or use other
|
56
|
+
# logic to determine whether the handler may be used to create new received webhooks
|
57
|
+
# in the system. This is primarily needed for load shedding.
|
58
|
+
def active?
|
59
|
+
true
|
65
60
|
end
|
66
61
|
end
|
67
62
|
end
|
@@ -5,22 +5,22 @@ module Munster
|
|
5
5
|
class HandlerRefused < StandardError
|
6
6
|
end
|
7
7
|
|
8
|
+
class HandlerInactive < StandardError
|
9
|
+
end
|
10
|
+
|
8
11
|
def create
|
9
|
-
handler = lookup_handler(params[:service_id])
|
10
|
-
return render_error("Webhook handler is inactive", :service_unavailable) unless handler.active?
|
12
|
+
handler = lookup_handler(params[:service_id]).new
|
11
13
|
|
14
|
+
raise HandlerInactive unless handler.active?
|
12
15
|
raise HandlerRefused unless handler.valid?(request)
|
13
16
|
|
14
|
-
# FIXME: Duplicated webhook will be overwritten here and processing job will be quite for second time.
|
15
|
-
# This will generate a following error in this case:
|
16
|
-
# Error performing Munster::ProcessingJob (Job ID: b40f3f28-81be-4c99-bce8-9ad879ec9754) from Async(default) in 9.95ms: ActiveRecord::RecordInvalid (Validation failed: Status Invalid transition from processing to received):
|
17
|
-
#
|
18
|
-
# This should be handled properly.
|
19
17
|
handler.handle(request)
|
20
18
|
head :ok
|
19
|
+
rescue KeyError # handler was not found, so we return generic 404 error.
|
20
|
+
render_error("Required parameters were not present in the request", :not_found)
|
21
21
|
rescue => e
|
22
|
-
|
23
|
-
|
22
|
+
Rails.error.set_context(**Munster.configuration.error_context)
|
23
|
+
Rails.error.report(e)
|
24
24
|
|
25
25
|
if handler&.expose_errors_to_sender?
|
26
26
|
error_for_sender_from_exception(e)
|
@@ -33,8 +33,10 @@ module Munster
|
|
33
33
|
case e
|
34
34
|
when HandlerRefused
|
35
35
|
render_error("Webhook handler did not validate the request (signature or authentication may be invalid)", :forbidden)
|
36
|
-
when
|
37
|
-
render_error("
|
36
|
+
when HandlerInactive
|
37
|
+
render_error("Webhook handler is inactive", :service_unavailable)
|
38
|
+
when JSON::ParserError
|
39
|
+
render_error("Request body is not a valid JSON", :bad_request)
|
38
40
|
else
|
39
41
|
render_error("Internal error", :internal_server_error)
|
40
42
|
end
|
@@ -42,11 +44,11 @@ module Munster
|
|
42
44
|
|
43
45
|
def render_error(message_str, status_sym)
|
44
46
|
json = {error: message_str}.to_json
|
45
|
-
render(json
|
47
|
+
render(json: json, status: status_sym)
|
46
48
|
end
|
47
49
|
|
48
50
|
def lookup_handler(service_id_str)
|
49
|
-
Munster.configuration.active_handlers.
|
51
|
+
Munster.configuration.active_handlers.with_indifferent_access.fetch(service_id_str)
|
50
52
|
end
|
51
53
|
end
|
52
54
|
end
|
@@ -1,4 +1,28 @@
|
|
1
1
|
Munster.configure do |config|
|
2
|
-
|
3
|
-
|
2
|
+
# Active Handlers are defined as hash with key as a service_id and handler class that would handle webhook request.
|
3
|
+
# Example:
|
4
|
+
# {:test => TestHandler, :inactive => InactiveHandler}
|
5
|
+
config.active_handlers = {}
|
6
|
+
|
7
|
+
# It's possible to overwrite default processing job to enahance it. As example if you want to add proper locking or retry mechanism.
|
8
|
+
#
|
9
|
+
# Example:
|
10
|
+
#
|
11
|
+
# class WebhookProcessingJob < Munster::ProcessingJob
|
12
|
+
# def perform(webhook)
|
13
|
+
# TokenLock.with(name: "webhook-processing-#{webhook.id}") do
|
14
|
+
# super(webhook)
|
15
|
+
# end
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# This is how you can change processing job:
|
19
|
+
#
|
20
|
+
# config.processing_job_class = WebhookProcessingJob
|
21
|
+
|
22
|
+
# We're using a common interface for error reporting provided by Rails, e.g Rails.error.report. In some cases
|
23
|
+
# you want to enhance those errors with additional context. As example to provide a namespace:
|
24
|
+
#
|
25
|
+
# { appsignal: { namespace: "webhooks" } }
|
26
|
+
#
|
27
|
+
# config.error_context = { appsignal: { namespace: "webhooks" } }
|
4
28
|
end
|
data/lib/munster/version.rb
CHANGED
data/lib/munster.rb
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
require_relative "munster/version"
|
4
4
|
require_relative "munster/engine"
|
5
|
-
require "active_support/configurable"
|
6
5
|
require_relative "munster/jobs/processing_job"
|
6
|
+
require "active_support/configurable"
|
7
7
|
|
8
8
|
module Munster
|
9
9
|
def self.configuration
|
@@ -20,4 +20,5 @@ class Munster::Configuration
|
|
20
20
|
|
21
21
|
config_accessor(:processing_job_class) { Munster::ProcessingJob }
|
22
22
|
config_accessor(:active_handlers) { [] }
|
23
|
+
config_accessor(:error_context) { {} }
|
23
24
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: munster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stanislav Katkov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -88,6 +88,7 @@ extensions: []
|
|
88
88
|
extra_rdoc_files: []
|
89
89
|
files:
|
90
90
|
- ".editorconfig"
|
91
|
+
- ".rubocop.yml"
|
91
92
|
- ".standard.yml"
|
92
93
|
- CHANGELOG.md
|
93
94
|
- LICENSE
|
@@ -110,7 +111,7 @@ files:
|
|
110
111
|
- example/app/models/application_record.rb
|
111
112
|
- example/app/models/concerns/.keep
|
112
113
|
- example/app/views/layouts/application.html.erb
|
113
|
-
- example/app/webhooks/
|
114
|
+
- example/app/webhooks/webhook_test_handler.rb
|
114
115
|
- example/bin/bundle
|
115
116
|
- example/bin/rails
|
116
117
|
- example/bin/rake
|