/// <inheritdoc />
        public async Task <LockToken> RenewAsync(LockToken token, TimeSpan duration)
        {
            var table = await GetTableAsync();

            var doc = new Document();

            doc[ColumnNames.HolderId]   = token.HolderId;
            doc[ColumnNames.ResourceId] = token.ResourceId;
            var expiry = DateTimeOffset.UtcNow.Add(duration);

            doc[ColumnNames.LeaseExpiry] = expiry.ToString("O");

            var expr = new Expression();

            expr.ExpressionStatement = $"{ColumnNames.ResourceId} = :ID OR {ColumnNames.LeaseExpiry} < :NOW";
            expr.ExpressionAttributeValues[":NOW"] = DateTimeOffset.UtcNow.ToString("O");
            expr.ExpressionAttributeValues[":ID"]  = token.ResourceId;

            try
            {
                await table.PutItemAsync(doc, new PutItemOperationConfig()
                {
                    ConditionalExpression = expr
                });

                return(token.WithNewExpiry(expiry));
            }
            catch (ConditionalCheckFailedException e)
            {
                return(null);
            }
        }
        /// <inheritdoc />
        public async Task ReleaseLockAsync(LockToken token)
        {
            var table = await GetTableAsync();

            var doc = new Document();

            doc[ColumnNames.HolderId]    = token.HolderId;
            doc[ColumnNames.ResourceId]  = token.ResourceId;
            doc[ColumnNames.LeaseExpiry] = token.LeaseExpiry.ToString("O");
            await table.DeleteItemAsync(doc);
        }