Exemplo n.º 1
0
        private async Task HandleChangesAsync(IReadOnlyCollection <Change> changes, CancellationToken cancellationToken)
        {
            // This is needed bc the 'WithStartTime' isn't working for me on the ChangeFeedBuilder
            // This would only be run through the first time after deleting leases container and trying to
            // replay some events.
            if (changes.First().TimeStamp <= _epochStartTime)
            {
                changes = changes.Where(x => x.TimeStamp > _epochStartTime)
                          .ToList().AsReadOnly();
            }

            foreach (var change in changes)
            {
                //  throw new ApplicationException();
                var @event = change.GetEvent(_eventTypeResolver);

                var subscribedProjections = _projections
                                            .Where(projection => projection.IsSubscribedTo(@event));

                foreach (var projection in subscribedProjections)
                {
                    var viewNames = projection.GetViewNames(change.StreamInfo.Id, @event);

                    foreach (var viewName in viewNames)
                    {
                        var handled = false;
                        while (!handled)
                        {
                            var view = await _viewRepository.LoadViewAsync(viewName);

                            // Only update if the LSN of the change is higher than the view. This will ensure
                            // that changes are only processed once.
                            // NOTE: This only works if there's just a single physical partition in Cosmos DB.
                            // TODO: To support multiple partitions we need access to the leases to store
                            // a LSN per lease in the view. This is not yet possible in the V3 SDK.
                            if (view.IsNewerThanCheckpoint(change))
                            {
                                projection.Apply(@event, view);

                                view.UpdateCheckpoint(change);

                                handled = await _viewRepository.SaveViewAsync(viewName, view);
                            }
                            else
                            {
                                // Already handled.
                                handled = true;
                            }

                            if (!handled)
                            {
                                // Oh noos! Somebody changed the view in the meantime, let's wait and try again.
                                await Task.Delay(100);
                            }
                        }
                    }
                }
            }
        }
        private async Task HandleChangesAsync(IReadOnlyCollection <Change> changes, CancellationToken cancellationToken)
        {
            foreach (var change in changes)
            {
                var @event = change.GetEvent(_eventTypeResolver);

                var subscribedProjections = _projections
                                            .Where(projection => projection.IsSubscribedTo(@event)).ToList();

                if (subscribedProjections.Any())
                {
                    _viewRepository = new MSSQLViewRepository(new esdemo3Context());
                }

                foreach (var projection in subscribedProjections)
                {
                    var viewName = projection.GetViewName(change.StreamInfo.Id, @event);

                    var handled = false;
                    while (!handled)
                    {
                        var view = (MSSQLView)await _viewRepository.LoadViewAsync(viewName);

                        // Only update if the LSN of the change is higher than the view. This will ensure
                        // that changes are only processed once.
                        // NOTE: This only works if there's just a single physical partition in Cosmos DB.
                        // TODO: To support multiple partitions we need access to the leases to store
                        // a LSN per lease in the view. This is not yet possible in the V3 SDK.
                        if (view.IsNewerThanCheckpoint(change))
                        {
                            projection.Apply(@event, view);

                            view.UpdateCheckpoint(change);

                            handled = await _viewRepository.SaveViewAsync(viewName, view);
                        }
                        else
                        {
                            // Already handled.
                            handled = true;
                        }

                        if (!handled)
                        {
                            // Oh noos! Somebody changed the view in the meantime, let's wait and try again.
                            await Task.Delay(100);
                        }
                    }
                }
            }
        }
        public async Task ProcessChangesAsync(IChangeFeedObserverContext context, IReadOnlyList <Document> documents, CancellationToken cancellationToken)
        {
            foreach (var document in documents)
            {
                var @event = DeserializeEvent(document);

                foreach (var projection in _projections)
                {
                    if (!projection.CanHandle(@event))
                    {
                        continue;
                    }

                    var streamInfo = document.GetPropertyValue <JObject>("stream");
                    var viewName   = projection.GetViewName(streamInfo["id"].Value <string>(), @event);

                    var handled = false;
                    while (!handled)
                    {
                        var view = await _viewRepository.LoadViewAsync(viewName);

                        if (view.IsNewerThanCheckpoint(context.PartitionKeyRangeId, document))
                        {
                            projection.Apply(@event, view);

                            view.UpdateCheckpoint(context.PartitionKeyRangeId, document);

                            handled = await _viewRepository.SaveViewAsync(viewName, view);
                        }
                        else
                        {
                            // Already handled.
                            handled = true;
                        }

                        if (!handled)
                        {
                            // Oh noos! Somebody changed the view in the meantime, let's wait and try again.
                            await Task.Delay(500);
                        }
                    }
                }
            }
        }