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

Revise page checkout procedure #756

Open
70ray opened this issue Jan 26, 2022 · 3 comments
Open

Revise page checkout procedure #756

70ray opened this issue Jan 26, 2022 · 3 comments

Comments

@70ray
Copy link
Collaborator

70ray commented Jan 26, 2022

It is theoreticaly possible for two different users to checkout the same page for proofreading if they both access the server at about the same time. The operation is now done in two steps: identify an available page, then update it. If this is running in a pre-emptive multitasking system, another user's request could get between these steps.
There is a case for not doing anything about this since the problem may never happen and would not be serious if it did.
It would be possible to fix it by updating a page based on the selection criteria and then finding it as the newest page checked out to the user.

@cpeel
Copy link
Member

cpeel commented Jan 26, 2022

In the failure case, the first request to update the page wins and the second request will get an error, correct?

@70ray
Copy link
Collaborator Author

70ray commented Jan 26, 2022

I suppose the first one to reach the checkout() would think they had the page but the last one would override. The problem would be noticed when they got to the next stage, in the second pass through proof_frame.php when one of them would get an error from resume_saved_page in LPage.php that they didn't have the necessary access. I think the name of this function (and comment in it) is misleading since the page could have come from page_out state. (Unless I have misunderstood how it works)

@jmdyck
Copy link
Contributor

jmdyck commented Feb 15, 2022

One possibility would be to add checks to the WHERE clause of the UPDATE command. E.g., when a page is being checked out, require that it be in the "avail" state. That way, even if get_available_page decides on the same page for two different users, only one of them will actually be able to check out the page.

We do currently perform these checks, but via a separate query, which is why there's a race condition.
Currently, _Page_require_ queries for some attributes of the page and then throws exceptions if they don't satisfy certain constraints. Instead, we could express the constraints as SQL conditions and add them to the UPDATE's WHERE clause. (Note that this also eliminates one query for most page operations.)

We could either retain _Page_require, but have it construct+return the SQL condition, which is then passed to _Page_UPDATE, or else just merge that functionality into _Page_UPDATE.

If the UPDATE fails, you wouldn't necessarily know why (to the level of detail that _Page_require currently describes). In the rare case that it happens, you could do follow-up queries to pin it down, but the default error-handling behavior might be enough.

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

3 participants