https://github.com/0exp/puma_after_reply
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.
https://github.com/0exp/puma_after_reply
puma-after-reply rack-after-reply
Last synced: 12 months ago
JSON representation
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.
- Host: GitHub
- URL: https://github.com/0exp/puma_after_reply
- Owner: 0exp
- License: mit
- Created: 2024-06-30T12:03:09.000Z (about 2 years ago)
- Default Branch: master
- Last Pushed: 2024-08-03T19:05:38.000Z (almost 2 years ago)
- Last Synced: 2025-07-09T06:04:16.835Z (12 months ago)
- Topics: puma-after-reply, rack-after-reply
- Language: Ruby
- Homepage:
- Size: 61.5 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# puma_after_reply ·  
Puma's `"rack.after_reply"` integration for your Rack-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](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Algorithm](#algorithm)
- [Configuration](#configuration)
- [Adding replies](#adding-replies-add_replycond_reply)
- [Some debugging methods](#some-debugging-methods)
- [Test environments](#test-environments-and-other-rack-apps)
- [Contributing](#contributing)
- [License](#license)
- [Authors](#authors)
---
### Requirements
\[[back to top](#table-of-contents)\]
- `concurrent-ruby` (`~> 1.3`)
---
### Installation
\[[back to top](#table-of-contents)\]
```ruby
gem 'puma_after_reply'
```
```shell
bundle install
# --- or ---
gem install puma_after_reply
```
```ruby
require 'puma_after_reply'
```
---
### Usage
\[[back to top](#table-of-contents)\]
- [Algorithm](#algorithm)
- [Configuration](#configuration)
- [Adding replies](#adding-replies-add_replycond_reply)
- [Some debugging methods](#some-debugging-methods)
- [Test environments](#test-environments-and-other-rack-apps)
---
#### 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](#adding-replies-add_replycond_reply));
- using `PumaAfterReply.cond_reply` ([doc](#adding-replies-add_replycond_reply));
- 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](#usage)\]
```ruby
PumaAfterReply.configure do |config|
# default values:
config.fail_on_error = false # expects:
config.log_error = nil # expects: (receives: error object)
config.on_error = nil # expects: (receives: error object)
config.before_reply = nil # expects: (receives: nothing)
config.after_reply = nil # expects: (receives: nothing)
config.run_anyway = false # expects:
config.thread_pool_size = 10 # expects:
end
# get configs as a hash:
PumaAfterReply.cofnig.to_h
# get configs directly:
PumaAfterRepy.config.fail_on_error # and etc;
```
```ruby
# (IMPORTANT): register the middleware (Rails example)
Rails.configuration.middleware.use(PumaAfterReply::Middleware)
```
---
#### Adding replies (`add_reply`/`cond_reply`)
\[[back to top](#usage)\]
- non-threaded way (this reply will be processed sequentially):
```ruby
# non-threaded way:
PumaAfterReply.add_reply { your_code }
```
- threaded-way (this reply will be processed in a separated thread):
```ruby
# 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`);
```ruby
# with a boolean value:
PumaAfterReply.cond_reply(!Rails.env.test?) { your_code }
```
```ruby
# with a callabale value:
is_puma_request = proc { check_that_we_are_inside_a_request }
PumaAfterReply.cond_reply(is_puma_request) { your_code }
```
```ruby
# add threaded reply:
PumaAfterReply.cond_reply(some_condition, threaded: true) { your_code }
```
---
#### Some debugging methods
\[[back to top](#usage)\]
```ruby
# the count of the added replies:
PumaAfterReply.count # or .size
```
```ruby
# replies collections:
PumaAfterReply.replies # all added replies
PumaAfterReply.inline_replies # all added non-threaded replies
PumaAfterReply.threaded_replies # all added threaded replies
```
```ruby
# manual replies running:
PumaAfterReply.call # or .run
```
```ruby
# clear replies collector:
PumaAfterReply.clear
```
```ruby
# reset configs to default values:
PumaAfterReply.config.__reset!
```
---
#### Test environments (and other Rack apps)
\[[back to top](#usage)\]
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](#table-of-contents)\]
- 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](#table-of-contents)\]
Released under MIT License.
## Authors
\[[back to top](#table-of-contents)\]
[Rustam Ibragimov](https://github.com/0exp)