public async Task Add(DispatchStreamJob job, CancellationToken token) { var table = await _table.GetOrCreate(); var entity = new DispatchStreamRecoveryJobTableEntity { PartitionKey = "StreamsToDispatchOnRecovery", RowKey = $"R^{job.StreamId.Value}^{job.SessionId.Value}", StreamId = job.StreamId.Value }; var operation = TableOperation.Insert(entity); await table.ExecuteAsync(operation, token); }
public async Task <CurrentPageIndexTableEntity> Get(CancellationToken token) { var table = await _table.GetOrCreate(); var query = table.CreateQuery <CurrentPageIndexTableEntity>() .Where(x => x.PartitionKey == "Indexes") .Where(x => x.RowKey == "CurrentPageIndex") .Take(1) .AsTableQuery(); CurrentPageIndexTableEntity entity; do { token.ThrowIfCancellationRequested(); var segment = await table.ExecuteQuerySegmentedAsync(query, null, token); entity = segment.SingleOrDefault() ?? await Create(table, token); } while (entity == null); return(entity); }
public async Task Dispatch(List <EventToDispatchRecordTableEntity> events, CancellationToken token) { var table = await _table.GetOrCreate(); CurrentPageIndexTableEntity pageIndex; EventStorePageInfoTableEntity pageInfo; var eventsCount = events.Count; var eventIndex = 0L; do { token.ThrowIfCancellationRequested(); pageIndex = await _provideCurrentPageIndexes.Get(token); var partitionKey = $"P^{pageIndex.Index:x16}"; var queryCurrentPageInfo = table.CreateQuery <EventStorePageInfoTableEntity>() .Where(x => x.PartitionKey == partitionKey) .Where(x => x.RowKey == PageInfoRowKey) .Take(1) .AsTableQuery(); var result = await table.ExecuteQuerySegmentedAsync(queryCurrentPageInfo, null, token); pageInfo = result.SingleOrDefault(); if (pageInfo == null) { eventIndex = 0; pageInfo = new EventStorePageInfoTableEntity { PartitionKey = partitionKey, RowKey = PageInfoRowKey, NextIndex = eventsCount, NextPageIndex = 0 }; if (pageInfo.NextIndex > _pageSize) { pageInfo.NextPageIndex = pageIndex.Index + 1; } var operation = TableOperation.Insert(pageInfo); try { await table.ExecuteAsync(operation, token); } catch (StorageException e) { if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.Conflict) { throw; } pageInfo = null; } } else { if (pageInfo.NextPageIndex == UndefinedNextPageIndex) { eventIndex = pageInfo.NextIndex; pageInfo.NextIndex += eventsCount; if (pageInfo.NextIndex > _pageSize) { pageInfo.NextPageIndex = pageIndex.Index + 1; } var operation = TableOperation.Replace(pageInfo); try { await table.ExecuteAsync(operation, token); } catch (StorageException e) { if (e.RequestInformation.HttpStatusCode != (int)HttpStatusCode.PreconditionFailed) { throw; } pageInfo = null; } } else { pageIndex.Index = pageInfo.NextPageIndex; await _updateCurrentPageIndexes.TryUpdate(pageIndex, token); pageInfo = null; } } } while (pageInfo == null); var batchOperation = new TableBatchOperation(); foreach (var @event in events) { var record = new EventStoreRecordTableEntity { PartitionKey = $"P^{pageIndex.Index:x16}", RowKey = $"E^{eventIndex:x16}", PageIndex = pageIndex.Index, RowIndex = eventIndex, AggregateType = @event.AggregateType, BucketId = @event.BucketId, AggregateId = @event.AggregateId, SessionId = @event.SessionId, Version = @event.Version, Created = @event.Created, Type = @event.Type, Payload = @event.Payload }; eventIndex++; batchOperation.InsertOrReplace(record); } await table.ExecuteBatchAsync(batchOperation, token); }