The Ruby gem runs into an issue with storing and accessing the current transaction from the Thread.current[:appsignal_transaction] store.
We had a customer report where their app uses a gem dependency that uses Dry::Effects, which changes the Fiber in which our EventHandler's on_finish method is called, which breaks it trying to call Thread.current[:appsignal_transaction] and the transaction is never closed.
I made a quick fix in Ruby gem 4.5.9, in PR #1402.
But this doesn't clear the current transaction in Thread.current[:appsignal_transaction], which may be leaky for as long as the original Fiber remains running and until the GC does a run.
I previously tried to fix this by using thread_variable_set and thread_variable_get, but this breaks for servers like Falcon, which handle requests in Fibers.
Related branch: https://github.com/appsignal/appsignal-ruby/tree/thread-variables
One small thing we could do to make it work slightly better is:
- Add a flag on the Ruby Transaction class when
complete is called.
- In
Transaction.create if a transaction is read from Thread.current[:appsignal_transaction], check if the complete flag is set and discard the transaction if it was completed.
But to make our Ruby gem actually compatible with Fibers, if at all possible, requires some more thought on how to support it. The way I understand it, the Transaction protocol doesn't support async, which Fibers are, and it may be time to switch to the Spans protocol for the Ruby gem.
The Ruby gem runs into an issue with storing and accessing the current transaction from the
Thread.current[:appsignal_transaction]store.We had a customer report where their app uses a gem dependency that uses Dry::Effects, which changes the Fiber in which our
EventHandler'son_finishmethod is called, which breaks it trying to callThread.current[:appsignal_transaction]and the transaction is never closed.I made a quick fix in Ruby gem 4.5.9, in PR #1402.
But this doesn't clear the current transaction in
Thread.current[:appsignal_transaction], which may be leaky for as long as the original Fiber remains running and until the GC does a run.I previously tried to fix this by using
thread_variable_setandthread_variable_get, but this breaks for servers like Falcon, which handle requests in Fibers.Related branch: https://github.com/appsignal/appsignal-ruby/tree/thread-variables
One small thing we could do to make it work slightly better is:
completeis called.Transaction.createif a transaction is read fromThread.current[:appsignal_transaction], check if thecompleteflag is set and discard the transaction if it was completed.But to make our Ruby gem actually compatible with Fibers, if at all possible, requires some more thought on how to support it. The way I understand it, the Transaction protocol doesn't support async, which Fibers are, and it may be time to switch to the Spans protocol for the Ruby gem.