Sync with local "scratch" folder.
There are a number of things that need to be cleaned up since some of these changes were related to experimenting with Redis and SQL Server's in-memory OLTP.
Cleanup SqlServer db reads.
Use a list and an index instead of two collections to indicate which tokens have been sent.
Add some retry code.
Parse type 2 frames.
Don't forget to include the response's error code.
Fix off-by-one when reading responses.
The error response indicates the last known good identifier.
Don't discard notifications due to Shutdown or NoError.
CompletePartialNotificationAsync needs to invoke Quack.CompletePartialBatch.
(And pass the right parameter type...)
Consider all active writes completed if the connection is closed politely.
Add retries to SqlNotificationWriter.
Get rid of the redundant IsFailed flag.
Use field initializers.
Clear _pendinWrites after failing it.
Fix off-by-one when handling partial completion.
Use IsCompleted() when evaluating the last device of a notification.
Look in _pendingWrite for identifiers if it isn't found in _activeWrites.
Since a flush may happen in the middle of a pending write, it can contain completed devices.