Beispiel #1
0
        private void NotifySubscribers(string type, BlittableJsonReaderObject value, List <DatabaseConnectionState> states)
        {
            switch (type)
            {
            case nameof(DocumentChange):
                var documentChange = DocumentChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(documentChange);
                }
                break;

            case nameof(IndexChange):
                var indexChange = IndexChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(indexChange);
                }
                break;

            case nameof(OperationStatusChange):
                var operationStatusChange = OperationStatusChange.FromJson(value, _conventions);
                foreach (var state in states)
                {
                    state.Send(operationStatusChange);
                }
                break;

            default:
                throw new NotSupportedException(type);
            }
        }
Beispiel #2
0
        private void RaiseNotifications(OperationStatusChange change, Operation operation)
        {
            var operationChanged = OperationChanged.Create(_name, change.OperationId, operation.Description, change.State, operation.Killable);

            operation.NotifyCenter(operationChanged, x => _notificationCenter.Add(x));

            _changes?.RaiseNotifications(change);
        }
Beispiel #3
0
        public void RaiseNotifications(OperationStatusChange operationStatusChange)
        {
            OnOperationStatusChange?.Invoke(operationStatusChange);

            foreach (var connection in Connections)
            {
                connection.Value.SendOperationStatusChangeNotification(operationStatusChange);
            }
        }
        public void SendOperationStatusChangeNotification(OperationStatusChange change)
        {
            if (_watchAllOperations > 0)
            {
                Send(change);
                return;
            }

            if (_matchingOperations.Contains(change.OperationId))
            {
                Send(change);
            }
        }
Beispiel #5
0
        private void NotifySubscribers(string type, BlittableJsonReaderObject value, List <DatabaseConnectionState> states)
        {
            switch (type)
            {
            case nameof(DocumentChange):
                var documentChange = DocumentChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(documentChange);
                }
                break;

            case nameof(CounterChange):
                var counterChange = CounterChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(counterChange);
                }
                break;

            case nameof(IndexChange):
                var indexChange = IndexChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(indexChange);
                }
                break;

            case nameof(OperationStatusChange):
                var operationStatusChange = OperationStatusChange.FromJson(value, _conventions);
                foreach (var state in states)
                {
                    state.Send(operationStatusChange);
                }
                break;

            case nameof(TopologyChange):
                var topologyChange = TopologyChange.FromJson(value);
                _requestExecutor?.UpdateTopologyAsync(new ServerNode
                {
                    Url      = topologyChange.Url,
                    Database = topologyChange.Database
                }, 0, true, "topology-change-notification").ConfigureAwait(false);
                break;

            default:
                throw new NotSupportedException(type);
            }
        }
        private void Send(OperationStatusChange change)
        {
            var value = new DynamicJsonValue
            {
                ["Type"]  = nameof(OperationStatusChange),
                ["Value"] = change.ToJson()
            };

            if (_disposeToken.IsCancellationRequested == false)
            {
                _sendQueue.Enqueue(new ChangeValue
                {
                    ValueToSend = value,
                    AllowSkip   = false
                });
            }
        }
Beispiel #7
0
        private void NotifySubscribers(string type, BlittableJsonReaderObject value, List <DatabaseConnectionState> states)
        {
            switch (type)
            {
            case nameof(DocumentChange):
                var documentChange = DocumentChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(documentChange);
                }
                break;

            case nameof(CounterChange):
                var counterChange = CounterChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(counterChange);
                }
                break;

            case nameof(TimeSeriesChange):
                var timeSeriesChange = TimeSeriesChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(timeSeriesChange);
                }
                break;

            case nameof(IndexChange):
                var indexChange = IndexChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(indexChange);
                }
                break;

            case nameof(OperationStatusChange):
                var operationStatusChange = OperationStatusChange.FromJson(value);
                foreach (var state in states)
                {
                    state.Send(operationStatusChange);
                }
                break;

            case nameof(TopologyChange):
                var topologyChange = TopologyChange.FromJson(value);

                var requestExecutor = _requestExecutor;
                if (requestExecutor != null)
                {
                    var node = new ServerNode
                    {
                        Url      = topologyChange.Url,
                        Database = topologyChange.Database
                    };

                    requestExecutor.UpdateTopologyAsync(new RequestExecutor.UpdateTopologyParameters(node)
                    {
                        TimeoutInMs = 0,
                        ForceUpdate = true,
                        DebugTag    = "topology-change-notification"
                    }).ConfigureAwait(false);
                }
                break;

            default:
                throw new NotSupportedException(type);
            }
        }
Beispiel #8
0
        public Task <IOperationResult> AddOperation(
            DocumentDatabase database,
            string description,
            OperationType operationType,
            Func <Action <IOperationProgress>, Task <IOperationResult> > taskFactory,
            long id,
            IOperationDetailedDescription detailedDescription = null,
            OperationCancelToken token = null)
        {
            var operationState = new OperationState
            {
                Status = OperationStatus.InProgress
            };

            var notification = new OperationStatusChange
            {
                OperationId = id,
                State       = operationState
            };

            var operationDescription = new OperationDescription
            {
                Description         = description,
                TaskType            = operationType,
                StartTime           = SystemTime.UtcNow,
                DetailedDescription = detailedDescription
            };

            var operation = new Operation
            {
                Database    = database,
                Id          = id,
                Description = operationDescription,
                Token       = token,
                State       = operationState
            };

            object locker = new object();

            Monitor.Enter(locker);
            try
            {
                operation.Task = Task.Run(() => taskFactory(ProgressNotification));
                operation.Task.ContinueWith(ContinuationFunction);
                _active.TryAdd(id, operation);

                if (token == null)
                {
                    return(operation.Task);
                }

                return(operation.Task.ContinueWith(t =>
                {
                    token.Dispose();
                    return t;
                }).Unwrap());
            }
            finally
            {
                Monitor.Exit(locker);
            }

            void ContinuationFunction(Task <IOperationResult> taskResult)
            {
                operationDescription.EndTime = SystemTime.UtcNow;
                operationState.Progress      = null;

                if (taskResult.IsCanceled)
                {
                    operationState.Result = null;
                    operationState.Status = OperationStatus.Canceled;
                }
                else if (taskResult.IsFaulted)
                {
                    var innerException = taskResult.Exception.ExtractSingleInnerException();

                    var isConflict = innerException is DocumentConflictException || innerException is ConcurrencyException;
                    var status     = isConflict ? HttpStatusCode.Conflict : HttpStatusCode.InternalServerError;

                    var shouldPersist = false;

                    switch (operationType)
                    {
                    case OperationType.DatabaseExport:
                    case OperationType.DatabaseImport:
                        shouldPersist = true;
                        break;
                    }

                    operationState.Result = new OperationExceptionResult(innerException, status, shouldPersist);
                    operationState.Status = OperationStatus.Faulted;
                }
                else
                {
                    operationState.Result = taskResult.Result;
                    operationState.Status = OperationStatus.Completed;
                }

                if (Monitor.TryEnter(locker) == false)
                {
                    // adding of operation still didn't finish, just exit
                    RaiseNotifications(notification, operation);
                    return;
                }

                try
                {
                    if (_active.TryGetValue(id, out Operation completed))
                    {
                        completed.SetCompleted();
                        // add to completed items before removing from active ones to ensure an operation status is accessible all the time
                        _completed.TryAdd(id, completed);
                        _active.TryRemove(id, out completed);
                    }

                    RaiseNotifications(notification, operation);
                }
                finally
                {
                    Monitor.Exit(locker);
                }
            }

            void ProgressNotification(IOperationProgress progress)
            {
                notification.State.Progress = progress;
                RaiseNotifications(notification, operation);
            }
        }
Beispiel #9
0
        public Task <IOperationResult> AddOperation(
            DocumentDatabase database,
            string description,
            OperationType operationType,
            Func <Action <IOperationProgress>, Task <IOperationResult> > taskFactory,
            long id,
            OperationCancelToken token = null)
        {
            var operationState = new OperationState
            {
                Status = OperationStatus.InProgress
            };

            var notification = new OperationStatusChange
            {
                OperationId = id,
                State       = operationState
            };

            var operationDescription = new OperationDescription
            {
                Description = description,
                TaskType    = operationType,
                StartTime   = SystemTime.UtcNow
            };

            var operation = new Operation
            {
                Database    = database,
                Id          = id,
                Description = operationDescription,
                Token       = token,
                State       = operationState
            };

            void ProgressNotification(IOperationProgress progress)
            {
                notification.State.Progress = progress;
                RaiseNotifications(notification, operation);
            }

            operation.Task = taskFactory(ProgressNotification);

            operation.Task.ContinueWith(taskResult =>
            {
                operationDescription.EndTime = SystemTime.UtcNow;
                operationState.Progress      = null;

                if (taskResult.IsCanceled)
                {
                    operationState.Result = null;
                    operationState.Status = OperationStatus.Canceled;
                }
                else if (taskResult.IsFaulted)
                {
                    var innerException = taskResult.Exception.ExtractSingleInnerException();

                    var isConflict = innerException is DocumentConflictException || innerException is ConcurrencyException;
                    var status     = isConflict ? HttpStatusCode.Conflict : HttpStatusCode.InternalServerError;

                    var shouldPersist = false;

                    switch (operationType)
                    {
                    case OperationType.DatabaseExport:
                    case OperationType.DatabaseImport:
                        shouldPersist = true;
                        break;
                    }

                    operationState.Result = new OperationExceptionResult(innerException, status, shouldPersist);
                    operationState.Status = OperationStatus.Faulted;
                }
                else
                {
                    operationState.Result = taskResult.Result;
                    operationState.Status = OperationStatus.Completed;
                }

                if (_active.TryGetValue(id, out Operation completed))
                {
                    // add to completed items before removing from active ones to ensure an operation status is accessible all the time
                    _completed.TryAdd(id, completed);
                    _active.TryRemove(id, out completed);
                }

                RaiseNotifications(notification, operation);
            });

            _active.TryAdd(id, operation);

            return(operation.Task);
        }
Beispiel #10
0
 void OnUpdatedOperationStatus(bool inProgress)
 {
     OperationStatusChange?.Invoke(inProgress);
 }
 public void Send(OperationStatusChange operationStatusChange)
 {
     OnOperationStatusChangeNotification?.Invoke(operationStatusChange);
 }