Support ETag Concurrency
Is your feature request related to a problem? Please describe. This is to avoid race conditions for writing a cache value from two places with conflicting values.
Describe the solution you'd like
Add support for CosmosDBs etag concurrency on Set (and maybe even Get)
Describe alternatives you've considered There is no 'true' alternative to fix this, as it would always require multiple cache reads or writes to accomplish, and without those being within a single transaction, there is no way to guarantee a race condition did not occur.
Additional context Recommend solution:
- Derive
CosmosDistributedCacheEntryOptions : DistributedCacheEntryOptionsand add ETag appropriate properties on there. - Set / Get implementation can test if the passed in value is that type, and change ETag request options to CosmosDB as appropriate.
This way there is no API change or breaking change for existing users. New usage just needs to use the new entry options type if they desire, but can continue to use the old type if they have no need for ETag.
How would you get the Etag from the Get response?
The ETag is available in the "_etag" property from the content returned by CosmosDB.
Albeit, I have not tested with just a byte array response, but json serialization directly with the Cosmos SDK.
So if it is present in that response, it would be up to the consumer to ensure they read the etag out of the content correctly.
That's true but the _etag or the content of the actual document stored on Cosmos DB is not exposed on any read APIs. The public surface is defined by IDistributedCache and the Get calls only return the actual byte content that was stored (not the complete byte content of the document but just the stored content), not anything else.
So based on that public API surface, there is no way for you to know which was the _etag that was read, right?
Unless we start going over the IDistributedCache API and start specific APIs on the CosmosCache implementation. How do other DistributedCache implementations handle concurrent Sets?
Ah right - didn't notice the document is wrapped in a CosmosCacheSession from this repo. The etag would be on that object (if you added a property that would deserialize from the "_etag" json property). Returning it to the caller would be tricky then, as it would be difficult to augment it into the returned byte array.
Only way I can think of without affective the APIs would be to do this via extension methods which have a different return type (and using internal methods which the extension calls into).
Yeah, you'd have to instead of accessing IDistributedCache, you'd have to access CosmosCache.
For example, if CosmosCache had an extension method called GetSoAndSo() that returned the current byte[] + the Headers (Etag actual value is returned on the Headers) it could work. Needs a bit of a think through because it would require 2 specialized flows (Read and Write) that are outside of the IDistributedCache API.
This obviously is not accessible for ASP.NET Session because they use the HttpContext.Session object directly, no way to access the underlying CosmosCache.