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

fix duplicate objects after restoring data from localStorage #2135

Merged
merged 3 commits into from
Feb 25, 2014

Conversation

tyrasd
Copy link
Member

@tyrasd tyrasd commented Feb 20, 2014

Attempt to fix #2134 (and possibly also #2091 and #1249).

This is not yet 100% finished, but can already be reviewed. Todos:

  • fix failing restores from v2 JSON (modification) test
  • add tests for restores from v3 JSON
  • undo v -> version refactoring

@jfirebaugh
Copy link
Member

Thanks for digging into this Martin. Can you explain what the problem is and the strategy this PR takes for fixing it?

@tyrasd
Copy link
Member Author

tyrasd commented Feb 20, 2014

OK. We have the following situation:

One edits in region A modifying object X (version v -> v+1) then closes the browser tab and later continues to edit in region B, using the restore tool.

After the fromJSON() the history stack looks like the following: stack[0] contains the data loaded from the API for region B, stack[1-…] contain the restored edits, including object X in version v+1. When iD later calculates the difference() between the head and the base (which is stack[0]), object X gets interpreted as a newly created one. The produced osmChange looks like the following:

<osmChange version="0.3" generator="iD">
  <create>
    <way id="X" version="v" changeset="…">…</way>
  </create>
</osmChange>

Note the non-negative id X of the "created" way and that v > 1. The response from the OSM API is something like:

<way old_id="X" new_id="…some new id…" new_version="1"/>

To solve this, I extended the toJSON() method to save also the original versions of all modified objects in the localStorage JSON (field baseEntities), which get rebased into the initially loaded data during the restore action.

@@ -292,8 +309,6 @@ iD.History = function(context) {

var json = context.storage(getKey('saved_history'));
if (json) history.fromJSON(json);

context.storage(getKey('saved_history', null));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line contained a typo (first parenthesis should close right after 'saved_history').
But then this would be quite contra-productive if the browser crashes right after restoring the data (before uploading or another change).
So, I simply dropped it.

@tyrasd
Copy link
Member Author

tyrasd commented Feb 20, 2014

I've also refactored the Entity class to use the version field instead of the v, because the version is already present from the API calls and it doesn't really make sense to maintain two different sets of entity versions. This should lead to osmChange files that have more meaningful version parameters (although the API apparently doesn't care about them anyway):

<osmChange version="0.3" generator="iD">
  <modify>
    <way id="X" version="v+1" changeset="…">…</way>
  </modify>
</osmChange>

(note the v+1 instead of simply v as above)

@tyrasd
Copy link
Member Author

tyrasd commented Feb 20, 2014

OK, the PR should be complete now.

@jfirebaugh
Copy link
Member

version and v serve two different purposes. version is the OSM version, v is an internal identifier that is incremented on when the entity undergoes a modification; it's used to avoid updating D3 selection elements whose corresponding datum has not changed. Please revert that portion of the commit.

This makes sure that the originals of changed entities get merged
into the base of the stack after restoring the data from JSON.
This is necessary, because the stack will only have elements for
the current viewport after a restart and previously *modified*
objects will now be falsely detected as *created* ones.

Also removed some ineffective code.
@tyrasd
Copy link
Member Author

tyrasd commented Feb 21, 2014

Oh, I see. (should have looked more at the inline documentation ^^).
It's reverted now.

@jfirebaugh
Copy link
Member

Ok, it took me a while to digest everything that was going on, but I think I have a good understanding now, and this approach looks sound. I see a couple adjustments to make:

  • A similar fix is needed for deletions -- the base version should be recorded and restored. Right now if you restore in a different area the deletion disappears. If you remove the history.merge([iD.Node({id: 'n1'})]); line from the deletion test (which should be done), you'll see it fail.
  • When rebasing, the tree needs to be rebased as well.

Deleted objects need to be kept in the base of the history stack, too.

This also improves the respective unit tests.
@tyrasd
Copy link
Member Author

tyrasd commented Feb 22, 2014

A similar fix is needed for deletions

True: efd3223

jfirebaugh added a commit that referenced this pull request Feb 25, 2014
fix duplicate objects after restoring data from localStorage
@jfirebaugh jfirebaugh merged commit 53f5379 into openstreetmap:master Feb 25, 2014
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

Successfully merging this pull request may close these issues.

History deleted when new changeset added
2 participants