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

Support ETag Concurrency #56

Open
jviau opened this issue Oct 20, 2021 · 5 comments
Open

Support ETag Concurrency #56

jviau opened this issue Oct 20, 2021 · 5 comments
Labels

Comments

@jviau
Copy link

jviau commented Oct 20, 2021

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:

  1. Derive CosmosDistributedCacheEntryOptions : DistributedCacheEntryOptions and add ETag appropriate properties on there.
  2. 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.

@jviau jviau added the enhancement New feature or request label Oct 20, 2021
@ealsur
Copy link
Member

ealsur commented Oct 20, 2021

How would you get the Etag from the Get response?

@jviau
Copy link
Author

jviau commented Oct 20, 2021

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.

@ealsur
Copy link
Member

ealsur commented Oct 20, 2021

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?

@jviau
Copy link
Author

jviau commented Oct 20, 2021

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).

@ealsur
Copy link
Member

ealsur commented Oct 20, 2021

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants