Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Open more actions menu

Repository files navigation

puma_after_reply · Gem Version build

Puma's "rack.after_reply" integration for your Rack- and Rails-applications. Provides #call-able reply abstraction and configurable non-threaded/threaded invocation flow with before/on_error/after hooks for each added reply.


Table of Contents


Requirements

[back to top]

  • concurrent-ruby (~> 1.3)

Installation

[back to top]

gem 'puma_after_reply'
bundle install
# --- or ---
gem install puma_after_reply
require 'puma_after_reply'

Usage

[back to top]


Algorithm

  • every Puma's worker gets own reply collector;
  • during the Puma's request your logic adds replies to the worker's reply collector:
    • using PumaAfterReply.add_reply (doc);
    • using PumaAfterReply.cond_reply (doc);
  • after processing the request, Puma's worker returns a response to the browser;
  • then Puma's worker launches accumulated replies:
    • threaded replies are launched in separated threads;
    • non-threaded replies are launched sequentially;
  • after processing all replies, the worker's reply collector is cleared;

Each separated reply is launched according to the following invocation flow:

  • before_reply hook (config.before_reply);
  • reply invocation (reply.call);
  • if reply.call failed with an error:
    • log_error hook (config.log_error);
    • on_error hook (config.on_error);
    • raise_on_error fail check (config.fail_on_error)
  • (ensure): after_reply hook (config.after_reply);

Remember: if you add a reply outside of the Puma's/Rack's request context your reply will never be processed and flushed (that can lead to the memory leak/memory bloat).


Configuration

[back to top]

PumaAfterReply.configure do |config|
  # default values:
  config.fail_on_error = false # expects: <Boolean>
  config.log_error = nil # expects: <nil,#call,Proc> (receives: error object)
  config.on_error = nil # expects: <nil,#call,Proc> (receives: error object)
  config.before_reply = nil # expects: <nil,#call,Proc> (receives: nothing)
  config.after_reply = nil # expects: <nil,#call,Proc> (receives: nothing)
  config.run_anyway = false # expects: <Boolean>
  config.thread_pool_size = 10 # expects: <Integer>
end

# get configs as a hash:
PumaAfterReply.cofnig.to_h

# get configs directly:
PumaAfterRepy.config.fail_on_error # and etc;
# (IMPORTANT): register the middleware (Rails example)
Rails.configuration.middleware.use(PumaAfterReply::Middleware)

Adding replies (add_reply/cond_reply)

[back to top]

  • non-threaded way (this reply will be processed sequentially):
# non-threaded way:
PumaAfterReply.add_reply { your_code }
  • threaded-way (this reply will be processed in a separated thread):
# threaded way:
PumaAfterReply.add_reply(threaded: true) { your_code }
  • conditional reply adding:
    • reply(condition, threaded: false, &reply) (threaded: false by default);
    • when condition is true - your reply will be pushed to the reply queue;
    • when condition is false - your reply will be processed immediately;
    • condition can be represented as callable object (#call/Proc);
# with a boolean value:
PumaAfterReply.cond_reply(!Rails.env.test?) { your_code }
# with a callabale value:
is_puma_request = proc { check_that_we_are_inside_a_request }
PumaAfterReply.cond_reply(is_puma_request) { your_code }
# add threaded reply:
PumaAfterReply.cond_reply(some_condition, threaded: true) { your_code }

Some debugging methods

[back to top]

# the count of the added replies:
PumaAfterReply.count # or .size
# replies collections:
PumaAfterReply.replies # all added replies
PumaAfterReply.inline_replies # all added non-threaded replies
PumaAfterReply.threaded_replies # all added threaded replies
# manual replies running:
PumaAfterReply.call # or .run
# clear replies collector:
PumaAfterReply.clear
# reset configs to default values:
PumaAfterReply.config.__reset!

Test environments (and other Rack apps)

[back to top]

In some cases and Rack applications you can have no "rack.after_reply" key in your Rack env (request environments in your tests, for example). For this cases you can use config.run_anyway = true: on each of your rack request all accumulated replies will be processed and cleared in the same way as for Puma.


Contributing

[back to top]

  • Fork it ( https://github.com/0exp/puma_after_reply )
  • Create your feature branch (git checkout -b feature/my-new-feature)
  • Commit your changes (git commit -am '[feature_context] Add some feature')
  • Push to the branch (git push origin feature/my-new-feature)
  • Create new Pull Request

License

[back to top]

Released under MIT License.

Authors

[back to top]

Rustam Ibragimov

About

Puma's "rack.after_reply" integration for your Rack-applications. Provides #call-able reply abstraction and configurable invocation flow with before/on_error/after hooks for each added reply.

Topics

Resources

Code of conduct

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages

Morty Proxy This is a proxified and sanitized view of the page, visit original site.