-
-
Notifications
You must be signed in to change notification settings - Fork 226
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
Optimistic conflicts resolution mecanism #772
Conversation
d37bee3
to
be5faee
Compare
f261af2
to
ae6fd3b
Compare
One of the keys, if we go that direction, is to keep the relevant versions while there is an editing session going, so maybe instead of keeping the n last versions, we should combine that with the versions from the last hour (but this implies some cron to delete versions, which is less KISS). |
d0d27d1
to
eaf1061
Compare
I've just rebased this but I'm getting an (unrelated ?) error:
Do you have an idea where this could come from? |
Happens also on the latest master, I've opened an issue #1404 |
eaf1061
to
2fab326
Compare
I've pushed an updated version of the code and tests. It's still doing some "magic" stuff with the form that I'm not super happy with, but I would gladly see a review of these changes already. |
if removed not in latest: | ||
raise ConflictError() | ||
|
||
merged = latest[:] |
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.
We might actually do a copy.deepcopy
here to avoid editing objects elsewhere.
umap/views.py
Outdated
response["Last-Modified"] = self.last_modified | ||
return response | ||
def has_been_modified_since(self, if_unmodified_since): | ||
if if_unmodified_since and self.last_modified != if_unmodified_since: |
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.
Maybe we could just return if_unmodified_since and self.last_modified != if_unmodified_since
if not merged: | ||
return HttpResponse(status=412) | ||
|
||
# Replace the uploaded file by the merged version. |
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.
I'm not a fan of this "let's overwrite what the client sent us", do you have a better idea?
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.
Sounds good to me!
Didn't you said you wanted to use sets instead ?
Actually, sets needs to have hashable elements inside, which is not our case at the moment, because we're storying dicts. and dicts of lists, so it's not possible :-) |
a9f80d4
to
4f32c6c
Compare
There is some magic done with the form handling here. It's useful in order to circumvent the way we use Django model forms. Changing this would probably mean using a separated "update datalayer form", not tied to the model, so we can validate the form without altering the model (which seem to be how django does). Here are some notes for later usage if needed: While trying to change how the Form is used in a DataLayer update, I've understood how things work, so here are some notes. I wanted the submitted form to be processed and validated, and then merged with a document already present in the database. However, since the form is a |
4f32c6c
to
5739228
Compare
The server tries to merge conflicting saves of the same layer. What it does: - use the `If-Unmodified-Since` header to check if changes happened to the stored data ; - Compare the incoming version with its reference version to get a diff. - Reapply the diff on top of the latest version. - If the merge is not possible, return a "422 Conflict" HTTP response. - If the merge worked, return the merged document, to be updated by the client.
5739228
to
f37ed70
Compare
BAM! 🎉 🚀 |
Bumps [psycopg](https://github.com/psycopg/psycopg) from 3.2.2 to 3.2.3. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/psycopg/psycopg/blob/master/docs/news.rst">psycopg's changelog</a>.</em></p> <blockquote> <p>.. currentmodule:: psycopg</p> <p>.. index:: single: Release notes single: News</p> <h1><code>psycopg</code> release notes</h1> <h2>Current release</h2> <p>Psycopg 3.2.3 ^^^^^^^^^^^^^</p> <ul> <li>Release binary packages including PostgreSQL 17 libpq (:ticket:<code>[#852](https://github.com/psycopg/psycopg/issues/852)</code>).</li> </ul> <p>Psycopg 3.2.2 ^^^^^^^^^^^^^</p> <ul> <li>Drop <code>!TypeDef</code> specifications as string from public modules, as they cannot be composed by users as <code>!typing</code> objects previously could (:ticket:<code>[#860](https://github.com/psycopg/psycopg/issues/860)</code>).</li> <li>Release Python 3.13 binary packages.</li> </ul> <p>Psycopg 3.2.1 ^^^^^^^^^^^^^</p> <ul> <li>Fix packaging metadata breaking <code>[c]</code>, <code>[binary]</code> dependencies (:ticket:<code>[#853](https://github.com/psycopg/psycopg/issues/853)</code>).</li> </ul> <h2>Psycopg 3.2</h2> <p>.. rubric:: New top-level features</p> <ul> <li>Add support for integer, floating point, boolean <code>NumPy scalar types</code>__ (:ticket:<code>[#332](https://github.com/psycopg/psycopg/issues/332)</code>).</li> <li>Add <code>!timeout</code> and <code>!stop_after</code> parameters to <code>Connection.notifies()</code> (:ticket:<code>340</code>).</li> <li>Allow dumpers to return <code>!None</code>, to be converted to NULL (:ticket:<code>[#377](https://github.com/psycopg/psycopg/issues/377)</code>).</li> <li>Add :ref:<code>raw-query-cursors</code> to execute queries using placeholders in PostgreSQL format (<code>$1</code>, <code>$2</code>...) (🎟️<code>[#560](psycopg/psycopg#560), [#839](https://github.com/psycopg/psycopg/issues/839)</code>).</li> <li>Add <code>capabilities</code> object to :ref:<code>inspect the libpq capabilities <capabilities></code> (🎫<code>[#772](https://github.com/psycopg/psycopg/issues/772)</code>).</li> <li>Add <code>~rows.scalar_row</code> to return scalar values from a query (:ticket:<code>[#723](https://github.com/psycopg/psycopg/issues/723)</code>).</li> <li>Add <code>~Connection.cancel_safe()</code> for encrypted and non-blocking cancellation when using libpq v17. Use such method internally to implement</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/psycopg/psycopg/commit/ce8f07321b8d0f0d95043596cbbbb6fd1e5831e7"><code>ce8f073</code></a> chore: bump psycopg package version to 3.2.3</li> <li><a href="https://github.com/psycopg/psycopg/commit/9af9267bdbe9075a7eacf5d3997512513a762022"><code>9af9267</code></a> Merge pull request <a href="https://redirect.github.com/psycopg/psycopg/issues/917">#917</a> from psycopg/pg17</li> <li><a href="https://github.com/psycopg/psycopg/commit/9c9369bea40ed20cf54241d9e04693fc2426a9ff"><code>9c9369b</code></a> docs: mention PostgreSQL 17 in binary packages in the news file</li> <li><a href="https://github.com/psycopg/psycopg/commit/d0b1a3ab0a53b8bc34ba52edbe0340fcc5b0db1f"><code>d0b1a3a</code></a> ci: install flex to build libpq</li> <li><a href="https://github.com/psycopg/psycopg/commit/17e8d85f695947ef3421ff4c596100124fa2c8c1"><code>17e8d85</code></a> ci(macos): fix dylib path for postgres 17 from brew</li> <li><a href="https://github.com/psycopg/psycopg/commit/d06613299aee124be6e673b238bbe747bad25978"><code>d066132</code></a> ci(macos): update brew to install PostgreSQL 17</li> <li><a href="https://github.com/psycopg/psycopg/commit/2cc362e4dc662413f32d9e289afa0493fb2aada2"><code>2cc362e</code></a> ci: bump to PostgreSQL 17 in binary packages</li> <li><a href="https://github.com/psycopg/psycopg/commit/810bfcf09c452e378adc23a2795736dea8395cfa"><code>810bfcf</code></a> chore: add PostgreSQL 17 TRANSACTION_TIMEOUT error</li> <li><a href="https://github.com/psycopg/psycopg/commit/2a0242163b144153a6c7b9af08c47c9f3fd790f4"><code>2a02421</code></a> ci: Add PostgreSQL 17 to CI test grid, remove PostgreSQL 11</li> <li><a href="https://github.com/psycopg/psycopg/commit/bea783d394ab5ad1f9f795af22a77370fad28ab6"><code>bea783d</code></a> fix(windows): resolve absolute path to libpq</li> <li>Additional commits viewable in <a href="https://github.com/psycopg/psycopg/compare/3.2.2...3.2.3">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=psycopg&package-manager=pip&previous-version=3.2.2&new-version=3.2.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details>
original code from @Biondilbiondo (Thanks! :) )
Basically:
then we merge