From: "byroot (Jean Boussier)" Date: 2022-10-26T10:21:19+00:00 Subject: [ruby-core:110515] [Ruby master Feature#19078] Introduce `Fiber#storage` for inheritable fiber-scoped variables. Issue #19078 has been updated by byroot (Jean Boussier). I'm generally in favor of this feature. Lots of Ruby code rely on "global" state (generally implemented as fiber locals) so whenever you spawn a new fiber or thread you lose all that context which generally breaks code. Things I think should be added to the ticket description: ### Inheritance A fiber storage is initialized as a shallow-copy of the parent fiber. Overwriting a key in the child, doesn't impact the parent, think of it as POSIX environment variables: ```ruby Fiber[:request_id] = SecureRandom.hex(16) # aaaaa Fiber.new do p Fiber[:request_id] # prints aaa Fiber[:request_id] = SecureRandom.hex(16) # bbbb p Fiber[:request_id] # prints bbbb end p Fiber[:request_id] # prints aaaa ``` However it is a shallow copy, so if you mutate one of the value, you may end up with shared mutable state, but that's on you. ### What keys can be used? Symbols only like `Thread#[]` ? Would seem sensible to me. ### Do we need the same API on `Thread`? Could be useful for variables that are thread scoped and should be inherited too. Problem is `Thread#[]` is already used for fiber-local variables. Overall I agree with @tenderlove, this would make Rails' `IsolatedExecutionState` obsolete, which is good, and if used properly would save the classic issue of code breaking in iterator fibers because some fiber local state was lost. ---------------------------------------- Feature #19078: Introduce `Fiber#storage` for inheritable fiber-scoped variables. https://bugs.ruby-lang.org/issues/19078#change-99838 * Author: ioquatix (Samuel Williams) * Status: Open * Priority: Normal * Assignee: ioquatix (Samuel Williams) ---------------------------------------- Pull Request: https://github.com/ruby/ruby/pull/6612 This is an evolution of the previous ideas: - https://bugs.ruby-lang.org/issues/19058 - https://bugs.ruby-lang.org/issues/19062 This PR introduces fiber scoped variables, and is a solution for problems like . The main interface is: ```ruby Fiber[key] = value Fiber[key] # => value ``` The variables are scoped (local to) a fiber and inherited into child fibers and threads. ```ruby Fiber[:request_id] = SecureRandom.hex(16) Fiber.new do p Fiber[:request_id] # prints the above request id end ``` The fiber scoped variables are stored and can be accessed: ```ruby Fiber.current.storage # => returns a Hash (copy) of the internal storage. Fiber.current.storage= # => assigns a Hash (copy) to the internal storage. ``` Fiber itself has one new keyword argument: ``` Fiber.new(..., storage: hash, false, undef, nil) ``` This can control how the fiber variables are setup in a child context. To minimise the performance overhead of some of the implementation choices, we are also simultaneously implementing . ## Examples ### Request loop ```ruby Thread.new do while request = queue.pop Fiber.new(storage: {id: SecureRandom.hex(16)}) do handle_request.call(request) end end end ``` OR ```ruby Thread.new do while request = queue.pop Fiber.current.storage = {id: SecureRandom.hex(16)} handle_request.call(request) end end ``` -- https://bugs.ruby-lang.org/ Unsubscribe: