[Bug] Some common uses of ActiveModel fail in workflows due to sync construct use
メンテナーはふだん 1 日以内に返信
評価
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 初心者へのやさしさ
- 30/100
- issue の種類
- バグ
- 明瞭さ
- 説明が足りない
- 活発さ
- 停滞
- 技術スタック
- ruby
調査の方向性
まず、示されている ActiveModel::Model と ActiveModel::Attributes の例を workflow 内で再現し、trace の attribute_methods.rb と illegal_call_tracer.rb のフレームを調査します。どの ActiveModel 操作が ConcurrentMap または Thread::Mutex を呼び出すのかを特定し、その後、回帰テストによる workflow で安全な動作を定義して検証します。一般的な ActiveModel の使用で workflow の非決定性エラーが発生しなくなれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
Many common uses of ActiveModel use ConcurrentMap under the hood which uses Thread::Mutex which is forbidden in workflows.
We believe this can be replicated simply by accessing an attribute that doesn't exist. We also believe this can be replicated using a model set like:
module MyCompany
module Messages
class Foo
include Message
attribute :some_field_1, :string
attribute :some_field_2, :string
attribute :some_field_3, ObjectType.for(Array), :default => []
attribute :some_field_4, :boolean, :default => false
attribute :some_field_5, :boolean, :default => false
end
end
module Message
extend ActiveSupport::Concern
include ActiveModel::Model
include ActiveModel::Attributes
include ActiveModel::Serializers::JSON
included do
def as_json(options = {})
super(options).merge(::JSON.create_id => self.class.name)
end
end
class_methods do
def json_create(data)
new(**data.except(JSON.create_id))
end
end
end
end
This can give stack traces like:
W, [2025-10-24T12:22:16.291089 #70269] WARN -- : Cannot access Thread::Mutex synchronize from inside a workflow, reason: disallowed. If this is known to be safe, the code can be run in a Temporalio::Workflow::Unsafe.illegal_call_tracing_disabled block. {:attempt=>1, :namespace=>"default", :run_id=>"019a1773-c113-74ff-924d-7c51d86cd682", :task_queue=>"deliverable-orchestration", :workflow_id=>"59824eb54dc4fa489c15c372", :workflow_type=>"OrchestrationWorkflowV2"} (Temporalio::Workflow::NondeterminismError)
/path/to/gems/temporalio-0.6.0-arm64-darwin/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb:112:in `block in initialize'
/path/to/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb:25:in `compute_if_absent'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attribute_methods.rb:400:in `attribute_method_matchers_matching'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attribute_methods.rb:506:in `matched_attribute_method'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attribute_methods.rb:494:in `respond_to?'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attribute_assignment.rb:48:in `_assign_attribute'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attribute_assignment.rb:42:in `block in _assign_attributes'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attribute_assignment.rb:41:in `each'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attribute_assignment.rb:41:in `_assign_attributes'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attribute_assignment.rb:34:in `assign_attributes'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/model.rb:81:in `initialize'
/path/to/gems/activemodel-6.1.7.10/lib/active_model/attributes.rb:77:in `initialize'
/path/to/models/my_models.rb:99:in `new'
And for cases where it's an invalid attribute access via method_missing, it can give traces like:
/path/to/gems/temporalio-1.0.0-arm64-darwin/lib/temporalio/internal/worker/workflow_instance/illegal_call_tracer.rb:112:in `block in initialize'
/path/to/gems/concurrent-ruby-1.3.4/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb:25:in `compute_if_absent'
/path/to/gems/activemodel-6.1.7.3/lib/active_model/attribute_methods.rb:400:in `attribute_method_matchers_matching'
/path/to/gems/activemodel-6.1.7.3/lib/active_model/attribute_methods.rb:506:in `matched_attribute_method'
/path/to/gems/activemodel-6.1.7.3/lib/active_model/attribute_methods.rb:468:in `method_missing'
my_workflow_class.rb:52:in `block in execute'
my_workflow_class.rb:39:in `loop'
ConcurrentMap use is so pervasive in ActiveModel, it is unreasonable for us to ask users not to use anything relying on it. Also, it may be unreasonable to just alter our illegal trace detector to check backtrace for the active model because the use of mutexes can cause an issue like we hit with loggers (see https://temporal.io/blog/temporal-ruby-crash-proof-fibers#implicitly-used-sync-constructs).
The best solution may be a WorkflowSafeObject type of mixin that surrounds every call with Workflow::Unsafe::durable_scheduler_disabled.
- 主要言語
- Ruby
- スター
- 207
- フォーク
- 44
- 平均マージ
- 2日 42分
- マージ済み PR(30日)
- 19
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
temporalio/sdk-ruby のほかの issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
temporalio/sdk-ruby#625 ·
メンテナーはふだん 1 日以内に返信
-
[Bug] JSON payload decoding raises ArgumentError with json 3.x (JSON.parse options are keyword-only)対応中かも @GregoryTravis が 5 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
temporalio/sdk-ruby#595 · コメント 4 件 · 担当者 2 名 ·
メンテナーはふだん 1 日以内に返信
-
Enable concurrent payload visiting - Ruby対応中かも @jmaeagle99 が 5 日前に担当しました。 オープン
temporalio/sdk-ruby#616 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
External Payload Storage Foundation - Ruby対応中かも @jmaeagle99 が 9 日前に担当しました。 オープン
temporalio/sdk-ruby#614 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
[Bug] Exception in an unawaited Workflow::Future is silently swallowed, leaving the workflow stuck RUNNING対応中かも @GregoryTravis が 5 日前に担当しました。 オープンbug
難易度 3/5 半日 初心者へのやさしさ 40/100
temporalio/sdk-ruby#613 · リアクション 1 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
temporalio/sdk-ruby の issue をすべて見る
似ている issue
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 61/100
hitobito/hitobito_pfadi_de#164 ·
メンテナーはふだん 5 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 7 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 2 日以内に返信
-
Windows: packaged_agent_ruby? never matches 'Puppet Labs\Puppet', so the openvox gem is not foundオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
-
難易度 1/5 1時間未満 初心者へのやさしさ 68/100
メンテナーはふだん 17 日以内に返信