Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-5823

Fiber-wrapped callbacks cannot see thread-local variables

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 9.1.0, 9.0.3
    • Affects Version/s: 9.0.2
    • Component/s: Callbacks
    • None
    • Ruby Drivers
    • Needed
    • Hide

      1. What would you like to communicate to the user about this feature?

      It is probably worth adding a footnote or an aside of some sort in the documentation for callbacks; something along the lines of:

      If you have embedded children with `cascade_callbacks: true`, it is important to understand that (as of Mongoid 9.0.1) those embedded child callbacks will be executed within a Ruby Fiber. This means that if you are using `Thread#[]` and `Thread#[]=` to get and set fiber-local variables, those callbacks will not be reading or setting the values you expect. It is strongly recommended that you use `Thread#thread_variable_get` and `Thread#thread_varaible_set` instead, for true thread-local variables. For convenience, Mongoid now provides `Mongoid::Threaded.get` and `Mongoid::Threaded.set`, to do just that.

      2. Would you like the user to see examples of the syntax and/or executable code and its output?

      No.

      3. Which versions of the driver/connector does this apply to?

      Mongoid 9.0.3 and later.

      Show
      1. What would you like to communicate to the user about this feature? It is probably worth adding a footnote or an aside of some sort in the documentation for callbacks; something along the lines of: If you have embedded children with `cascade_callbacks: true`, it is important to understand that (as of Mongoid 9.0.1) those embedded child callbacks will be executed within a Ruby Fiber. This means that if you are using `Thread#[]` and `Thread#[]=` to get and set fiber-local variables, those callbacks will not be reading or setting the values you expect. It is strongly recommended that you use `Thread#thread_variable_get` and `Thread#thread_varaible_set` instead, for true thread-local variables. For convenience, Mongoid now provides `Mongoid::Threaded.get` and `Mongoid::Threaded.set`, to do just that. 2. Would you like the user to see examples of the syntax and/or executable code and its output? No. 3. Which versions of the driver/connector does this apply to? Mongoid 9.0.3 and later.

      Internally, Mongoid depends (a lot) on thread-local variables. However, the current implementation actually uses fiber-local variables, rather than truly thread-local variables, which our nifty Fiber-wrapped callback implementation for child documents will loses access to all state that Mongoid has stored for the current thread. This has the potential to cause some really difficult bugs in some niche scenarios (like, when a child document wants to persist something in a cascaded callback).

      The solution might be to use true thread-local variables (Thread.current.thread_variable_get/set) instead of fiber-local variables.

            Assignee:
            jamis.buck@mongodb.com Jamis Buck
            Reporter:
            jamis.buck@mongodb.com Jamis Buck
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved: