-
Notifications
You must be signed in to change notification settings - Fork 44
Saga 单例情况下, 导致concurrent和orders持久化 #81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR fixes a singleton-related bug where concurrent and orders properties persisted across multiple Saga instances. The solution replaces instance properties with Context-based storage, ensuring proper isolation between Saga transactions.
Key Changes:
- Replaced instance properties
$concurrentand$orderswith Context-based storage using class constants as keys - Added initialization of concurrent and orders values in the
init()method to ensure clean state for each transaction
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
| Context::set(static::CONCURRENT, false); | ||
| Context::set(static::ORDERS, []); |
Copilot
AI
Oct 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential race condition in singleton usage: if multiple threads call init() concurrently, the Context state could be overwritten unexpectedly. Consider using a transaction-specific context key (e.g., including $gid in the key) to ensure isolation between concurrent Saga instances.
| class Saga extends AbstractTransaction | ||
| { | ||
| protected array $orders = []; | ||
| protected const CONCURRENT = self::class . '.concurrent'; |
Copilot
AI
Oct 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using self::class instead of static::class in the constant definition may cause issues in inheritance scenarios. If a subclass of Saga uses these constants, they should resolve to the subclass name. Consider using a runtime method to generate context keys with static::class or document that these constants should not be inherited.
| $orders = Context::get(static::ORDERS, []); | ||
| $orders[$branch] = $preBranches; | ||
| Context::set(static::ORDERS, $orders); |
Copilot
AI
Oct 22, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The get-modify-set pattern for updating the orders array creates unnecessary overhead. Each call retrieves the entire array, modifies it, and stores it back. If addBranchOrder is called frequently, consider whether the Context API supports direct array modification or accumulate changes locally before final persistence.
|
@PandaLIU-1111 麻烦看一下这个pr 在例子中 Saga 对象中 concurrent和orders 一直存在, 不释放; 会影响 其他方法调用 |
你这种用法是有点问题的,理论上你应该要用 |
这里不建议使用单例,给的用例有点问题,你这么想这个问题,假设如果我一个协程内同时存在两个 Saga 是否就出问题了 public function complexOperation(Saga $saga1, Saga $saga2)
{
} |
public function complexOperation() 这样也有问题, Saga对象里面 add方法 底层也是 协程上下文保存的; |
当调用enableConcurrent方法后
concurrent的值一直为 true