Skip to content
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

Concurrency Problems #31

Open
caleblloyd opened this issue Oct 7, 2013 · 3 comments
Open

Concurrency Problems #31

caleblloyd opened this issue Oct 7, 2013 · 3 comments

Comments

@caleblloyd
Copy link

The current implementation of this behavior only provides concurrency in a single Yii Application instance scenario. The static variable $_cached tracks all of the instances of Nested Set AR's in a single Yii Application instance and keeps left, right, level, and root attributes current.

The problem with this assumption is that each request served by a web server generates a new instance of a Yii Application. Furthermore, load balanced applications can create even more instances of Yii Applications on different servers. The static $_cache variable does not track anything outside the current Yii Application instance, meaning that the possibility for a stale cache exists both on a single and multi server implementation.

Databases transactions can solve this problem. This behavior does use transactions, but it uses potentially stale data that was fetched before the transaction was started. The following methods use potentially stale data:

-save(): This will by default save left, right, root, and level attributes. These could have been changed on another instance since the model was loaded. These attributes should not be saved by default.

-delete(): This uses $owner attributes, which were loaded before the DB Transaction was started. These attributes should be refreshed once the DB Transaction starts.

-addNode(): This uses $key (computed based off $target) and $target attributes, which were loaded before the DB Transaction was started. $target should be refreshed once the DB Transaction starts and $key should be computed after $target has been refreshed.

-moveNode(): same problem as addNode() except $owner attributes are also used.

-moveAsRoot(): same problem as delete().

Please let me know if you think refreshing this data inside of the Database transaction would fix the Concurrency issues that presently exist. I'm happy to contribute a fix.

@caleblloyd
Copy link
Author

I've put together a solution using SELECT...FOR UPDATE at the beginning of each transaction that modifies a tree. My only concern here is that I don't think SELECT...FOR UPDATE is database agnostic and therefore would need to be a configuration option that could be turned off for databases that don't support it.

I'm currently working off of this fork. It needs further testing, and I'd also like input on what needs to change for this to get Pulled into Master:
https://github.com/caleblloyd/nested-set-behavior/commit/4ea2b24a58a20e5b9754180c0eb1205ad13862ed

@creocoder
Copy link
Member

@caleblloyd Can you provide any real-life task when we need support concurrency in several Yii Applications?

@caleblloyd
Copy link
Author

One example would be an Application that allows Users to signup for accounts and stores each User ID in a Nested Set Hierarchy as they signup. In a high-traffic application, two users could easily sign up at the same time resulting in a corrupted Nested Set Tree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants