Bug? Saves are blocked to $SNAP_USER_DATA if snap updates when it is already running

While working on this I came across a part that should be explicitly designed as it involves user interaction. The specific decision on what to do when in a set of snaps that is being refreshed, some snaps are busy, some snaps were explicitly requested, what should happen: should we refresh partially or reject, and if we refreshed partially how to notify the user.

I think it’s easier to consider several cases as hypothetical user interaction on command line.

Context for examples below

  • snaps s1, s2, s3 and s4 are installed.
  • snaps s1 and s2 have pending refreshes.
  • snaps s2 and s3 have running non-service apps and cannot be refreshed.

Refreshing all snaps implicitly

$ snap refresh
refreshing snap s1
cannot refresh snap s2, it is currently running.

The error message about s2 is task log message, not a warning, because the user will see it and can take action immediately.

Auto-refreshing all snaps

This is exactly the same as above, namely, what can refresh does so, with the exception that the error message becomes a warning that the user can see via the warnings system.

Refreshing a single snap explicitly

$ snap refresh s1

Here snap s1 is outdated and not busy so it can refresh as usual.

$ snap refresh s2
cannot refresh snap s2, it is currently running

Here snap s2 is outdated but busy so it cannot refresh.

The error message about s2 should be a synchronous error from the API call per discussion with @niemayer in Cape Town.

Currently this cannot be done this way (synchronously) because we unconditionally refresh assertions before passing control to Update/UpdateMany. Instead error message can be logged via the task logger as for the case “refreshing all snaps implicitly” above.

$ snap refresh s3
snap s3 is up-to-date

Here snap s3 is up-to-date so we don’t even consider checking if it is busy or not.

Refreshing multiple snaps explicitly

When multiple snaps are refreshed we can complete a subset of the operation, depending on what the state of each requested snap is.

$ snap refresh s1 s2
refreshing snap s1
cannot refresh snap s2, it is currently running.

Here s1 and s2 are outdated but s2 is busy.

The error message about s2 is an asynchronous task log message, not a warning, because the user will see it and can take action immediately. At the same time, because s1 can refresh so the whole operation is a success.

$ snap refresh s2 s3
cannot refresh snap s2, its is currently running.
snap s3 is up-to-date

Here s2 is outdated and busy and s3 is up-to-date.

Here nothing was actually refreshed. The case behaves just as the one above though: the error message is logged asynchronously because we were busy checking for updates for s2 before we determined that it is busy. There are no warnings used since the user can see the message and act upon it.

$ snap refresh s3 s4
snaps are up-to-date, nothing to do

Here both s3 and s4 are up-to-date. We have not even considered if they are busy or not.