-
Notifications
You must be signed in to change notification settings - Fork 290
Scope the shoryuken context to the current fiber. #765
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,6 +3,10 @@ | |||||||||||||||||||||||||||||||||
| require 'time' | ||||||||||||||||||||||||||||||||||
| require 'logger' | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| class Fiber | ||||||||||||||||||||||||||||||||||
| attr_accessor :shoryuken_context | ||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| module Shoryuken | ||||||||||||||||||||||||||||||||||
| module Logging | ||||||||||||||||||||||||||||||||||
| class Base < ::Logger::Formatter | ||||||||||||||||||||||||||||||||||
|
|
@@ -11,8 +15,7 @@ def tid | |||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| def context | ||||||||||||||||||||||||||||||||||
| c = Thread.current[:shoryuken_context] | ||||||||||||||||||||||||||||||||||
| c ? " #{c}" : '' | ||||||||||||||||||||||||||||||||||
| Fiber.current.shoryuken_context&.then{|context| " #{context}"} | ||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+18
to
19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainBehavior change: thread-local to fiber-local is likely breaking in fiber-heavy apps Previously, context was thread-local, so all fibers in the same thread shared it. After this change, context is fiber-local and won’t automatically propagate to new fibers, which may surprise users (e.g., Async/Fiber scheduler, fan-out patterns). The PR mentions this, but the code currently provides no migration path or configuration.
Option A: Provide a configurable strategy (default: :thread, opt-in :fiber): # e.g., Shoryuken::Logging.context_scope = :thread or :fiber
def self.current_context_get
case Shoryuken::Logging.context_scope
when :fiber
Fiber.current.instance_variable_get(:@shoryuken_context)
else
Thread.current[:shoryuken_context]
end
end
def self.current_context_set(value)
case Shoryuken::Logging.context_scope
when :fiber
Fiber.current.instance_variable_set(:@shoryuken_context, value)
else
Thread.current[:shoryuken_context] = value
end
endOption B (Ruby 3.1+): Use Fiber-local storage (Fiber.current[:shoryuken_context]) for clarity and potential inheritance if you implement it, gated by Ruby version check; fallback to thread-local otherwise. To assess blast radius, search for any code relying on thread-local context: Also applies to: 36-39 🏁 Script executed: #!/bin/bash
# Find any remaining uses of the old thread-local context or behavior assumptions.
rg -n "Thread\.current\[:shoryuken_context\]|\bwith_context\b"Length of output: 419 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== lib/shoryuken/logging.rb ==="
nl -ba lib/shoryuken/logging.rb | sed -n '1,240p'
echo
echo "=== lib/shoryuken/processor.rb ==="
nl -ba lib/shoryuken/processor.rb | sed -n '1,240p'
echo
echo "=== spec/shoryuken/processor_spec.rb ==="
nl -ba spec/shoryuken/processor_spec.rb | sed -n '1,240p'Length of output: 237 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "=== lib/shoryuken/logging.rb ==="
if [ -f lib/shoryuken/logging.rb ]; then
sed -n '1,240p' lib/shoryuken/logging.rb
else
echo "MISSING: lib/shoryuken/logging.rb"
fi
echo
echo "=== lib/shoryuken/processor.rb ==="
if [ -f lib/shoryuken/processor.rb ]; then
sed -n '1,240p' lib/shoryuken/processor.rb
else
echo "MISSING: lib/shoryuken/processor.rb"
fi
echo
echo "=== spec/shoryuken/processor_spec.rb ==="
if [ -f spec/shoryuken/processor_spec.rb ]; then
sed -n '1,240p' spec/shoryuken/processor_spec.rb
else
echo "MISSING: spec/shoryuken/processor_spec.rb"
fi
echo
echo "=== Search for context-related usages ==="
rg -n "Thread\\.current\\[:shoryuken_context\\]|Fiber\\.current\\.shoryuken_context|shoryuken_context|with_context|context_scope" || true
echo
echo "=== Check gemspecs / ruby version hints ==="
rg -n "required_ruby_version|required_ruby_version\\s*=|s.required_ruby_version|.ruby-version|ruby:|matrix:.*ruby" || true
echo
if [ -f .ruby-version ]; then
echo ".ruby-version:"
cat .ruby-version
else
echo "no .ruby-version file"
fi
echo
echo "=== GitHub workflows (ruby matrix) ==="
if [ -d .github/workflows ]; then
for wf in .github/workflows/*.yml .github/workflows/*.yaml; do
[ -f "$wf" ] || continue
echo "---- $wf ----"
sed -n '1,240p' "$wf"
echo
done
else
echo "no .github/workflows directory"
fiLength of output: 14642 Breaking change: logging context moved from thread-local → fiber-local — needs compatibility option or docs Short summary: I verified the change — logging now adds Fiber#shoryuken_context and uses Fiber.current for context/get/set (see lib/shoryuken/logging.rb). The repo requires Ruby >= 3.1 and CI runs 3.1–3.4, so Fiber-based storage is supported, but this does change semantics (contexts no longer automatically propagate across fibers). There are no other references to Thread.current[:shoryuken_context] in the repo. Files to inspect / attention points
Recommended action (fix required)
# default to :thread for backwards compatibility
@context_scope = :thread
def self.context_scope
@context_scope
end
def self.context_scope=(val)
@context_scope = val
end
def self.current_context_get
case context_scope
when :fiber
Fiber.current.shoryuken_context
else
Thread.current[:shoryuken_context]
end
end
def self.current_context_set(value)
case context_scope
when :fiber
Fiber.current.shoryuken_context = value
else
Thread.current[:shoryuken_context] = value
end
end
Rationale: the change is limited to logging.rb (no other Thread.current uses remain), but it is a behavioral change that can surprise fiber-heavy apps. If maintaining backward compatibility matters, implement the configurable strategy above (or document the breaking change clearly). 🧰 Tools🪛 RuboCop (1.76.1)[convention] 18-18: Space missing to the left of {. (Layout/SpaceBeforeBlockBraces) [convention] 18-18: Space between { and | missing. (Layout/SpaceInsideBlockBraces) [convention] 18-18: Space missing inside }. (Layout/SpaceInsideBlockBraces) 🤖 Prompt for AI Agents💡 Verification agent 🧩 Analysis chainFix style offenses and avoid Kernel#then for broader Ruby compatibility The safe-navigation + then pattern triggers RuboCop spacing offenses and depends on Kernel#then (Ruby 2.6+). A simpler expression avoids both issues and keeps behavior identical. Apply this diff: - Fiber.current.shoryuken_context&.then{|context| " #{context}"}
+ if (context = Fiber.current.instance_variable_get(:@shoryuken_context))
+ " #{context}"
+ endNotes:
If you prefer to keep using Kernel#then, please confirm the minimum supported Ruby version in the gemspec: Or verify via web search when Kernel#then was introduced: 🏁 Script executed: #!/bin/bash
# Check the minimum supported Ruby version to assess if Kernel#then is acceptable.
fd -a -t f -HI '\.gemspec$' | while read -r f; do
echo "== $f"
rg -n 'required_ruby_version|spec.required_ruby_version' "$f" || true
doneLength of output: 283 🌐 Web query: 💡 Result: Short answer
Details & dates
What versions support it
If you need
Citations:
Keep Kernel#then (gemspec ≥ 3.1.0) — just fix the RuboCop spacing Brief: the gemspec requires Ruby >= 3.1.0 (so Kernel#then, added in Ruby 2.6, is available). The remaining problem is a RuboCop spacing offense; please fix the block-brace spacing.
Apply this diff: - Fiber.current.shoryuken_context&.then{|context| " #{context}"}
+ Fiber.current.shoryuken_context&.then { |context| " #{context}" }📝 Committable suggestion
Suggested change
🧰 Tools🪛 RuboCop (1.76.1)[convention] 18-18: Space missing to the left of {. (Layout/SpaceBeforeBlockBraces) [convention] 18-18: Space between { and | missing. (Layout/SpaceInsideBlockBraces) [convention] 18-18: Space missing inside }. (Layout/SpaceInsideBlockBraces) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
@@ -30,10 +33,10 @@ def call(severity, _time, _program_name, message) | |||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| def self.with_context(msg) | ||||||||||||||||||||||||||||||||||
| Thread.current[:shoryuken_context] = msg | ||||||||||||||||||||||||||||||||||
| Fiber.current.shoryuken_context = msg | ||||||||||||||||||||||||||||||||||
| yield | ||||||||||||||||||||||||||||||||||
| ensure | ||||||||||||||||||||||||||||||||||
| Thread.current[:shoryuken_context] = nil | ||||||||||||||||||||||||||||||||||
| Fiber.current.shoryuken_context = nil | ||||||||||||||||||||||||||||||||||
| end | ||||||||||||||||||||||||||||||||||
|
Comment on lines
35
to
40
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Restore previous context on exit to support nested with_context blocks Current ensure unconditionally sets the context to nil, which breaks nested with_context usage. Example: with_context("outer") { with_context("inner") { ... } } after the inner block, context should be "outer", not nil.Apply this diff to save and restore the previous context: - def self.with_context(msg)
- Fiber.current.shoryuken_context = msg
- yield
- ensure
- Fiber.current.shoryuken_context = nil
- end
+ def self.with_context(msg)
+ fiber = Fiber.current
+ previous = fiber.instance_variable_get(:@shoryuken_context)
+ fiber.instance_variable_set(:@shoryuken_context, msg)
+ yield
+ ensure
+ fiber.instance_variable_set(:@shoryuken_context, previous)
+ endI can also add unit tests that validate:
📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| def self.initialize_logger(log_target = STDOUT) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid globally monkey-patching Fiber; prefer a scoped storage approach
Adding a public attr_accessor to Fiber introduces a global method that may clash with other libraries and is hard to reason about. You can avoid this by storing the context as an instance variable on the current fiber without adding methods to Fiber.
Apply this diff to remove the monkey patch:
Follow-up diffs for lines 18, 36, and 39 update the access to use instance_variable_get/set (see separate comments).
📝 Committable suggestion
🤖 Prompt for AI Agents