Skip to content

Use PatchOperation.Set() for sliding expiration refresh. #88

@krispenner

Description

@krispenner

Using PatchOperation.Set<T>(String, T) to update a last accessed property on the document and therefore refreshing the _ts will be much faster and efficient than writing back the entire document including the cached item's content every time.

I think there are two places this should be done to replace the ReplaceItemAsync() call with PatchItemAsync() instead:

I wrote the original code to replace the document and update the ttl when using absolute expiration on the cached item several years ago, before Cosmos DB supported patch operations.

Adding a last accessed property for this purpose to set via a patch operation is most efficient. This single property would be set to current UTC unix time in a patch call which would in turn update the _ts property and therefore extend the time-to-live appropriately.

ItemResponse<CosmosCacheSession> refreshCacheSessionResponse = await this.cosmosContainer.PatchItemAsync<dynamic>(
    partitionKey: new PartitionKey(key),
    id: key,
    patchOperations: [
        PatchOperation.Set("/lastAccessed", DateTimeOffset.UtcNow.ToUnixTimeSeconds())
    ],
    requestOptions: new ItemRequestOptions()
    {
        IfMatchEtag = cosmosCacheSessionResponse.ETag,
        EnableContentResponseOnWrite = false,
    },
    cancellationToken: token).ConfigureAwait(false);

this.options.DiagnosticsHandler?.Invoke(refreshCacheSessionResponse.Diagnostics);

Could alternatively use Increment on a counter:

ItemResponse<CosmosCacheSession> refreshCacheSessionResponse = await this.cosmosContainer.PatchItemAsync<dynamic>(
    partitionKey: new PartitionKey(key),
    id: key,
    patchOperations: [
        PatchOperation.Increment("/refreshCounter", 1L)
    ],
    requestOptions: new ItemRequestOptions()
    {
        IfMatchEtag = cosmosCacheSessionResponse.ETag,
        EnableContentResponseOnWrite = false,
    },
    cancellationToken: token).ConfigureAwait(false);

this.options.DiagnosticsHandler?.Invoke(refreshCacheSessionResponse.Diagnostics);

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions