public async Task <StorageRecord> GetAsync(string id)
        {
            await this.SetupStorageAsync();

            try
            {
                this.log.Debug("Fetching record...", () => new { this.storageName, id });
                var response = await this.docDb.ReadAsync(this.client, this.storageConfig, id);

                this.log.Debug("Record fetched", () => new { this.storageName, id });

                var record = StorageRecord.FromDocumentDb(response?.Resource);

                if (record.IsExpired())
                {
                    this.log.Debug("The resource requested has expired, deleting...", () => new { this.storageName, id });
                    await this.TryToDeleteExpiredRecord(id);

                    this.log.Debug("Expired resource deleted", () => new { this.storageName, id });

                    throw new ResourceNotFoundException($"The resource {id} doesn't exist.");
                }

                return(record);
            }
            catch (DocumentClientException e) when(e.StatusCode == HttpStatusCode.NotFound)
            {
                this.log.Debug("The resource requested doesn't exist.", () => new { this.storageName, id });
                throw new ResourceNotFoundException($"The resource {id} doesn't exist.");
            }
        }
        public async Task <bool> ExistsAsync(string id)
        {
            await this.SetupStorageAsync();

            try
            {
                var response = await this.docDb.ReadAsync(this.client, this.storageConfig, id);

                var record = StorageRecord.FromDocumentDb(response?.Resource);

                if (record.IsExpired())
                {
                    this.log.Info("The resource requested has expired.", () => new { this.storageName, id });
                    await this.TryToDeleteExpiredRecord(id);

                    return(false);
                }

                return(true);
            }
            catch (DocumentClientException e) when(e.StatusCode == HttpStatusCode.NotFound)
            {
                return(false);
            }
        }
        public async Task <StorageRecord> CreateAsync(StorageRecord input)
        {
            await this.SetupStorageAsync();

            try
            {
                var record = input.GetDocumentDbRecord();
                record.Touch();
                var response = await this.docDb.CreateAsync(this.client, this.storageConfig, record);

                return(StorageRecord.FromDocumentDb(response?.Resource));
            }
            catch (DocumentClientException e) when(e.StatusCode == HttpStatusCode.Conflict)
            {
                this.log.Info("There is already a resource with the id specified.", () => new { this.storageName, input.Id });
                throw new ConflictingResourceException($"There is already a resource with id = '{input.Id}'.");
            }
        }
        public async Task <StorageRecord> UpsertAsync(StorageRecord input, string eTag)
        {
            await this.SetupStorageAsync();

            try
            {
                var record = input.GetDocumentDbRecord();
                record.Touch();
                var response = await this.docDb.UpsertAsync(this.client, this.storageConfig, record, eTag);

                return(StorageRecord.FromDocumentDb(response?.Resource));
            }
            catch (DocumentClientException e) when(e.StatusCode == HttpStatusCode.PreconditionFailed)
            {
                this.log.Info(
                    "E-Tag mismatch: the resource has been updated by another client.",
                    () => new { this.storageName, input.Id, input.ETag });
                throw new ConflictingResourceException("E-Tag mismatch: the resource has been updated by another client.");
            }
        }
 public async Task <StorageRecord> UpsertAsync(StorageRecord input)
 {
     return(await this.UpsertAsync(input, input.ETag));
 }