Skip to content

Conversation

@JoasE
Copy link
Contributor

@JoasE JoasE commented Oct 24, 2025

Allows the user to retrieve session tokens from reads and writes done by a dbcontext and set session tokens to use for reads.
Adds a GetSessionTokens() extension method to DatabaseFacade which returns session tokens per container.
Adds a AppendSessionTokens() extension method to DatabaseFacade which allows appending session tokens per container.
Adds GetSessionToken() and AppendSessionToken() for the default container.
Adds option ManualSessionTokenManagementEnabled to CosmosDbContextOptionsBuilder

Implements: #36504

  • I've read the guidelines for contributing and seen the walkthrough
  • I've posted a comment on an issue with a detailed description of how I am planning to contribute and got approval from a member of the team
  • The code builds and tests pass locally (also verified by our automated build checks)
  • Commit messages follow this format:
        Summary of the changes
        - Detail 1
        - Detail 2

        Fixes #bugnumber
  • Tests for the changes have been added (for bug fixes / features)
  • Code follows the same patterns and style as existing code in this repo

@JoasE JoasE changed the title Add Cosmos db manual session token management #36504 Add Cosmos db manual session token management Oct 24, 2025
Copy link
Contributor Author

@JoasE JoasE left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few questions from me still

/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public class SessionTokenStorage : ISessionTokenStorage
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering if this needs to be a wrapper and have an SessionTokenStorageInternal.
Also wondering about naming: CosmosSessionTokenStorage?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now think that this API might be somewhat clunky to use. Perhaps this should just implement IReadOnlyDictionary<string, string> and that's what GetSessionTokens returns. AddSessionTokens(IReadOnlyDictionary<string, string>) will merge in the passed values and that's when you'll check container names (when the tokens are set internally we know that the containers are correct). I think this will make the common case of just moving all tokens from one instance to another easier and since it's not a special type it would also be simpler to (de)serialize in the app. This also avoids the potential ambiguity of the API using the default container name.

Copy link
Contributor Author

@JoasE JoasE Oct 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this implements IReadOnlyDictionary then the values in the reference the user receives will change after using a query or savechanges. Preventing them from having to call GetSessionTokens multiple times, but it might be confusing that it doesn't return a snapshot. Thoughts on this?

}

// @TODO: Is this the right place for this?
annotations.Add(CosmosAnnotationNames.ContainerNames, GetContainerNames(model));
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In SessionTokenStorage I want to check whether the container exists if a user is appending or adding a session token. It felt expensive to do GetContainerNames every DbContext instantiation, while I felt it could be a property of the model. However, I am not sure if annotations are the right way to add this data to the model for the cosmos provider. I am also not sure what would be the best place to calculate this metadata and set the annotation. Doing this this way fails CompiledModelCosmosTests and I am not sure if there is actually something wrong or the test should change and if so how.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AndriySvyryd or @roji Could you provide some guidance on this?

/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected virtual ISessionTokenStorage SessionTokenStorage => _sessionTokenStorage ??= Dependencies.Context.Database.GetSessionTokens();

This comment was marked as outdated.

_queryLogger = cosmosQueryContext.QueryLogger;
_standAloneStateManager = standAloneStateManager;
_threadSafetyChecksEnabled = threadSafetyChecksEnabled;
_sessionTokenStorage = sessionTokenStorage;
Copy link
Member

@AndriySvyryd AndriySvyryd Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will contain the instance from when the query was compiled, which will be incorrect for all, but the first time it's executed. Instead, add this to CosmosQueryContext

_currentDbContext = currentDbContext;
_cosmosClient = cosmosClient;

SessionTokenStorage = new SessionTokenStorage(_currentDbContext.Context);
Copy link
Member

@AndriySvyryd AndriySvyryd Oct 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implement IResettableService on this type and clear the tokens from SessionTokenStorage on reset (when an instance is returned to the pool). You can keep the container names, since a particular instance would only be reused for the same model.

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

Successfully merging this pull request may close these issues.

2 participants