Skip to content

Conversation

byroot
Copy link
Contributor

@byroot byroot commented Jul 31, 2025

It is very similar to rack.after_reply, but is part of the Rack spec.

It can't just be an alias because the spec state it has to invoke callbacks in reverse order.

Fix: #3631 (The PR seems stalled?)
Ref: rack/rack#1777
Ref: rack/rack#1802

@github-actions github-actions bot added the waiting-for-review Waiting on review from anyone label Jul 31, 2025
@MSP-Greg
Copy link
Member

@byroot

Thanks for these PR's.

Question, which I've wondered about, but never tested:

Given obj, which of the following is better:

# assume env["rack.response_finished"] is allowed to be nil
if temp = env["rack.response_finished"]
  temp.each { # some op }
end

-- or --

temp = env["rack.response_finished"] || []
temp.each { # some op }

Obviously, we probably shouldn't create extra arrays, or create one for every request, so the code above wouldn't be exactly the same if added to Puma...

@byroot
Copy link
Contributor Author

byroot commented Jul 31, 2025

Given obj, which of the following is better:

The first version saves an allocation, and saves a method call if the value is nil. That the only difference.

But since the key is pretty much guaranteed to be there (unless the application delete the key for some reason), it really doesn't make any substantial difference in reality.

@MSP-Greg
Copy link
Member

Sorry. Posted before I consumed enough coffee. Kind of rooted in a frustration for a method similar to not_empty? which would be true if an object could be enumerated with at least one loop, with the assumption that nil cannot.

I may do a future PR adding these keys to Binder's @proto_env with a nil value, and also add a constant RACK_RESPONSE_FINISHED...

Thanks.

@schneems
Copy link
Contributor

I merged in your other PR this one now has a conflict. I'm trying to get the keepalive fix out the door, to do that I'm trying to cut a release 6.6.1 and then have main target v7. As this is an addition, it would need to either be 6.7 (would need a new codename) or go out in 7.x.

@byroot
Copy link
Contributor Author

byroot commented Jul 31, 2025

also add a constant RACK_RESPONSE_FINISHED...

Right, I wasn't sure if all keys needed a constant or not. I can easily add it.

@byroot byroot force-pushed the rack-response-finished branch from b283739 to ba88f0a Compare July 31, 2025 14:39
@byroot
Copy link
Contributor Author

byroot commented Jul 31, 2025

Rebased.

@github-actions github-actions bot added waiting-for-merge and removed waiting-for-review Waiting on review from anyone labels Jul 31, 2025
@@ -92,6 +92,7 @@ def handle_request(client, requests)
# array, we will invoke them when the request is done.
#
env[RACK_AFTER_REPLY] ||= []
env[RACK_RESPONSE_FINISHED] ||= []

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
env[RACK_RESPONSE_FINISHED] ||= []
response_finished = []
env[RACK_RESPONSE_FINISHED] = response_finished

Do we actually need ||= here?

Comment on lines 149 to 157
if response_finished = env[RACK_RESPONSE_FINISHED]
response_finished.reverse_each do |o|
begin
o.call
rescue StandardError => e
@log_writer.debug_error e
end
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if response_finished = env[RACK_RESPONSE_FINISHED]
response_finished.reverse_each do |o|
begin
o.call
rescue StandardError => e
@log_writer.debug_error e
end
end
end
response_finished.reverse_each do |o|
begin
o.call
rescue StandardError => e
@log_writer.debug_error e
end
end

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@samuel-williams-shopify

Thanks.

Re the actual call, should it be something similar to:

o.call(env, status, headers, e)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's correct. This is now strictly clarified in the rack-head spec, so if you run against Rack::Lint in Rack::Head and have some tests for this, it will validate the callback.

@github-actions github-actions bot added waiting-for-review Waiting on review from anyone and removed waiting-for-merge labels Aug 5, 2025
It is very similar to `rack.after_reply`, but is part of the Rack spec.

It can't just be an alias because the spec state it has to
invoke callbacks in reverse order.

Fix: puma#3631
Ref: rack/rack#1777
Ref: rack/rack#1802

Co-Authored-By: Robert Laurin <robert.laurin@shopify.com>
@byroot byroot force-pushed the rack-response-finished branch from ba88f0a to a745614 Compare August 6, 2025 16:45
@byroot
Copy link
Contributor Author

byroot commented Aug 6, 2025

I updated the PR to pass env, status, headers and error.

@MSP-Greg
Copy link
Member

MSP-Greg commented Aug 7, 2025

@byroot

Sorry for jumping in, I noticed the CI crash & burn, assumed it was related to the e to error rename.

I'm fine with the conditional, better 'sleep factor'...

@schneems?

@MSP-Greg MSP-Greg merged commit 1b08ed7 into puma:master Aug 15, 2025
100 of 101 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature waiting-for-review Waiting on review from anyone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants