예제 #1
0
        private async Task LoadChangeFeed(Func <IEnumerable <EveneumDocument>, Task> callback, string token = null, CancellationToken cancellationToken = default)
        {
            PartitionKeyRange partitionKeyRange = this.PartitionKey != null ? null : (await this.GetPartitionKeyRanges()).FirstOrDefault();

            var changeFeed = this.Client.CreateDocumentChangeFeedQuery(this.DocumentCollectionUri,
                                                                       new ChangeFeedOptions
            {
                PartitionKeyRangeId = partitionKeyRange?.Id,
                PartitionKey        = this.PartitionKey,
                RequestContinuation = token,
                StartFromBeginning  = true,
                MaxItemCount        = 10000,
            });

            Task callbackTask = null;

            while (changeFeed.HasMoreResults)
            {
                var page = await changeFeed.ExecuteNextAsync <Document>(cancellationToken);

                if (callbackTask != null)
                {
                    await callbackTask;
                }

                callbackTask = callback(page.Select(x => EveneumDocument.Parse(x, this.JsonSerializerSettings)));
            }
        }
예제 #2
0
        public async Task DeleteSnapshots(string streamId, ulong olderThanVersion, CancellationToken cancellationToken = default)
        {
            await this.ReadHeader(streamId, cancellationToken);

            var query = this.Client.CreateDocumentQuery <SnapshotDocument>(this.DocumentCollectionUri, new FeedOptions {
                PartitionKey = this.PartitionKey
            })
                        .Where(x => x.StreamId == streamId)
                        .Where(x => x.DocumentType == DocumentType.Snapshot)
                        .Where(x => x.Version < olderThanVersion)
                        .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(UriFactory.CreateDocumentUri(this.Database, this.Collection, document.Id), new RequestOptions { PartitionKey = this.PartitionKey }, cancellationToken);
                    }
                }
            }
        }
예제 #3
0
        public static async Task <IReadOnlyCollection <EveneumDocument> > All(this IDocumentQuery <Document> query, JsonSerializerSettings jsonSerializerSettings)
        {
            var documents = new List <EveneumDocument>();

            while (query.HasMoreResults)
            {
                var page = await query.ExecuteNextAsync <Document>();

                documents.AddRange(page.Select(x => EveneumDocument.Parse(x, jsonSerializerSettings)));
            }

            return(documents);
        }
예제 #4
0
        public async Task LoadEvents(string sql, Func <IReadOnlyCollection <EventData>, Task> callback, CancellationToken cancellationToken = default)
        {
            var query = this.Client.CreateDocumentQuery <Document>(this.DocumentCollectionUri, sql, new FeedOptions {
                PartitionKey = this.PartitionKey, MaxItemCount = -1
            }).AsDocumentQuery();

            do
            {
                var page = await query.ExecuteNextAsync <Document>(cancellationToken);

                await callback(page.Select(x => EveneumDocument.Parse(x, this.JsonSerializerSettings)).Where(x => !x.Deleted).OfType <EventDocument>().Select(Deserialize).ToList());
            }while (query.HasMoreResults);
        }
예제 #5
0
        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);
                    }
                }
            }
        }
예제 #6
0
        private static async Task <List <TDocument> > Query <TDocument>(IDocumentClient client, string database, string collection, string query, FeedOptions feedOptions)
            where TDocument : EveneumDocument
        {
            var documentQuery = client.CreateDocumentQuery <Document>(UriFactory.CreateDocumentCollectionUri(database, collection), query, feedOptions).AsDocumentQuery();

            var documents = new List <TDocument>();

            do
            {
                var page = await documentQuery.ExecuteNextAsync <Document>();

                documents.AddRange(page.Select(x => EveneumDocument.Parse(x, new JsonSerializerSettings())).OfType <TDocument>());
            }while (documentQuery.HasMoreResults);

            return(documents);
        }
예제 #7
0
        public async Task <Stream?> ReadStream(string streamId, CancellationToken cancellationToken = default)
        {
            if (streamId == null)
            {
                throw new ArgumentNullException(nameof(streamId));
            }

            var sql   = $"SELECT * FROM x WHERE x.{nameof(EveneumDocument.StreamId)} = '{streamId}' ORDER BY x.{nameof(EveneumDocument.SortOrder)} DESC";
            var query = this.Client.CreateDocumentQuery <Document>(this.DocumentCollectionUri, sql, new FeedOptions {
                PartitionKey = this.PartitionKey
            }).AsDocumentQuery();

            var documents     = new List <EveneumDocument>();
            var finishLoading = false;

            do
            {
                var page = await query.ExecuteNextAsync <Document>(cancellationToken);

                foreach (var document in page)
                {
                    var eveneumDoc = EveneumDocument.Parse(document, this.JsonSerializerSettings);

                    if (eveneumDoc is HeaderDocument && eveneumDoc.Deleted)
                    {
                        throw new StreamNotFoundException(streamId);
                    }

                    if (eveneumDoc.Deleted)
                    {
                        continue;
                    }

                    documents.Add(eveneumDoc);

                    if (eveneumDoc is SnapshotDocument)
                    {
                        finishLoading = true;
                        break;
                    }
                }

                if (finishLoading)
                {
                    break;
                }
            }while (query.HasMoreResults);

            if (documents.Count == 0)
            {
                return(null);
            }

            var headerDocument = documents.First() as HeaderDocument;
            var events         = documents.OfType <EventDocument>().Select(this.Deserialize).Reverse().ToArray();
            var snapshot       = documents.OfType <SnapshotDocument>().Select(this.Deserialize).Cast <Snapshot?>().FirstOrDefault();

            object metadata = null;

            if (!string.IsNullOrEmpty(headerDocument.MetadataType))
            {
                metadata = headerDocument.Metadata.ToObject(this.TypeCache.Resolve(headerDocument.MetadataType), this.JsonSerializer);
            }

            return(new Stream(streamId, headerDocument.Version, metadata, events, snapshot));
        }