natsy 0.3.0 → 0.4.3
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/.github/workflows/main.yml +8 -0
- data/.rubocop.yml +17 -1
- data/README.md +104 -26
- data/lib/natsy.rb +4 -0
- data/lib/natsy/client.rb +53 -72
- data/lib/natsy/config.rb +255 -0
- data/lib/natsy/controller.rb +6 -7
- data/lib/natsy/utils.rb +14 -0
- data/lib/natsy/version.rb +1 -1
- data/natsy.gemspec +1 -1
- metadata +18 -18
- data/CHANGELOG.md +0 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: e8c3433d746ea11eacc51f7e602ab6a0d0816a69c5ef7db7e802847cf5b931fd
         | 
| 4 | 
            +
              data.tar.gz: 79dc340ffefbe6371558fa1cd901977e55215f8cbda71024fcd930dda94eab2c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: e7c12f04962acfb2e36bfd1ad580da552678dd26a6c5c51b7b373ef69f816a2018bc72a1c2ad2278b394f0e9e7d18f3d942dd46883a01630b1e30384e21fcc9a
         | 
| 7 | 
            +
              data.tar.gz: af46e5498949a3806972d9a5a26fdadfc275e3d8914338c634a3cc01ab33c45b26fb48849103ec8a786903d580685912b418df099ace08f9aa5fbdcc9b05dfbb
         | 
    
        data/.github/workflows/main.yml
    CHANGED
    
    
    
        data/.rubocop.yml
    CHANGED
    
    | @@ -26,13 +26,20 @@ Layout/FirstArrayElementIndentation: | |
| 26 26 | 
             
            # Metrics
         | 
| 27 27 |  | 
| 28 28 | 
             
            Metrics/AbcSize:
         | 
| 29 | 
            -
              Max:  | 
| 29 | 
            +
              Max: 35
         | 
| 30 30 | 
             
              CountRepeatedAttributes: false
         | 
| 31 31 | 
             
              Exclude:
         | 
| 32 32 | 
             
                - 'spec/**/*_spec.rb'
         | 
| 33 33 | 
             
                - '*.gemspec'
         | 
| 34 34 |  | 
| 35 35 | 
             
            Metrics/BlockLength:
         | 
| 36 | 
            +
              Max: 50
         | 
| 37 | 
            +
              Exclude:
         | 
| 38 | 
            +
                - 'spec/**/*_spec.rb'
         | 
| 39 | 
            +
                - '*.gemspec'
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            Metrics/CyclomaticComplexity:
         | 
| 42 | 
            +
              Max: 15
         | 
| 36 43 | 
             
              Exclude:
         | 
| 37 44 | 
             
                - 'spec/**/*_spec.rb'
         | 
| 38 45 | 
             
                - '*.gemspec'
         | 
| @@ -55,6 +62,9 @@ Metrics/MethodLength: | |
| 55 62 | 
             
                - array
         | 
| 56 63 | 
             
                - hash
         | 
| 57 64 | 
             
                - heredoc
         | 
| 65 | 
            +
              Exclude:
         | 
| 66 | 
            +
                - 'spec/**/*_spec.rb'
         | 
| 67 | 
            +
                - '*.gemspec'
         | 
| 58 68 |  | 
| 59 69 | 
             
            Metrics/ModuleLength:
         | 
| 60 70 | 
             
              Max: 150
         | 
| @@ -67,6 +77,12 @@ Metrics/ModuleLength: | |
| 67 77 | 
             
                - 'spec/**/*_spec.rb'
         | 
| 68 78 | 
             
                - '*.gemspec'
         | 
| 69 79 |  | 
| 80 | 
            +
            Metrics/PerceivedComplexity:
         | 
| 81 | 
            +
              Max: 20
         | 
| 82 | 
            +
              Exclude:
         | 
| 83 | 
            +
                - 'spec/**/*_spec.rb'
         | 
| 84 | 
            +
                - '*.gemspec'
         | 
| 85 | 
            +
             | 
| 70 86 | 
             
            # Rspec
         | 
| 71 87 |  | 
| 72 88 | 
             
            RSpec/ExampleLength:
         | 
    
        data/README.md
    CHANGED
    
    | @@ -5,14 +5,15 @@ The `natsy` gem allows you to listen for (and reply to) NATS messages asynchrono | |
| 5 5 | 
             
            ## TODO
         | 
| 6 6 |  | 
| 7 7 | 
             
            - [x] docs
         | 
| 8 | 
            -
            - [ | 
| 8 | 
            +
            - [x] tests
         | 
| 9 9 | 
             
            - [x] "controller"-style classes for reply organization
         | 
| 10 10 | 
             
            - [x] runtime subscription additions
         | 
| 11 11 | 
             
            - [x] multiple queues
         | 
| 12 | 
            -
            - [ | 
| 13 | 
            -
            - [ ] config options for URL/host/port/etc.
         | 
| 12 | 
            +
            - [x] config options for URL/host/port/etc.
         | 
| 14 13 | 
             
            - [ ] config for restart behavior (default is to restart listening on any `StandardError`)
         | 
| 15 | 
            -
            - [ ]  | 
| 14 | 
            +
            - [ ] `on_error` handler so you can send a response (what's standard?)
         | 
| 15 | 
            +
            - [ ] support lifecycle callbacks (like `on_connect`, `on_disconnect`, etc.) provided by the `nats` gem
         | 
| 16 | 
            +
            - [ ] ability to _request_ (not just reply)
         | 
| 16 17 |  | 
| 17 18 | 
             
            ## Installation
         | 
| 18 19 |  | 
| @@ -44,6 +45,8 @@ This gem also requires a NATS server to be installed and running before use. See | |
| 44 45 |  | 
| 45 46 | 
             
            ## Usage
         | 
| 46 47 |  | 
| 48 | 
            +
            <a id="starting-the-nats-server-section">
         | 
| 49 | 
            +
             | 
| 47 50 | 
             
            ### Starting the NATS server
         | 
| 48 51 |  | 
| 49 52 | 
             
            You'll need to start a NATS server before running your Ruby application. If you installed it via Docker, you might start it like so:
         | 
| @@ -56,6 +59,57 @@ docker run -p 4222:4222 -p 8222:8222 -p 6222:6222 -ti nats:latest | |
| 56 59 |  | 
| 57 60 | 
             
            > **NOTE:** For other methods of running a NATS server, see [the NATS documentation](https://docs.nats.io/nats-server/installation).
         | 
| 58 61 |  | 
| 62 | 
            +
            ### Configuration
         | 
| 63 | 
            +
             | 
| 64 | 
            +
            Use `Natsy::Config::set` to set configuration options. These options can either be set via a `Hash`/keyword arguments passed to the `::set` method, or set by invoking the method with a block and assigning your options to the yielded `Natsy::Config::Options` instance.
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            This README will use the following two syntaxes interchangably; remember that they do **exactly the same thing:**
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            ```ruby
         | 
| 69 | 
            +
            Natsy::Config.set(
         | 
| 70 | 
            +
              urls: ["nats://foo.bar:4567", "nats://foo.bar:5678"],
         | 
| 71 | 
            +
              default_queue: "foobar",
         | 
| 72 | 
            +
              logger: Rails.logger,
         | 
| 73 | 
            +
            )
         | 
| 74 | 
            +
            ```
         | 
| 75 | 
            +
             | 
| 76 | 
            +
            ```ruby
         | 
| 77 | 
            +
            Natsy::Config.set do |options|
         | 
| 78 | 
            +
              options.urls = ["nats://foo.bar:4567", "nats://foo.bar:5678"]
         | 
| 79 | 
            +
              options.default_queue = "foobar"
         | 
| 80 | 
            +
              options.logger = Rails.logger
         | 
| 81 | 
            +
            end
         | 
| 82 | 
            +
            ```
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            The following options are available:
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            - `url`: A single URL string (including protocol, domain, and port) which points to the relevant NATS server (see [here](#setting-nats-server-url-section) for more info)
         | 
| 87 | 
            +
            - `urls`: An array of URL strings in case you need to listen to multiple NATS servers (see [here](#setting-nats-server-url-section) for more info)
         | 
| 88 | 
            +
            - `logger`: A logger where `natsy` can write helpful information (see [here](#logging-section) for more info)
         | 
| 89 | 
            +
            - `default_queue`: The default queue that your application should fall back to if none is given in a more specific context (see [here](#default-queue-section) for more info)
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            <a id="setting-nats-server-url-section"></a>
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            ### Setting the NATS server URL(s)
         | 
| 94 | 
            +
             | 
| 95 | 
            +
            Set the URL/URLs at which your NATS server mediates messages.
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            ```ruby
         | 
| 98 | 
            +
            Natsy::Config.set do |options|
         | 
| 99 | 
            +
              options.url = "nats://foo.bar:4567"
         | 
| 100 | 
            +
            end
         | 
| 101 | 
            +
            ```
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            ```ruby
         | 
| 104 | 
            +
            Natsy::Config.set do |options|
         | 
| 105 | 
            +
              options.urls = ["nats://foo.bar:4567", "nats://foo.bar:5678"]
         | 
| 106 | 
            +
            end
         | 
| 107 | 
            +
            ```
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            > **NOTE:** If no `url`/`urls` option is specified, `natsy` will fall back on the default NATS server URL, which is `nats://localhost:4222`.
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            <a id="logging-section"></a>
         | 
| 112 | 
            +
             | 
| 59 113 | 
             
            ### Logging
         | 
| 60 114 |  | 
| 61 115 | 
             
            #### Attaching a logger
         | 
| @@ -66,23 +120,24 @@ Attach a logger to have `natsy` write out logs for messages received, responses | |
| 66 120 | 
             
            require 'natsy'
         | 
| 67 121 | 
             
            require 'logger'
         | 
| 68 122 |  | 
| 69 | 
            -
             | 
| 70 | 
            -
            nats_logger | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 123 | 
            +
            Natsy::Config.set do |options|
         | 
| 124 | 
            +
              nats_logger = Logger.new(STDOUT)
         | 
| 125 | 
            +
              nats_logger.level = Logger::INFO
         | 
| 126 | 
            +
              options.logger = nats_logger
         | 
| 127 | 
            +
            end
         | 
| 73 128 | 
             
            ```
         | 
| 74 129 |  | 
| 75 130 | 
             
            In a Rails application, you might do this instead:
         | 
| 76 131 |  | 
| 77 132 | 
             
            ```ruby
         | 
| 78 | 
            -
            Natsy:: | 
| 133 | 
            +
            Natsy::Config.set(logger: Rails.logger)
         | 
| 79 134 | 
             
            ```
         | 
| 80 135 |  | 
| 81 136 | 
             
            #### Log levels
         | 
| 82 137 |  | 
| 83 138 | 
             
            The following will be logged at the specified log levels
         | 
| 84 139 |  | 
| 85 | 
            -
            - `DEBUG`: Lifecycle events (starting NATS listeners, stopping NATS, reply registration,  | 
| 140 | 
            +
            - `DEBUG`: Lifecycle events (starting NATS listeners, stopping NATS, reply registration, etc.), as well as everything under `INFO`, `WARN`, and `ERROR`
         | 
| 86 141 | 
             
            - `INFO`: Message activity over NATS (received a message, replied with a message, etc.), as well as everything under `WARN` and `ERROR`
         | 
| 87 142 | 
             
            - `WARN`: Error handled gracefully (listening restarted due to some exception, etc.), as well as everything under `ERROR`
         | 
| 88 143 | 
             
            - `ERROR`: Some exception was raised in-thread (error in handler, error in subscription, etc.)
         | 
| @@ -94,13 +149,13 @@ The following will be logged at the specified log levels | |
| 94 149 | 
             
            Set a default queue for subscriptions.
         | 
| 95 150 |  | 
| 96 151 | 
             
            ```ruby
         | 
| 97 | 
            -
            Natsy:: | 
| 152 | 
            +
            Natsy::Config.set(default_queue: "foobar")
         | 
| 98 153 | 
             
            ```
         | 
| 99 154 |  | 
| 100 | 
            -
            Leave the  | 
| 155 | 
            +
            Leave the `default_queue` blank (or assign `nil`) to use no default queue.
         | 
| 101 156 |  | 
| 102 157 | 
             
            ```ruby
         | 
| 103 | 
            -
            Natsy:: | 
| 158 | 
            +
            Natsy::Config.set(default_queue: nil)
         | 
| 104 159 | 
             
            ```
         | 
| 105 160 |  | 
| 106 161 | 
             
            <a id="reply-to-section"></a>
         | 
| @@ -153,15 +208,29 @@ The following should be enough to start a `natsy` setup in your Ruby application | |
| 153 208 | 
             
            require 'natsy'
         | 
| 154 209 | 
             
            require 'logger'
         | 
| 155 210 |  | 
| 156 | 
            -
             | 
| 157 | 
            -
            nats_logger | 
| 211 | 
            +
            Natsy::Config.set do |options|
         | 
| 212 | 
            +
              nats_logger = Logger.new(STDOUT)
         | 
| 213 | 
            +
              nats_logger.level = Logger::DEBUG
         | 
| 158 214 |  | 
| 159 | 
            -
             | 
| 160 | 
            -
             | 
| 215 | 
            +
              options.logger = nats_logger
         | 
| 216 | 
            +
              options.urls = ["nats://foo.bar:4567", "nats://foo.bar:5678"]
         | 
| 217 | 
            +
              options.default_queue = "foobar"
         | 
| 218 | 
            +
            end
         | 
| 161 219 |  | 
| 162 | 
            -
            Natsy::Client.reply_to("some.subject")  | 
| 163 | 
            -
             | 
| 164 | 
            -
             | 
| 220 | 
            +
            Natsy::Client.reply_to("some.subject") do |data|
         | 
| 221 | 
            +
              "Got it! #{data.inspect}"
         | 
| 222 | 
            +
            end
         | 
| 223 | 
            +
             | 
| 224 | 
            +
            Natsy::Client.reply_to("some.*.pattern") do |data, subject|
         | 
| 225 | 
            +
              "Got #{data} on #{subject}"
         | 
| 226 | 
            +
            end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
            Natsy::Client.reply_to("subject.in.queue", queue: "barbaz") do
         | 
| 229 | 
            +
              {
         | 
| 230 | 
            +
                msg: "My turn!",
         | 
| 231 | 
            +
                turn: 5,
         | 
| 232 | 
            +
              }
         | 
| 233 | 
            +
            end
         | 
| 165 234 |  | 
| 166 235 | 
             
            Natsy::Client.start!
         | 
| 167 236 | 
             
            ```
         | 
| @@ -172,7 +241,7 @@ Natsy::Client.start! | |
| 172 241 |  | 
| 173 242 | 
             
            Create controller classes which inherit from `Natsy::Controller` in order to give your message listeners some structure.
         | 
| 174 243 |  | 
| 175 | 
            -
            Use the `::default_queue` macro to set a default queue string. If omitted, the controller will fall back on the global default queue assigned  | 
| 244 | 
            +
            Use the `::default_queue` macro to set a default queue string. If omitted, the controller will fall back on the global default queue assigned to `Natsy::Config::default_queue` (as described [here](#default-queue-section)). If no default queue is set in either the controller or globally, then the default queue will be blank. Set the default queue to `nil` in a controller to fall back to the global default queue.
         | 
| 176 245 |  | 
| 177 246 | 
             
            Use the `::subject` macro to create a block for listening to that subject segment. Nested calls to `::subject` will append each subsequent subject/pattern string to the last (joined by a periods). There is no limit to the level of nesting.
         | 
| 178 247 |  | 
| @@ -208,9 +277,13 @@ class HelloController < Natsy::Controller | |
| 208 277 | 
             
              end
         | 
| 209 278 |  | 
| 210 279 | 
             
              subject "hows" do
         | 
| 211 | 
            -
                 | 
| 280 | 
            +
                # The queue at this point is "foobar"
         | 
| 281 | 
            +
                subject "*", queue: "barbaz" do # Override the default queue at any point
         | 
| 282 | 
            +
                  # The queue at this point is "barbaz" (!)
         | 
| 212 283 | 
             
                  subject "doing" do
         | 
| 213 | 
            -
                     | 
| 284 | 
            +
                    # The queue at this point is "barbaz"
         | 
| 285 | 
            +
                    response queue: "bazbam" do |data, subject|
         | 
| 286 | 
            +
                      # The queue at this point is "bazbam" (!)
         | 
| 214 287 | 
             
                      # The subject at this point is "hows.<wildcard>.doing" (i.e., the
         | 
| 215 288 | 
             
                      # subjects "hows.jack.doing" and "hows.jill.doing" will both match)
         | 
| 216 289 | 
             
                      sender_name = data["name"]
         | 
| @@ -229,8 +302,7 @@ end | |
| 229 302 | 
             
            > For example: in a Rails project (assuming you have your NATS controllers in a directory called `app/nats/`), you may want to put something like the following in an initializer (such as `config/initializers/nats.rb`):
         | 
| 230 303 | 
             
            >
         | 
| 231 304 | 
             
            > ```ruby
         | 
| 232 | 
            -
            > Natsy:: | 
| 233 | 
            -
            > Natsy::Client.default_queue = "foobar"
         | 
| 305 | 
            +
            > Natsy::Config.set(logger: Rails.logger, default_queue: "foobar")
         | 
| 234 306 | 
             
            >
         | 
| 235 307 | 
             
            > # ...
         | 
| 236 308 | 
             
            >
         | 
| @@ -267,7 +339,7 @@ bin/console | |
| 267 339 |  | 
| 268 340 | 
             
            ### Run the tests
         | 
| 269 341 |  | 
| 270 | 
            -
            To run the RSpec test suites, run:
         | 
| 342 | 
            +
            To run the RSpec test suites, first [start the NATS server](#starting-the-nats-server-section). Then, run the tests:
         | 
| 271 343 |  | 
| 272 344 | 
             
            ```bash
         | 
| 273 345 | 
             
            bundle exec rake spec
         | 
| @@ -285,6 +357,12 @@ rake spec | |
| 285 357 | 
             
            bundle exec rubocop
         | 
| 286 358 | 
             
            ```
         | 
| 287 359 |  | 
| 360 | 
            +
            ...or (if your Ruby setup has good defaults) just this:
         | 
| 361 | 
            +
             | 
| 362 | 
            +
            ```bash
         | 
| 363 | 
            +
            rubocop
         | 
| 364 | 
            +
            ```
         | 
| 365 | 
            +
             | 
| 288 366 | 
             
            ### Create a release
         | 
| 289 367 |  | 
| 290 368 | 
             
            Bump the `Natsy::VERSION` value in `lib/natsy/version.rb`, commit, and then run:
         | 
    
        data/lib/natsy.rb
    CHANGED
    
    | @@ -3,6 +3,7 @@ | |
| 3 3 | 
             
            require "nats/client"
         | 
| 4 4 | 
             
            require_relative "natsy/version"
         | 
| 5 5 | 
             
            require_relative "natsy/utils"
         | 
| 6 | 
            +
            require_relative "natsy/config"
         | 
| 6 7 | 
             
            require_relative "natsy/client"
         | 
| 7 8 | 
             
            require_relative "natsy/controller"
         | 
| 8 9 |  | 
| @@ -14,4 +15,7 @@ module Natsy | |
| 14 15 |  | 
| 15 16 | 
             
              # New subscription has been added at runtime
         | 
| 16 17 | 
             
              class NewSubscriptionsError < Natsy::Error; end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              # Invalid options have been provided to +Natsy::Config+
         | 
| 20 | 
            +
              class InvalidConfigError < Natsy::Error; end
         | 
| 17 21 | 
             
            end
         | 
    
        data/lib/natsy/client.rb
    CHANGED
    
    | @@ -10,50 +10,6 @@ module Natsy | |
| 10 10 | 
             
              # most functionality if desired.
         | 
| 11 11 | 
             
              class Client
         | 
| 12 12 | 
             
                class << self
         | 
| 13 | 
            -
                  # Optional logger for lifecycle events, messages received, etc.
         | 
| 14 | 
            -
                  attr_reader :logger
         | 
| 15 | 
            -
             | 
| 16 | 
            -
                  # Optional default queue for message subscription and replies.
         | 
| 17 | 
            -
                  attr_reader :default_queue
         | 
| 18 | 
            -
             | 
| 19 | 
            -
                  # Attach a logger to have +natsy+ write out logs for messages
         | 
| 20 | 
            -
                  # received, responses sent, errors raised, lifecycle events, etc.
         | 
| 21 | 
            -
                  #
         | 
| 22 | 
            -
                  # @example
         | 
| 23 | 
            -
                  #   require 'natsy'
         | 
| 24 | 
            -
                  #   require 'logger'
         | 
| 25 | 
            -
                  #
         | 
| 26 | 
            -
                  #   nats_logger = Logger.new(STDOUT)
         | 
| 27 | 
            -
                  #   nats_logger.level = Logger::INFO
         | 
| 28 | 
            -
                  #
         | 
| 29 | 
            -
                  #   Natsy::Client.logger = nats_logger
         | 
| 30 | 
            -
                  #
         | 
| 31 | 
            -
                  # In a Rails application, you might do this instead:
         | 
| 32 | 
            -
                  #
         | 
| 33 | 
            -
                  # @example
         | 
| 34 | 
            -
                  #   Natsy::Client.logger = Rails.logger
         | 
| 35 | 
            -
                  #
         | 
| 36 | 
            -
                  def logger=(some_logger)
         | 
| 37 | 
            -
                    @logger = some_logger
         | 
| 38 | 
            -
                    log("Set the logger to #{@logger.inspect}")
         | 
| 39 | 
            -
                  end
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                  # Set a default queue for subscriptions.
         | 
| 42 | 
            -
                  #
         | 
| 43 | 
            -
                  # @example
         | 
| 44 | 
            -
                  #   Natsy::Client.default_queue = "foobar"
         | 
| 45 | 
            -
                  #
         | 
| 46 | 
            -
                  # Leave the +::default_queue+ blank (or assign +nil+) to use no default
         | 
| 47 | 
            -
                  # queue.
         | 
| 48 | 
            -
                  #
         | 
| 49 | 
            -
                  # @example
         | 
| 50 | 
            -
                  #   Natsy::Client.default_queue = nil
         | 
| 51 | 
            -
                  #
         | 
| 52 | 
            -
                  def default_queue=(some_queue)
         | 
| 53 | 
            -
                    @default_queue = Utils.presence(some_queue.to_s)
         | 
| 54 | 
            -
                    log("Setting the default queue to #{@default_queue || '(none)'}", level: :debug)
         | 
| 55 | 
            -
                  end
         | 
| 56 | 
            -
             | 
| 57 13 | 
             
                  # Returns +true+ if +::start!+ has already been called (meaning the client
         | 
| 58 14 | 
             
                  # is listening to NATS messages). Returns +false+ if it has not yet been
         | 
| 59 15 | 
             
                  # called, or if it has been stopped.
         | 
| @@ -72,8 +28,9 @@ module Natsy | |
| 72 28 | 
             
                  # method. Pass a subject string as the first argument (either a static
         | 
| 73 29 | 
             
                  # subject string or a pattern to match more than one subject). Specify a
         | 
| 74 30 | 
             
                  # queue (or don't) with the +queue:+ option. If you don't provide the
         | 
| 75 | 
            -
                  # +queue:+ option, it will be set to the value of | 
| 76 | 
            -
                  # +nil+ (no queue) if a default | 
| 31 | 
            +
                  # +queue:+ option, it will be set to the value of
         | 
| 32 | 
            +
                  # +Natsy::Config::default_queue+, or to +nil+ (no queue) if a default
         | 
| 33 | 
            +
                  # queue hasn't been set.
         | 
| 77 34 | 
             
                  #
         | 
| 78 35 | 
             
                  # The result of the given block will be published in reply to the message.
         | 
| 79 36 | 
             
                  # The block is passed two arguments when a message matching the subject is
         | 
| @@ -101,7 +58,7 @@ module Natsy | |
| 101 58 | 
             
                  #   end
         | 
| 102 59 | 
             
                  #
         | 
| 103 60 | 
             
                  def reply_to(subject, queue: nil, &block)
         | 
| 104 | 
            -
                    queue = Utils.presence(queue) || default_queue
         | 
| 61 | 
            +
                    queue = Utils.presence(queue) || Config.default_queue
         | 
| 105 62 | 
             
                    queue_desc = " in queue '#{queue}'" if queue
         | 
| 106 63 | 
             
                    log("Registering a reply handler for subject '#{subject}'#{queue_desc}", level: :debug)
         | 
| 107 64 | 
             
                    register_reply!(subject: subject.to_s, handler: block, queue: queue.to_s)
         | 
| @@ -145,44 +102,54 @@ module Natsy | |
| 145 102 |  | 
| 146 103 | 
             
                    started!
         | 
| 147 104 |  | 
| 148 | 
            -
                     | 
| 105 | 
            +
                    thread = Thread.new do
         | 
| 149 106 | 
             
                      Thread.handle_interrupt(StandardError => :never) do
         | 
| 150 107 | 
             
                        Thread.handle_interrupt(StandardError => :immediate) { listen }
         | 
| 151 108 | 
             
                      rescue NATS::ConnectError => e
         | 
| 152 109 | 
             
                        log("Could not connect to NATS server:", level: :error)
         | 
| 153 110 | 
             
                        log(e.full_message, level: :error, indent: 2)
         | 
| 154 111 | 
             
                        Thread.current.exit
         | 
| 155 | 
            -
                      rescue NewSubscriptionsError =>  | 
| 112 | 
            +
                      rescue NewSubscriptionsError => _e
         | 
| 156 113 | 
             
                        log("New subscriptions! Restarting...", level: :info)
         | 
| 157 114 | 
             
                        restart!
         | 
| 158 | 
            -
                         | 
| 115 | 
            +
                        Thread.current.exit
         | 
| 116 | 
            +
                        # raise e # TODO: there has to be a better way
         | 
| 159 117 | 
             
                      rescue StandardError => e
         | 
| 160 118 | 
             
                        log("Encountered an error:", level: :error)
         | 
| 161 119 | 
             
                        log(e.full_message, level: :error, indent: 2)
         | 
| 162 120 | 
             
                        restart!
         | 
| 163 | 
            -
                         | 
| 121 | 
            +
                        Thread.current.exit
         | 
| 122 | 
            +
                        # raise e
         | 
| 164 123 | 
             
                      end
         | 
| 165 124 | 
             
                    end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    threads << thread
         | 
| 166 127 | 
             
                  end
         | 
| 167 128 |  | 
| 168 | 
            -
                   | 
| 129 | 
            +
                  # **USE WITH CAUTION:** This method (+::reset!+) clears all subscriptions,
         | 
| 130 | 
            +
                  # stops listening (if started), and kills any active threads.
         | 
| 131 | 
            +
                  def reset!
         | 
| 132 | 
            +
                    replies.clear
         | 
| 133 | 
            +
                    stop!
         | 
| 134 | 
            +
                    kill!
         | 
| 135 | 
            +
                  end
         | 
| 169 136 |  | 
| 170 | 
            -
                   | 
| 137 | 
            +
                  private
         | 
| 171 138 |  | 
| 172 | 
            -
                  def  | 
| 173 | 
            -
                     | 
| 139 | 
            +
                  def threads
         | 
| 140 | 
            +
                    @threads ||= []
         | 
| 141 | 
            +
                  end
         | 
| 174 142 |  | 
| 175 | 
            -
             | 
| 176 | 
            -
                     | 
| 177 | 
            -
             | 
| 143 | 
            +
                  def current_thread
         | 
| 144 | 
            +
                    threads.last
         | 
| 145 | 
            +
                  end
         | 
| 178 146 |  | 
| 179 | 
            -
             | 
| 180 | 
            -
             | 
| 181 | 
            -
                    end
         | 
| 147 | 
            +
                  def log(text, level: :info, indent: 0)
         | 
| 148 | 
            +
                    Utils.log(Config.logger, text, level: level, indent: indent)
         | 
| 182 149 | 
             
                  end
         | 
| 183 150 |  | 
| 184 151 | 
             
                  def kill!
         | 
| 185 | 
            -
                     | 
| 152 | 
            +
                    threads.each { |thread| thread.kill if thread.alive? }
         | 
| 186 153 | 
             
                  end
         | 
| 187 154 |  | 
| 188 155 | 
             
                  def stop!
         | 
| @@ -200,6 +167,7 @@ module Natsy | |
| 200 167 | 
             
                  def restart!
         | 
| 201 168 | 
             
                    log("Restarting NATS", level: :warn)
         | 
| 202 169 | 
             
                    stop!
         | 
| 170 | 
            +
                    kill!
         | 
| 203 171 | 
             
                    start!
         | 
| 204 172 | 
             
                  end
         | 
| 205 173 |  | 
| @@ -228,7 +196,7 @@ module Natsy | |
| 228 196 | 
             
                    reply = {
         | 
| 229 197 | 
             
                      subject: subject,
         | 
| 230 198 | 
             
                      handler: handler,
         | 
| 231 | 
            -
                      queue: Utils.presence(queue) || default_queue,
         | 
| 199 | 
            +
                      queue: Utils.presence(queue) || Config.default_queue,
         | 
| 232 200 | 
             
                    }
         | 
| 233 201 |  | 
| 234 202 | 
             
                    replies << reply
         | 
| @@ -237,30 +205,43 @@ module Natsy | |
| 237 205 | 
             
                  end
         | 
| 238 206 |  | 
| 239 207 | 
             
                  def listen
         | 
| 240 | 
            -
                    NATS.start do
         | 
| 208 | 
            +
                    NATS.start(servers: Natsy::Config.urls) do
         | 
| 241 209 | 
             
                      replies.each do |replier|
         | 
| 242 210 | 
             
                        queue_desc = " in queue '#{replier[:queue]}'" if replier[:queue]
         | 
| 243 211 | 
             
                        log("Subscribing to subject '#{replier[:subject]}'#{queue_desc}", level: :debug)
         | 
| 244 212 |  | 
| 245 | 
            -
                        NATS.subscribe(replier[:subject], queue: replier[:queue]) do |message,  | 
| 246 | 
            -
                          parsed_message =  | 
| 247 | 
            -
             | 
| 213 | 
            +
                        NATS.subscribe(replier[:subject], queue: replier[:queue]) do |message, reply_subject, subject|
         | 
| 214 | 
            +
                          parsed_message = begin
         | 
| 215 | 
            +
                            JSON.parse(message)
         | 
| 216 | 
            +
                          rescue StandardError
         | 
| 217 | 
            +
                            message
         | 
| 218 | 
            +
                          end
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                          id, data, pattern = if parsed_message.is_a?(Hash)
         | 
| 221 | 
            +
                            parsed_message.values_at("id", "data", "pattern")
         | 
| 222 | 
            +
                          else
         | 
| 223 | 
            +
                            [nil, parsed_message, nil]
         | 
| 224 | 
            +
                          end
         | 
| 225 | 
            +
             | 
| 226 | 
            +
                          message_data = id && data && pattern ? data : parsed_message
         | 
| 248 227 |  | 
| 249 228 | 
             
                          log("Received a message!")
         | 
| 250 229 | 
             
                          message_desc = <<~LOG_MESSAGE
         | 
| 251 230 | 
             
                            id:      #{id || '(none)'}
         | 
| 252 231 | 
             
                            pattern: #{pattern || '(none)'}
         | 
| 253 232 | 
             
                            subject: #{subject || '(none)'}
         | 
| 254 | 
            -
                            data:    #{ | 
| 255 | 
            -
                            inbox:   #{ | 
| 233 | 
            +
                            data:    #{message_data.to_json}
         | 
| 234 | 
            +
                            inbox:   #{reply_subject || '(none)'}
         | 
| 235 | 
            +
                            queue:   #{replier[:queue] || '(none)'}
         | 
| 236 | 
            +
                            message: #{message}
         | 
| 256 237 | 
             
                          LOG_MESSAGE
         | 
| 257 238 | 
             
                          log(message_desc, indent: 2)
         | 
| 258 239 |  | 
| 259 | 
            -
                           | 
| 240 | 
            +
                          raw_response = replier[:handler].call(message_data, subject)
         | 
| 260 241 |  | 
| 261 | 
            -
                          log("Responding with '#{ | 
| 242 | 
            +
                          log("Responding with '#{raw_response}'")
         | 
| 262 243 |  | 
| 263 | 
            -
                          NATS.publish( | 
| 244 | 
            +
                          NATS.publish(reply_subject, raw_response.to_json) if Utils.present?(reply_subject)
         | 
| 264 245 | 
             
                        end
         | 
| 265 246 | 
             
                      end
         | 
| 266 247 | 
             
                    end
         | 
    
        data/lib/natsy/config.rb
    ADDED
    
    | @@ -0,0 +1,255 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require "ostruct"
         | 
| 4 | 
            +
            require_relative "./utils"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            module Natsy
         | 
| 7 | 
            +
              # Represents the configuration options for +Natsy+. Configuration options are
         | 
| 8 | 
            +
              # set using the `Natsy::Config::set` method, either as arguments or by using
         | 
| 9 | 
            +
              # the appropriate setters on the object passed to the block.
         | 
| 10 | 
            +
              class Config
         | 
| 11 | 
            +
                # A +Natsy::Config::Options+ object is passed as a single argument to the
         | 
| 12 | 
            +
                # block (if provided) for the +Natsy::Config::set+ method. This class should
         | 
| 13 | 
            +
                # probably *NOT* be instantiated directly; instead, set the relevant options
         | 
| 14 | 
            +
                # using +Natsy::Config.set(some_option: "...", some_other_option: "...")+.
         | 
| 15 | 
            +
                # If you find yourself instantiating this class directly, there's probably a
         | 
| 16 | 
            +
                # better way to do what you're trying to do.
         | 
| 17 | 
            +
                class Options
         | 
| 18 | 
            +
                  # Specify a NATS server URL (or multiple URLs)
         | 
| 19 | 
            +
                  #
         | 
| 20 | 
            +
                  # **NOTE:** The following two examples do exactly the same thing.
         | 
| 21 | 
            +
                  #
         | 
| 22 | 
            +
                  # @example
         | 
| 23 | 
            +
                  #   Natsy::Config.set(url: "nats://foo.bar:4567"))
         | 
| 24 | 
            +
                  #
         | 
| 25 | 
            +
                  # @example
         | 
| 26 | 
            +
                  #   Natsy::Config.set do |options|
         | 
| 27 | 
            +
                  #     options.url = "nats://foo.bar:4567"
         | 
| 28 | 
            +
                  #   end
         | 
| 29 | 
            +
                  #
         | 
| 30 | 
            +
                  # **NOTE:** The following two examples do exactly the same thing.
         | 
| 31 | 
            +
                  #
         | 
| 32 | 
            +
                  # @example
         | 
| 33 | 
            +
                  #   Natsy::Config.set(urls: ["nats://foo.bar:4567", "nats://foo.bar:5678"])
         | 
| 34 | 
            +
                  #
         | 
| 35 | 
            +
                  # @example
         | 
| 36 | 
            +
                  #   Natsy::Config.set do |options|
         | 
| 37 | 
            +
                  #     options.urls = ["nats://foo.bar:4567", "nats://foo.bar:5678"]
         | 
| 38 | 
            +
                  #   end
         | 
| 39 | 
            +
                  #
         | 
| 40 | 
            +
                  # If left blank/omitted, +natsy+ will fall back on the default URL, which
         | 
| 41 | 
            +
                  # is +nats://localhost:4222+.
         | 
| 42 | 
            +
                  #
         | 
| 43 | 
            +
                  attr_accessor :url, :urls
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  # Attach a logger to have +natsy+ write out logs for messages
         | 
| 46 | 
            +
                  # received, responses sent, errors raised, lifecycle events, etc.
         | 
| 47 | 
            +
                  #
         | 
| 48 | 
            +
                  # **NOTE:** The following two examples do exactly the same thing.
         | 
| 49 | 
            +
                  #
         | 
| 50 | 
            +
                  # @example
         | 
| 51 | 
            +
                  #   require 'natsy'
         | 
| 52 | 
            +
                  #   require 'logger'
         | 
| 53 | 
            +
                  #
         | 
| 54 | 
            +
                  #   nats_logger = Logger.new(STDOUT)
         | 
| 55 | 
            +
                  #   nats_logger.level = Logger::INFO
         | 
| 56 | 
            +
                  #
         | 
| 57 | 
            +
                  #   Natsy::Config.set(logger: nats_logger)
         | 
| 58 | 
            +
                  #
         | 
| 59 | 
            +
                  # @example
         | 
| 60 | 
            +
                  #   require 'natsy'
         | 
| 61 | 
            +
                  #   require 'logger'
         | 
| 62 | 
            +
                  #
         | 
| 63 | 
            +
                  #   Natsy::Config.set do |options|
         | 
| 64 | 
            +
                  #     nats_logger = Logger.new(STDOUT)
         | 
| 65 | 
            +
                  #     nats_logger.level = Logger::INFO
         | 
| 66 | 
            +
                  #
         | 
| 67 | 
            +
                  #     options.logger = nats_logger
         | 
| 68 | 
            +
                  #   end
         | 
| 69 | 
            +
                  #
         | 
| 70 | 
            +
                  #
         | 
| 71 | 
            +
                  # In a Rails application, you might do this instead:
         | 
| 72 | 
            +
                  #
         | 
| 73 | 
            +
                  # @example
         | 
| 74 | 
            +
                  #   Natsy::Config.set(logger: Rails.logger)
         | 
| 75 | 
            +
                  #
         | 
| 76 | 
            +
                  attr_reader :logger
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                  # {include:Natsy::Config::Options#logger}
         | 
| 79 | 
            +
                  def logger=(new_logger)
         | 
| 80 | 
            +
                    @logger = new_logger
         | 
| 81 | 
            +
                    Utils.log(@logger, "Set the logger to #{@logger.inspect}", level: :debug)
         | 
| 82 | 
            +
                  end
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                  # Set a default queue for subscriptions.
         | 
| 85 | 
            +
                  #
         | 
| 86 | 
            +
                  # **NOTE:** The following two examples do exactly the same thing.
         | 
| 87 | 
            +
                  #
         | 
| 88 | 
            +
                  # @example
         | 
| 89 | 
            +
                  #   Natsy::Config.set(default_queue: "foobar")
         | 
| 90 | 
            +
                  #
         | 
| 91 | 
            +
                  # @example
         | 
| 92 | 
            +
                  #   Natsy::Config.set do |options|
         | 
| 93 | 
            +
                  #     options.default_queue = "foobar"
         | 
| 94 | 
            +
                  #   end
         | 
| 95 | 
            +
                  #
         | 
| 96 | 
            +
                  # Leave the +::default_queue+ blank (or assign +nil+) to use no default
         | 
| 97 | 
            +
                  # queue.
         | 
| 98 | 
            +
                  #
         | 
| 99 | 
            +
                  # **NOTE:** The following two examples do exactly the same thing.
         | 
| 100 | 
            +
                  #
         | 
| 101 | 
            +
                  # @example
         | 
| 102 | 
            +
                  #   Natsy::Config.set(default_queue: nil)
         | 
| 103 | 
            +
                  #
         | 
| 104 | 
            +
                  # @example
         | 
| 105 | 
            +
                  #   Natsy::Config.set do |options|
         | 
| 106 | 
            +
                  #     options.default_queue = nil
         | 
| 107 | 
            +
                  #   end
         | 
| 108 | 
            +
                  #
         | 
| 109 | 
            +
                  attr_reader :default_queue
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                  # {include:Natsy::Config::Options#default_queue}
         | 
| 112 | 
            +
                  def default_queue=(new_queue)
         | 
| 113 | 
            +
                    @default_queue = Utils.presence(new_queue.to_s)
         | 
| 114 | 
            +
                    Utils.log(logger, "Setting the default queue to #{@default_queue || '(none)'}", level: :debug)
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  # Returns ONLY the config options THAT HAVE BEEN SET as a +Hash+. Will not
         | 
| 118 | 
            +
                  # have keys for properties that are unassigned, but will have keys for
         | 
| 119 | 
            +
                  # properties assigned +nil+.
         | 
| 120 | 
            +
                  def to_h
         | 
| 121 | 
            +
                    hash = {}
         | 
| 122 | 
            +
                    hash[:url] = url if defined?(@url)
         | 
| 123 | 
            +
                    hash[:urls] = urls if defined?(@urls)
         | 
| 124 | 
            +
                    hash[:logger] = logger if defined?(@logger)
         | 
| 125 | 
            +
                    hash[:default_queue] = default_queue if defined?(@default_queue)
         | 
| 126 | 
            +
                    hash
         | 
| 127 | 
            +
                  end
         | 
| 128 | 
            +
                end
         | 
| 129 | 
            +
             | 
| 130 | 
            +
                # Valid option keys that can be given to +Natsy::Config::set+, either in a
         | 
| 131 | 
            +
                # +Hash+ passed to the method, keyword arguments passed to the method, or by
         | 
| 132 | 
            +
                # using setters on the +Natsy::Config::Options+ object passed to the block.
         | 
| 133 | 
            +
                VALID_OPTIONS = %i[
         | 
| 134 | 
            +
                  url
         | 
| 135 | 
            +
                  urls
         | 
| 136 | 
            +
                  logger
         | 
| 137 | 
            +
                  default_queue
         | 
| 138 | 
            +
                ].freeze
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                # The default NATS server URL (used if none is configured)
         | 
| 141 | 
            +
                DEFAULT_URL = "nats://localhost:4222"
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                class << self
         | 
| 144 | 
            +
                  # Specify configuration options, either by providing them as keyword
         | 
| 145 | 
            +
                  # arguments or by using a block. Should you choose to set options using
         | 
| 146 | 
            +
                  # a block, it will be passed a single argument (an instance of
         | 
| 147 | 
            +
                  # +Natsy::Config::Options+). You can set any options on the instance that
         | 
| 148 | 
            +
                  # you see fit.
         | 
| 149 | 
            +
                  #
         | 
| 150 | 
            +
                  # **NOTE:** The following two examples do exactly the same thing.
         | 
| 151 | 
            +
                  #
         | 
| 152 | 
            +
                  # @example
         | 
| 153 | 
            +
                  #   Natsy::Config.set(
         | 
| 154 | 
            +
                  #     urls: ["nats://foo.bar:4567", "nats://foo.bar:5678"],
         | 
| 155 | 
            +
                  #     default_queue: "foobar",
         | 
| 156 | 
            +
                  #     logger: Rails.logger,
         | 
| 157 | 
            +
                  #   )
         | 
| 158 | 
            +
                  #
         | 
| 159 | 
            +
                  # @example
         | 
| 160 | 
            +
                  #   Natsy::Config.set do |options|
         | 
| 161 | 
            +
                  #     options.urls = ["nats://foo.bar:4567", "nats://foo.bar:5678"]
         | 
| 162 | 
            +
                  #     options.default_queue = "foobar"
         | 
| 163 | 
            +
                  #     options.logger = Rails.logger
         | 
| 164 | 
            +
                  #   end
         | 
| 165 | 
            +
                  #
         | 
| 166 | 
            +
                  def set(keyword_options = {})
         | 
| 167 | 
            +
                    new_hash_options = (keyword_options || {}).transform_keys(&:to_sym)
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                    invalid_config = lambda do |detail, keys|
         | 
| 170 | 
            +
                      raise InvalidConfigError, "Invalid options provided #{detail}: #{keys.join(', ')}"
         | 
| 171 | 
            +
                    end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                    invalid_keys = invalid_option_keys(new_hash_options)
         | 
| 174 | 
            +
                    invalid_config.call("as arguments", invalid_keys) if invalid_keys.any?
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                    # Want to take advantage of the setters on +Natsy::Config::Options+...
         | 
| 177 | 
            +
                    new_hash_options_object = new_hash_options.each_with_object(Options.new) do |(key, value), options|
         | 
| 178 | 
            +
                      options.send(:"#{key}=", value)
         | 
| 179 | 
            +
                    end
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                    given_options.merge!(new_hash_options_object.to_h)
         | 
| 182 | 
            +
             | 
| 183 | 
            +
                    new_block_options_object = Options.new
         | 
| 184 | 
            +
                    yield(new_block_options_object) if block_given?
         | 
| 185 | 
            +
             | 
| 186 | 
            +
                    invalid_keys = invalid_option_keys(new_block_options_object)
         | 
| 187 | 
            +
                    invalid_config.call("in block", invalid_keys) if invalid_keys.any?
         | 
| 188 | 
            +
             | 
| 189 | 
            +
                    given_options.merge!(new_block_options_object.to_h)
         | 
| 190 | 
            +
                  end
         | 
| 191 | 
            +
             | 
| 192 | 
            +
                  # The NATS server URLs that +natsy+ should listen on.
         | 
| 193 | 
            +
                  #
         | 
| 194 | 
            +
                  # See also: {Natsy::Config::Options#urls=}
         | 
| 195 | 
            +
                  #
         | 
| 196 | 
            +
                  def urls
         | 
| 197 | 
            +
                    given_url_list = [given_options[:url]].flatten
         | 
| 198 | 
            +
                    given_urls_list = [given_options[:urls]].flatten
         | 
| 199 | 
            +
                    all_given_urls = [*given_url_list, *given_urls_list].compact.uniq
         | 
| 200 | 
            +
                    Utils.presence(all_given_urls) || [DEFAULT_URL]
         | 
| 201 | 
            +
                  end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                  # The logger that +natsy+ should use to write out logs for messages
         | 
| 204 | 
            +
                  # received, responses sent, errors raised, lifecycle events, etc.
         | 
| 205 | 
            +
                  #
         | 
| 206 | 
            +
                  # See also: {Natsy::Config::Options#logger=}
         | 
| 207 | 
            +
                  #
         | 
| 208 | 
            +
                  def logger
         | 
| 209 | 
            +
                    Utils.presence(given_options[:logger])
         | 
| 210 | 
            +
                  end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                  # The default queue that +natsy+ should use for subscriptions.
         | 
| 213 | 
            +
                  #
         | 
| 214 | 
            +
                  # See also: {Natsy::Config::Options#default_queue=}
         | 
| 215 | 
            +
                  #
         | 
| 216 | 
            +
                  def default_queue
         | 
| 217 | 
            +
                    Utils.presence(given_options[:default_queue])
         | 
| 218 | 
            +
                  end
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                  # Returns all config options as a +Hash+.
         | 
| 221 | 
            +
                  def to_h
         | 
| 222 | 
            +
                    {
         | 
| 223 | 
            +
                      urls: urls,
         | 
| 224 | 
            +
                      logger: logger,
         | 
| 225 | 
            +
                      default_queue: default_queue,
         | 
| 226 | 
            +
                    }
         | 
| 227 | 
            +
                  end
         | 
| 228 | 
            +
             | 
| 229 | 
            +
                  # Alias for {Natsy::Config::to_h}.
         | 
| 230 | 
            +
                  def as_json(*_args)
         | 
| 231 | 
            +
                    to_h
         | 
| 232 | 
            +
                  end
         | 
| 233 | 
            +
             | 
| 234 | 
            +
                  # Serialize the configuration into a JSON object string.
         | 
| 235 | 
            +
                  def to_json(*_args)
         | 
| 236 | 
            +
                    to_h.to_json
         | 
| 237 | 
            +
                  end
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                  # Reset the configuration to default values.
         | 
| 240 | 
            +
                  def reset!
         | 
| 241 | 
            +
                    @given_options = nil
         | 
| 242 | 
            +
                  end
         | 
| 243 | 
            +
             | 
| 244 | 
            +
                  private
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                  def given_options
         | 
| 247 | 
            +
                    @given_options ||= {}
         | 
| 248 | 
            +
                  end
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                  def invalid_option_keys(options)
         | 
| 251 | 
            +
                    options.to_h.keys - VALID_OPTIONS
         | 
| 252 | 
            +
                  end
         | 
| 253 | 
            +
                end
         | 
| 254 | 
            +
              end
         | 
| 255 | 
            +
            end
         | 
    
        data/lib/natsy/controller.rb
    CHANGED
    
    | @@ -25,18 +25,17 @@ module Natsy | |
| 25 25 | 
             
                  #   end
         | 
| 26 26 | 
             
                  #
         | 
| 27 27 | 
             
                  # If omitted, the controller will fall back on the global default queue
         | 
| 28 | 
            -
                  # assigned with +Natsy:: | 
| 29 | 
            -
                  #  | 
| 30 | 
            -
                  #  | 
| 31 | 
            -
                  #  | 
| 32 | 
            -
                  # blank for that controller.
         | 
| 28 | 
            +
                  # assigned with +Natsy::Config::set+. If no default queue is set in either
         | 
| 29 | 
            +
                  # the controller or globally, then the default queue will be blank. Set
         | 
| 30 | 
            +
                  # the default queue to +nil+ in a controller to fall back to the global
         | 
| 31 | 
            +
                  # default queue.
         | 
| 33 32 | 
             
                  #
         | 
| 34 33 | 
             
                  def default_queue(some_queue = NO_QUEUE_GIVEN)
         | 
| 35 34 | 
             
                    # +NO_QUEUE_GIVEN+ is a special symbol (rather than +nil+) so that the
         | 
| 36 35 | 
             
                    # default queue can be "unset" to +nil+ (given a non-+nil+ global
         | 
| 37 | 
            -
                    # default set with +Natsy::Client:: | 
| 36 | 
            +
                    # default set with +Natsy::Client::set+).
         | 
| 38 37 | 
             
                    if some_queue == NO_QUEUE_GIVEN
         | 
| 39 | 
            -
                      @default_queue ||  | 
| 38 | 
            +
                      @default_queue || Config.default_queue
         | 
| 40 39 | 
             
                    else
         | 
| 41 40 | 
             
                      @default_queue = Utils.presence(some_queue.to_s)
         | 
| 42 41 | 
             
                    end
         | 
    
        data/lib/natsy/utils.rb
    CHANGED
    
    | @@ -15,6 +15,20 @@ module Natsy | |
| 15 15 | 
             
                  def presence(value)
         | 
| 16 16 | 
             
                    present?(value) ? value : nil
         | 
| 17 17 | 
             
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def log(logger, text, level: :info, indent: 0)
         | 
| 20 | 
            +
                    return unless logger
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                    timestamp = Time.now.to_s
         | 
| 23 | 
            +
                    text_lines = text.split("\n")
         | 
| 24 | 
            +
                    indentation = indent.is_a?(String) ? indent : (" " * indent)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    text_lines.each do |line|
         | 
| 27 | 
            +
                      logger.send(level, "[#{timestamp}] Natsy | #{indentation}#{line}")
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    nil
         | 
| 31 | 
            +
                  end
         | 
| 18 32 | 
             
                end
         | 
| 19 33 | 
             
              end
         | 
| 20 34 | 
             
            end
         | 
    
        data/lib/natsy/version.rb
    CHANGED
    
    
    
        data/natsy.gemspec
    CHANGED
    
    | @@ -28,6 +28,7 @@ Gem::Specification.new do |spec| | |
| 28 28 | 
             
              spec.require_paths = ["lib"]
         | 
| 29 29 |  | 
| 30 30 | 
             
              spec.add_development_dependency "bundler", "~> 2.2"
         | 
| 31 | 
            +
              spec.add_development_dependency "pry"
         | 
| 31 32 | 
             
              spec.add_development_dependency "rake", "~> 13.0"
         | 
| 32 33 | 
             
              spec.add_development_dependency "rspec", "~> 3.0"
         | 
| 33 34 | 
             
              spec.add_development_dependency "rubocop", "~> 1.10"
         | 
| @@ -35,7 +36,6 @@ Gem::Specification.new do |spec| | |
| 35 36 | 
             
              spec.add_development_dependency "rubocop-rake", "~> 0.5"
         | 
| 36 37 | 
             
              spec.add_development_dependency "rubocop-rspec", "~> 2.2"
         | 
| 37 38 | 
             
              spec.add_development_dependency "solargraph"
         | 
| 38 | 
            -
              spec.add_development_dependency "pry"
         | 
| 39 39 |  | 
| 40 40 | 
             
              spec.add_runtime_dependency "nats", "~> 0.11"
         | 
| 41 41 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: natsy
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.3 | 
| 4 | 
            +
              version: 0.4.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Keegan Leitz
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2021-05- | 
| 11 | 
            +
            date: 2021-05-19 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: bundler
         | 
| @@ -24,6 +24,20 @@ dependencies: | |
| 24 24 | 
             
                - - "~>"
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 26 | 
             
                    version: '2.2'
         | 
| 27 | 
            +
            - !ruby/object:Gem::Dependency
         | 
| 28 | 
            +
              name: pry
         | 
| 29 | 
            +
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 | 
            +
                requirements:
         | 
| 31 | 
            +
                - - ">="
         | 
| 32 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            +
                    version: '0'
         | 
| 34 | 
            +
              type: :development
         | 
| 35 | 
            +
              prerelease: false
         | 
| 36 | 
            +
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 | 
            +
                requirements:
         | 
| 38 | 
            +
                - - ">="
         | 
| 39 | 
            +
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            +
                    version: '0'
         | 
| 27 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 42 | 
             
              name: rake
         | 
| 29 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -122,20 +136,6 @@ dependencies: | |
| 122 136 | 
             
                - - ">="
         | 
| 123 137 | 
             
                  - !ruby/object:Gem::Version
         | 
| 124 138 | 
             
                    version: '0'
         | 
| 125 | 
            -
            - !ruby/object:Gem::Dependency
         | 
| 126 | 
            -
              name: pry
         | 
| 127 | 
            -
              requirement: !ruby/object:Gem::Requirement
         | 
| 128 | 
            -
                requirements:
         | 
| 129 | 
            -
                - - ">="
         | 
| 130 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 131 | 
            -
                    version: '0'
         | 
| 132 | 
            -
              type: :development
         | 
| 133 | 
            -
              prerelease: false
         | 
| 134 | 
            -
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 135 | 
            -
                requirements:
         | 
| 136 | 
            -
                - - ">="
         | 
| 137 | 
            -
                  - !ruby/object:Gem::Version
         | 
| 138 | 
            -
                    version: '0'
         | 
| 139 139 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 140 140 | 
             
              name: nats
         | 
| 141 141 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| @@ -161,7 +161,6 @@ files: | |
| 161 161 | 
             
            - ".gitignore"
         | 
| 162 162 | 
             
            - ".rspec"
         | 
| 163 163 | 
             
            - ".rubocop.yml"
         | 
| 164 | 
            -
            - CHANGELOG.md
         | 
| 165 164 | 
             
            - Gemfile
         | 
| 166 165 | 
             
            - LICENSE.txt
         | 
| 167 166 | 
             
            - README.md
         | 
| @@ -170,6 +169,7 @@ files: | |
| 170 169 | 
             
            - bin/setup
         | 
| 171 170 | 
             
            - lib/natsy.rb
         | 
| 172 171 | 
             
            - lib/natsy/client.rb
         | 
| 172 | 
            +
            - lib/natsy/config.rb
         | 
| 173 173 | 
             
            - lib/natsy/controller.rb
         | 
| 174 174 | 
             
            - lib/natsy/utils.rb
         | 
| 175 175 | 
             
            - lib/natsy/version.rb
         | 
| @@ -178,7 +178,7 @@ homepage: https://github.com/openbay/natsy | |
| 178 178 | 
             
            licenses:
         | 
| 179 179 | 
             
            - MIT
         | 
| 180 180 | 
             
            metadata:
         | 
| 181 | 
            -
              documentation_uri: https://www.rubydoc.info/gems/natsy/0.3 | 
| 181 | 
            +
              documentation_uri: https://www.rubydoc.info/gems/natsy/0.4.3
         | 
| 182 182 | 
             
            post_install_message: 
         | 
| 183 183 | 
             
            rdoc_options: []
         | 
| 184 184 | 
             
            require_paths:
         |