Warm tip: This article is reproduced from serverfault.com, please click

Where to store and how to maintain the continuation Token from cosmos db at client side

发布于 2020-12-01 12:26:40

am planning to implement paging using cosmos db continuation token. My api will return results and continuation token to client. My question here is which is the best place to store continuation token? Also the token will be changing per each subsequent request? How to maintain the previous continousTokens?

Here it shows where we get the value from and not where to store it How to pass\user azure continue token via webAPI Pagination in Cosmos DB using Page Size and Page Number

controller.cs

        [Route("myApps")]
        [HttpGet]
        public async Task<IActionResult> GetAllAppsAsync(string continuationToken, CancellationToken cancellationToken)
        {
            var user = this.GetUser();
            var results = await this.appRepository.GetAppsForUserAsync(user, continuationToken, cancellationToken).ConfigureAwait(false);
            var result = this.mapper.Map<AppHeader[]>(results.Value);
            return this.Ok(new KeyValuePair<string, AppDefinitionHeader[]>(results.Key, result));
        }
Repository.cs

 public async Task<KeyValuePair<string, IEnumerable<App>>> GetAppForUserAsync(User user,  string continuationToken, CancellationToken cancellationToken)
        {
            
            try
            {
                FeedOptions queryOptions = new FeedOptions
                {
                    MaxItemCount = 2,
                    RequestContinuation = continuationToken
                };
                string token = string.Empty;
                var query = this.factory.GetClient()
                    .CreateDocumentQuery<AppDefinitionResource>(
                        UriFactory.CreateDocumentCollectionUri(DatabaseName, CollectionName),
                        queryOptions)
                    .AsDocumentQuery();

                List<AppDefinition> results = new List<AppDefinition>();
                while (query.HasMoreResults && results.Count <= 2)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var response = await query.ExecuteNextAsync<App>(cancellationToken).ConfigureAwait(false);

                    var apps = this.mapper.Map<App[]>(response);
                    results.AddRange(apps);
                    token = response.ResponseContinuation;
                }

                return new KeyValuePair<string, IEnumerable<App>>(token, results);
            }
           
        }

Update :

How to maintain the previous continousTokens?

Ex : If there are 100 records and pageSize=10 and pageNumbers are 1,2,3,4,5,6,7,8,9,10 and if user clicks randomly on any page. In that case how to fetch required records? or just if I place "Previous" button in the below screenshot and want to traverse back in the list.

https://i.stack.imgur.com/BMwI2.gif

Questioner
Deepak Kothari
Viewed
0
Mo B. 2020-12-01 23:17:59

Yes, the token changes for each request, so that you can retrieve previous pages with previous tokens.

If you pass the token on to the client to keep the backend stateless, you should not send the token within the URL or a URL query, since the token can get quite large. Within the client you can just keep the token in memory. In most cases it's not necessary to persist the token, since a token should be short-lived. It should be short-lived since paginated results reflects all the changes that happen between each page request.


Update based comments

Since the token may be large, it has to be passed in the body of the request, which also means it shouldn't be a GET request.

An alternative solution would be to store the token in a cache with a smaller key (e.g. a GUID) in the backend (with some limited TTL) and just pass the key between backend and client. That way you can pass the key in the URL or in a URL query. But that requires the backend to hold state.