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

UX design for persistence failure user notification #154

Closed
charlesh88 opened this issue Sep 28, 2015 · 7 comments
Closed

UX design for persistence failure user notification #154

charlesh88 opened this issue Sep 28, 2015 · 7 comments
Assignees

Comments

@charlesh88
Copy link
Contributor

#58 needs some design. Modal dialog is feeling like the best solution here. Victor created something similar to this a little while ago to handle overwrite situations - may use that, or clean that up.

@VWoeltjen
Copy link
Contributor

The desire here is to have a UI specification for how the application should behave when persistence errors occur, sufficient to cover all cases/varieties of persistence failure.

There are two specific goals to support here:

  1. Immediate priority: Users want to be aware of which changes have and have not been persisted successfully.
  2. Second priority: Users would like to be able to recover from persistence failures when possible.

There are some complicating factors:

  • There are a variety of different actions which may trigger persistence (the list is effectively open-ended since plugins can add actions)
  • Some actions effect multiple objects (meaning multiple separate persistence attempts)
  • Persistence failures may have multiple varieties, each of which has different basic resolution methods available.
  • Persistence failures may occur in a fixed fashion (e.g. when persisting changes to N objects, some objects may successfully persist while some others fail, and those failures may occur for different reasons)
    • It is unlikely that this would occur in practice, but is completely possible.

Actions which trigger persistence:

Action Number of objects persisted
Save (from Edit mode) Many (all objects modified while editing)
Edit Properties One
Remove One (the parent object)
Create Two (created object and parent)
Move Three (moved object, old parent, new parent)
Duplicate Many (new parent, duplicated objects)
Link One (new parent)
Start Timer One

Possible reasons for persistence to fail (this list is not comprehensive, but summarizes the cases which I think we might handle distinctly):

Reason Description Recovery Options
Revision conflict Same object had changes made from another browser/tab Overwrite, Discard, Merge? *
Permissions error User doesn't have permissions to persist changes server-side Discard, Retry? †
Server error Some server-side error caused persistence to fail Discard, Retry ‡
Network error Could not reach the server to persist. Discard, Retry ‡

* Merging could be attempted in principle, but doubtful this could be done in a way that the user would perceive as correct.
† Not sure retry makes sense here; I don't think there's any practical way for a user to resolve a permissions issue
‡ Retrying after a server error or network error could work, or could continue to fail indefinitely - no way to know this ahead of time.

@VWoeltjen
Copy link
Contributor

Note that, above, "Overwrite" is very similar (nearly functionally equivalent) to "Retry"; the distinction is that more recent changes are known to exist on the server which would be overwritten by the Retry attempt.

@charlesh88
Copy link
Contributor Author

Questions:

  • When persistence fails as mapped out above in the Victor's tables, will we know in all cases which objects failed to persist and which were successful? This could be presented in a scrolling list to the user, similar to or the same as we do now.
  • Will the notification be able to know the action that was being undertaken when persistence failed? Will it know the difference between the user Creating, Moving, Duplicating, etc.?
  • If there are persistence failures, what is the immediate result for the user? For example, I edit a Layout that contains two child elements that also persist. I click Save, and Persistence fails for the parent and one child, but succeeds for one child.
    • If I go back to the Layout, do I see my latest changes, or the old non-persisted object?
    • Same question for the one child that failed.
  • When persistence fails based on a user action, is the failure pretty immediate? I would think so, but if minutes might elapse between the action and the subsequent recognition of the failure mode, we may need to message the user differently.
  • I'm most worried about handling partial failure during Move and Copy, i.e. I move a large number of objects, some of them do get moved, and some don't. While we've said this shouldn't happen, seems to me we will not be able to absolutely prevent a failure of this type. When this does happen, what would Retry do? I think it has to retry only the failed items, yes? Otherwise, we run the risk of creating duplicate objects.
  • Are there cases where persistence failure should be a blocking event? Right now, I don't think so.

My comments:

  • I think making Retry available after a server or network error makes sense, even if there's no practical way for a user to resolve the issue - maybe they had a temporary Internet outage that fixed itself. Retry is better than nothing.
  • The case for Merge is with regard to Folder contents. I think this would be what the user expects and wants. I don't see Merge having relevance to other more complex composed objects.
  • While I think we should message successful persistence completion, this has to be done in a non-intrusive way that summarizes (not just communicates) what happened. So, let's say we show a banner message (per the current UI) when persistence is completed successfully. If the user saves a Layout that contains n items, they should only see a single success message, not n for each of the child items saved by the layout.
  • We mostly need to interrupt the user more directly when things don't work as expected; i.e. persistence fails for some reason. In this case, the user should be interrupted with a non-blocking dialog with available actions.

@charlesh88 charlesh88 assigned VWoeltjen and unassigned charlesh88 Oct 19, 2015
@charlesh88
Copy link
Contributor Author

Assigning to Victor for responses to questions.

@VWoeltjen VWoeltjen added this to the Banks milestone Nov 6, 2015
@VWoeltjen
Copy link
Contributor

  • When persistence fails as mapped out above in the Victor's tables, will we know in all cases which objects failed to persist and which were successful? This could be presented in a scrolling list to the user, similar to or the same as we do now.

Yes, we will know which ones failed and which were successful.

  • Will the notification be able to know the action that was being undertaken when persistence failed? Will it know the difference between the user Creating, Moving, Duplicating, etc.?

Yes, but it limits our options for how we do this (would be incompatible with #160.) Would prefer to stay generic if possible.

  • If there are persistence failures, what is the immediate result for the user? For example, I edit a Layout that contains two child elements that also persist. I click Save, and Persistence fails for the parent and one child, but succeeds for one child.
    • If I go back to the Layout, do I see my latest changes, or the old non-persisted object?
    • Same question for the one child that failed.

The result is that the back-end now is up-to-date for one of the children, but changes to the parent and child are not present. If you were to view the same layout from another client instance, you'd see the Layout and the first child as they appeared before the save, but the second child would contain the changes from editing.

As to what you'd see within the original window, a variety of behaviors could be implemented. I think currently you'd see the latest changes, but I don't think that's desired behavior.

Which one is "right" depends, I think, on what else has happened in the UI leading up to that point. If you give a dialog that says "Revert or Retry" and you choose revert, you should get the old version of the object (including the one that successfully saved, ideally *); if you retry, you should see the new version when it's been retrieved.

There are alternate models for presenting persistent state in the UI, though. You could just always show the user's latest edits and keep retrying persistence in the background (as discussed for #160).

* We can do this in semi-nominal cases where persistence failed, and the client detected it and rolled back changes. But we can't do this in all cases. If two-of-three persist operations fails, and my computer explodes before I can choose between Revert or Retry, I'm just going to be stuck with a mixed state in the database.

  • When persistence fails based on a user action, is the failure pretty immediate? I would think so, but if minutes might elapse between the action and the subsequent recognition of the failure mode, we may need to message the user differently.

For small operations (e.g. Create), yes, failure should be very immediate. For long-running actions like Duplicate, it may be much less than immediate. We can block the UI if needed until actions resolve.

  • I'm most worried about handling partial failure during Move and Copy, i.e. I move a large number of objects, some of them do get moved, and some don't. While we've said this shouldn't happen, seems to me we will not be able to absolutely prevent a failure of this type. When this does happen, what would Retry do? I think it has to retry only the failed items, yes? Otherwise, we run the risk of creating duplicate objects.

I agree that Retry should only do so for failed items, yes. In both cases, you can play with the ordering of operations to minimize disruption. For Copy, if you wait until everything else has successfully written before updating the destination to point to the new objects, you're pretty safe. Move is simpler (involves changes to three objects); I think the ordering we use here is to add it to the destination, then update the location of the moved object, then remove it from its original location. If you interrupt that at any point, you don't get what you wanted, but you get something that's recoverable (the object will be in its original location, or its new location, or both)

  • Are there cases where persistence failure should be a blocking event? Right now, I don't think so.

I can't think of any cases where it would absolutely have to be, so long as we effectively communicate the state of the system. If an object has unpersisted changes, I think we should at least visually indicate that.

@VWoeltjen VWoeltjen assigned charlesh88 and unassigned VWoeltjen Nov 6, 2015
@charlesh88
Copy link
Contributor Author

Still need to handle certain cases where a failed action isn't bubbling back up to the user. Flesh out scenarios that we haven't defined yet and eval for severity / priority. See #58.

@charlesh88 charlesh88 modified the milestones: Banks, Baxter Nov 30, 2015
@charlesh88 charlesh88 modified the milestones: Baxter, Bradbury Jan 5, 2016
@charlesh88 charlesh88 modified the milestones: Bradbury, Clarke Jan 29, 2016
@charlesh88 charlesh88 modified the milestones: Clarke, Ellison Feb 16, 2016
@charlesh88 charlesh88 removed this from the Clarke milestone Feb 16, 2016
@charlesh88 charlesh88 modified the milestones: Ellison, Gibson Mar 7, 2016
@VWoeltjen VWoeltjen modified the milestones: Gibson, Heinlein Apr 1, 2016
@VWoeltjen VWoeltjen modified the milestones: Heinlein, Herbert Apr 25, 2016
@VWoeltjen
Copy link
Contributor

Given that #58 is resolved, believe this is no longer an active issue.

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