Project

General

Profile

Feature #19078

Updated by ioquatix (Samuel Williams) over 1 year ago

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 <https://github.com/ioquatix/ioquatix/discussions/17>. 

 The main interface is: 

 ```ruby 
 Fiber[key] = value 
 Fiber[key] # => value 
 ``` 

 The variables are scoped (local to) a by 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 of the internal storage. 
 Fiber.current.storage= # => assigns a Hash to the internal storage. 
 ``` 

 I'm still on the fence as to whether these methods should return an actual mutable Hash, or function as a copy (so we don't force the internal representation to be a hash table). 

 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 <https://bugs.ruby-lang.org/issues/19077>. 

 ## 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 
 ``` 

Back