tobox 0.2.0 → 0.3.1
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/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
         |