tobox 0.2.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -0
- data/README.md +62 -0
- data/lib/tobox/configuration.rb +3 -1
- data/lib/tobox/fetcher.rb +21 -5
- data/lib/tobox/plugins/sentry.rb +2 -2
- data/lib/tobox/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee99cb00423c6956bff6231956ddd964680d374d0ade2402af46b8246d0ae33a
|
4
|
+
data.tar.gz: 2c39e05251cff04e03fb514395118448ab10ad90d005a4c4e4fb54189eef2f3b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 98bfab94ac55fec6019706862eb39daad743e57f0fa9433f5badfca714ec63add109108d44dcbd48ba32d89bf297280ae26a233771fb453804a468410843a387
|
7
|
+
data.tar.gz: 1ac228909e4308b792b8af1586f931415bbc312f968648047904a2bcf47afd09cf2ff0065119b6a4f08619e5b6af5f78c955d9fe63d579d66d3705c207e0e37a
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,38 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.3.1] - 2022-03-03
|
4
|
+
|
5
|
+
### Bugfixes
|
6
|
+
|
7
|
+
In Sentry plugin, exception capturing is no longer dependent on transaction monitoring being enabled (if `traces_sampling_rate` would be set to 0, exceptions wouldn't be capture; now they are).
|
8
|
+
|
9
|
+
## [0.3.0] - 2022-12-12
|
10
|
+
|
11
|
+
### Features
|
12
|
+
|
13
|
+
#### Inbox
|
14
|
+
|
15
|
+
Implementation of the "inbox pattern", which ensures that events are processed to completion only once.
|
16
|
+
|
17
|
+
```ruby
|
18
|
+
# create an inbox table and reference it
|
19
|
+
create_table(:inbox) do
|
20
|
+
column :id, :varchar, null: true, primary_key: true
|
21
|
+
# ...
|
22
|
+
create_table(:outbox) do
|
23
|
+
column :inbox_id, :varchar
|
24
|
+
foreign_key :inbox_id, :inbox
|
25
|
+
# ...
|
26
|
+
|
27
|
+
# tobox.rb
|
28
|
+
inbox_table :inbox
|
29
|
+
inbox_column :inbox_id
|
30
|
+
|
31
|
+
# event production
|
32
|
+
DB[:outbox].insert(event_type: "order_created", inbox_id: "order_created_#{order.id}", ....
|
33
|
+
DB[:outbox].insert(event_type: "billing_event_started", inbox_id: "billing_event_started_#{order.id}", ....
|
34
|
+
```
|
35
|
+
|
3
36
|
## [0.2.0] - 2022-12-05
|
4
37
|
|
5
38
|
### Features
|
data/README.md
CHANGED
@@ -15,6 +15,7 @@ Simple, data-first events processing framework based on the [transactional outbo
|
|
15
15
|
- [Event](#event)
|
16
16
|
- [Features](#features)
|
17
17
|
- [Ordered event processing](#ordered-event-processing)
|
18
|
+
- [Inbox](#inbox)
|
18
19
|
- [Plugins](#plugins)
|
19
20
|
- [Zeitwerk](#zeitwerk)
|
20
21
|
- [Sentry](#sentry)
|
@@ -299,6 +300,14 @@ Overrides the default log level ("info" when in "production" environment, "debug
|
|
299
300
|
|
300
301
|
Defines the column to be used for event grouping, when [ordered processing of events is a requirement](#ordered-event-processing).
|
301
302
|
|
303
|
+
### inbox table
|
304
|
+
|
305
|
+
Defines the name of the table to be used for inbox, when [inbox usage is a requirement](#inbox).
|
306
|
+
|
307
|
+
### inbox column
|
308
|
+
|
309
|
+
Defines the column in the outbox table which references the inbox table, when one is set.
|
310
|
+
|
302
311
|
<a id="markdown-event" name="event"></a>
|
303
312
|
## Event
|
304
313
|
|
@@ -361,6 +370,59 @@ end
|
|
361
370
|
# "order_created" will be processed first
|
362
371
|
# "billing_event_created" will only start processing once "order_created" finishes
|
363
372
|
```
|
373
|
+
<a id="inbox" name="inbox"></a>
|
374
|
+
### Inbox
|
375
|
+
|
376
|
+
`tobox` also supports the [inbox pattern](https://event-driven.io/en/outbox_inbox_patterns_and_delivery_guarantees_explained/), to ensure "exactly-once" processing of events. This is achieved by "tagging" events with a unique identifier, and registering them in the inbox before processing (and if they're there, ignoring it altogether).
|
377
|
+
|
378
|
+
In order to do so, you'll have to:
|
379
|
+
|
380
|
+
1. add an "inbox" table in the database
|
381
|
+
|
382
|
+
```ruby
|
383
|
+
create_table(:inbox) do
|
384
|
+
column :inbox_id, :varchar, null: true, primary_key: true # it can also be a uuid, you decide
|
385
|
+
column :created_at, "timestamp without time zone", null: false, default: Sequel::CURRENT_TIMESTAMP
|
386
|
+
end
|
387
|
+
```
|
388
|
+
|
389
|
+
2. add the unique id reference in the outbox table:
|
390
|
+
|
391
|
+
```ruby
|
392
|
+
create_table(:outbox) do
|
393
|
+
primary_key :id
|
394
|
+
column :type, :varchar, null: false
|
395
|
+
column :inbox_id, :varchar, null: true
|
396
|
+
# ...
|
397
|
+
foreign_key :inbox_id, :inbox
|
398
|
+
```
|
399
|
+
|
400
|
+
3. reference them in the configuration
|
401
|
+
|
402
|
+
```ruby
|
403
|
+
# tobox.rb
|
404
|
+
inbox_table :inbox
|
405
|
+
inbox_column :inbox_id
|
406
|
+
```
|
407
|
+
|
408
|
+
4. insert related outbox events with an inbox id
|
409
|
+
|
410
|
+
```ruby
|
411
|
+
order = Order.new(
|
412
|
+
item_id: item.id,
|
413
|
+
price: 20_20,
|
414
|
+
currency: "EUR"
|
415
|
+
)
|
416
|
+
DB.transaction do
|
417
|
+
order.save
|
418
|
+
DB[:outbox].insert(event_type: "order_created", inbox_id: "ord_crt_#{order.id}", data_after: order.to_hash)
|
419
|
+
DB[:outbox].insert(event_type: "billing_event_started", inbox_id: "bil_evt_std_#{order.id}", data_after: order.to_hash)
|
420
|
+
end
|
421
|
+
|
422
|
+
# assuming this bit above runs two times in two separate workers, each will be processed by tobox only once.
|
423
|
+
```
|
424
|
+
|
425
|
+
**NOTE**: make sure you keep cleaning the inbox periodically from older messages, once there's no more danger of receiving them again.
|
364
426
|
|
365
427
|
<a id="markdown-plugins" name="plugins"></a>
|
366
428
|
## Plugins
|
data/lib/tobox/configuration.rb
CHANGED
@@ -18,6 +18,8 @@ module Tobox
|
|
18
18
|
database_uri: nil,
|
19
19
|
table: :outbox,
|
20
20
|
group_column: nil,
|
21
|
+
inbox_table: nil,
|
22
|
+
inbox_column: nil,
|
21
23
|
max_attempts: 10,
|
22
24
|
exponential_retry_factor: 4,
|
23
25
|
wait_for_events_delay: 5,
|
@@ -122,7 +124,7 @@ module Tobox
|
|
122
124
|
def method_missing(meth, *args, &block)
|
123
125
|
if DEFAULT_CONFIGURATION.key?(meth) && args.size == 1
|
124
126
|
@config[meth] = args.first
|
125
|
-
elsif /\Aon_(.*)\z/.match(meth) && args.
|
127
|
+
elsif /\Aon_(.*)\z/.match(meth) && args.empty?
|
126
128
|
on(Regexp.last_match(1).to_sym, &block)
|
127
129
|
else
|
128
130
|
super
|
data/lib/tobox/fetcher.rb
CHANGED
@@ -24,6 +24,9 @@ module Tobox
|
|
24
24
|
|
25
25
|
max_attempts = configuration[:max_attempts]
|
26
26
|
|
27
|
+
@inbox_table = configuration[:inbox_table]
|
28
|
+
@inbox_column = configuration[:inbox_column]
|
29
|
+
|
27
30
|
@ds = @db[@table]
|
28
31
|
|
29
32
|
run_at_conds = [
|
@@ -80,14 +83,17 @@ module Tobox
|
|
80
83
|
if blk
|
81
84
|
num_events = events.size
|
82
85
|
|
83
|
-
events.
|
84
|
-
|
85
|
-
|
86
|
-
|
86
|
+
events.map! do |ev|
|
87
|
+
try_insert_inbox(ev) do
|
88
|
+
ev[:metadata] = try_json_parse(ev[:metadata])
|
89
|
+
handle_before_event(ev)
|
90
|
+
yield(to_message(ev))
|
91
|
+
ev
|
92
|
+
end
|
87
93
|
rescue StandardError => e
|
88
94
|
error = e
|
89
95
|
raise Sequel::Rollback
|
90
|
-
end
|
96
|
+
end.compact!
|
91
97
|
else
|
92
98
|
events.map!(&method(:to_message))
|
93
99
|
end
|
@@ -148,6 +154,16 @@ module Tobox
|
|
148
154
|
data
|
149
155
|
end
|
150
156
|
|
157
|
+
def try_insert_inbox(event)
|
158
|
+
return yield unless @inbox_table && @inbox_column
|
159
|
+
|
160
|
+
ret = @db[@inbox_table].insert_conflict.insert(@inbox_column => event[@inbox_column])
|
161
|
+
|
162
|
+
return unless ret
|
163
|
+
|
164
|
+
yield
|
165
|
+
end
|
166
|
+
|
151
167
|
def handle_before_event(event)
|
152
168
|
@logger.debug do
|
153
169
|
log_message("outbox event (type: \"#{event[:type]}\", attempts: #{event[:attempts]}) starting...")
|
data/lib/tobox/plugins/sentry.rb
CHANGED
@@ -74,12 +74,12 @@ module Tobox
|
|
74
74
|
def on_error(event, error)
|
75
75
|
return unless ::Sentry.initialized?
|
76
76
|
|
77
|
+
capture_exception(event, error)
|
78
|
+
|
77
79
|
transaction = retrieve_transaction(event)
|
78
80
|
|
79
81
|
return unless transaction
|
80
82
|
|
81
|
-
capture_exception(event, error)
|
82
|
-
|
83
83
|
finish_transaction(transaction, 500)
|
84
84
|
end
|
85
85
|
|
data/lib/tobox/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tobox
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- HoneyryderChuck
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|