public async Task WriteToStream(string streamId, EventData[] events, ulong?expectedVersion = null, object metadata = null, CancellationToken cancellationToken = default) { HeaderDocument header; // Existing stream if (expectedVersion.HasValue) { header = await this.ReadHeader(streamId, cancellationToken); if (header.Version != expectedVersion) { throw new OptimisticConcurrencyException(streamId, expectedVersion.Value, header.Version); } } else { header = new HeaderDocument { Partition = this.Partition, StreamId = streamId }; } header.Version += (ulong)events.Length; if (metadata != null) { header.Metadata = JToken.FromObject(metadata, this.JsonSerializer); header.MetadataType = metadata.GetType().AssemblyQualifiedName; } if (!expectedVersion.HasValue) { try { await this.Client.CreateDocumentAsync(this.DocumentCollectionUri, header, new RequestOptions { PartitionKey = this.PartitionKey }, disableAutomaticIdGeneration : true, cancellationToken); } catch (DocumentClientException ex) when(ex.Error.Code == nameof(System.Net.HttpStatusCode.Conflict)) { throw new StreamAlreadyExistsException(streamId); } } else { await this.Client.ReplaceDocumentAsync(this.HeaderDocumentUri(streamId), header, new RequestOptions { PartitionKey = this.PartitionKey, AccessCondition = new AccessCondition { Type = AccessConditionType.IfMatch, Condition = header.ETag } }, cancellationToken); } var eventDocuments = (events ?? Enumerable.Empty <EventData>()).Select(@event => this.Serialize(@event, streamId)); foreach (var eventDocument in eventDocuments) { await this.Client.CreateDocumentAsync(this.DocumentCollectionUri, eventDocument, new RequestOptions { PartitionKey = this.PartitionKey }, disableAutomaticIdGeneration : true, cancellationToken); } }
public async Task DeleteStream(string streamId, ulong expectedVersion, CancellationToken cancellationToken = default) { var header = new HeaderDocument { Partition = this.Partition, StreamId = streamId, Version = expectedVersion }; var existingHeader = await this.ReadHeader(streamId, cancellationToken); if (existingHeader.Deleted) { throw new StreamNotFoundException(streamId); } if (existingHeader.Version != expectedVersion) { throw new OptimisticConcurrencyException(streamId, expectedVersion, existingHeader.Version); } string etag = existingHeader.ETag; var query = this.Client.CreateDocumentQuery <EveneumDocument>(this.DocumentCollectionUri, new FeedOptions { PartitionKey = this.PartitionKey }) .Where(x => x.StreamId == streamId) .AsDocumentQuery(); while (query.HasMoreResults) { var page = await query.ExecuteNextAsync <Document>(cancellationToken); foreach (var document in page) { if (this.DeleteMode == DeleteMode.SoftDelete) { var doc = EveneumDocument.Parse(document, this.JsonSerializerSettings); doc.Deleted = true; await this.Client.UpsertDocumentAsync(this.DocumentCollectionUri, doc, new RequestOptions { PartitionKey = this.PartitionKey }, disableAutomaticIdGeneration : true, cancellationToken); } else { await this.Client.DeleteDocumentAsync(document.SelfLink, new RequestOptions { PartitionKey = this.PartitionKey }, cancellationToken); } } } }
private Uri HeaderDocumentUri(string streamId) => UriFactory.CreateDocumentUri(this.Database, this.Collection, HeaderDocument.GenerateId(streamId));
public ScriptManager() { Header = new HeaderDocument(); Items = new ScriptCollection(); }