示例#1
0
        private void RequestTeams(string recipientId)
        {
            if (_teamsToInitialize.IsEmpty)
            {
                EndInitialization();
            }
            else
            {
                var lockObject         = new object();
                var serviceBusMessages = ServiceBus.ObservableMessages.Where(m => !string.Equals(m.SenderNodeId, NodeId, StringComparison.OrdinalIgnoreCase));
                serviceBusMessages = serviceBusMessages.Synchronize(lockObject);

                var lastMessageTime = PlanningPoker.DateTimeProvider.UtcNow;

                var initTeamActions = serviceBusMessages.Where(m => m.MessageType == NodeMessageType.InitializeTeam)
                                      .TakeWhile(m => !_teamsToInitialize.IsEmpty)
                                      .Select(m => new Action(() =>
                {
                    lastMessageTime = PlanningPoker.DateTimeProvider.UtcNow;
                    ProcessInitializeTeamMessage(m);
                }));
                var messageTimeoutActions = Observable.Interval(TimeSpan.FromSeconds(1.0)).Synchronize(lockObject)
                                            .SelectMany(i => lastMessageTime + Configuration.InitializationMessageTimeout < PlanningPoker.DateTimeProvider.UtcNow ? Observable.Throw <Action>(new TimeoutException()) : Observable.Empty <Action>());

                void RetryRequestTeamList(Exception ex)
                {
                    _logger?.LogWarning(Resources.Warning_RetryRequestTeamList, NodeId);
                    RequestTeamList();
                }

                initTeamActions.Merge(messageTimeoutActions)
                .Subscribe(a => a(), RetryRequestTeamList);

                var requestTeamsMessage = new NodeMessage(NodeMessageType.RequestTeams)
                {
                    RecipientNodeId = recipientId,
                    Data            = _teamsToInitialize.Values.ToArray()
                };
                SendNodeMessage(requestTeamsMessage);
            }
        }
示例#2
0
 public void SinglePredicate_Empty()
 {
     ReactiveAssert.Throws <InvalidOperationException>(() => Observable.Empty <int>().Single(_ => true));
 }
示例#3
0
 public override IObservable <int> ReadRssi() => Observable.Empty <int>();
示例#4
0
 public IObservable <IResponse> GetResponses(IRequest request)
 {
     return(Observable.Empty <IResponse>());
 }
示例#5
0
 public void Wait_Empty()
 {
     ReactiveAssert.Throws <InvalidOperationException>(() => Observable.Empty <int>().Wait());
 }
示例#6
0
 public static IObservable <T> OnErrorResumeEmpty <T>(this IObservable <T> observable)
 => observable.OnErrorResumeNext(Observable.Empty <T>());
示例#7
0
 public virtual IObservable <int> ReadRssi() => Observable.Empty <int>();
示例#8
0
 public IObservable <IAdapter> FindAdapters() => Observable.Empty <IAdapter>();
        public PullRequestListViewModel(
            IModelServiceFactory modelServiceFactory,
            IPackageSettings settings,
            IPullRequestSessionManager sessionManager,
            IVisualStudioBrowser visualStudioBrowser)
        {
            Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory));
            Guard.ArgumentNotNull(settings, nameof(settings));
            Guard.ArgumentNotNull(sessionManager, nameof(sessionManager));
            Guard.ArgumentNotNull(visualStudioBrowser, nameof(visualStudioBrowser));

            constructing             = true;
            this.modelServiceFactory = modelServiceFactory;
            this.settings            = settings;
            this.visualStudioBrowser = visualStudioBrowser;

            Title = Resources.PullRequestsNavigationItemText;

            States = new List <PullRequestState> {
                new PullRequestState {
                    IsOpen = true, Name = "Open"
                },
                new PullRequestState {
                    IsOpen = false, Name = "Closed"
                },
                new PullRequestState {
                    Name = "All"
                }
            };

            trackingAuthors = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(),
                                                                OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare);
            trackingAssignees = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(),
                                                                  OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare);
            trackingAuthors.Subscribe();
            trackingAssignees.Subscribe();

            Authors   = trackingAuthors.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAuthor));
            Assignees = trackingAssignees.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAssignee));

            CreatePullRequests();

            this.WhenAny(x => x.SelectedState, x => x.Value)
            .Where(x => PullRequests != null)
            .Subscribe(s => UpdateFilter(s, SelectedAssignee, SelectedAuthor, SearchQuery));

            this.WhenAny(x => x.SelectedAssignee, x => x.Value)
            .Where(x => PullRequests != null && x != EmptyUser)
            .Subscribe(a => UpdateFilter(SelectedState, a, SelectedAuthor, SearchQuery));

            this.WhenAny(x => x.SelectedAuthor, x => x.Value)
            .Where(x => PullRequests != null && x != EmptyUser)
            .Subscribe(a => UpdateFilter(SelectedState, SelectedAssignee, a, SearchQuery));

            this.WhenAny(x => x.SearchQuery, x => x.Value)
            .Where(x => PullRequests != null)
            .Subscribe(f => UpdateFilter(SelectedState, SelectedAssignee, SelectedAuthor, f));

            this.WhenAnyValue(x => x.SelectedRepository)
            .Skip(1)
            .Subscribe(_ => ResetAndLoad());

            OpenPullRequest = ReactiveCommand.Create();
            OpenPullRequest.Subscribe(DoOpenPullRequest);
            CreatePullRequest = ReactiveCommand.Create();
            CreatePullRequest.Subscribe(_ => DoCreatePullRequest());

            OpenPullRequestOnGitHub = ReactiveCommand.Create();
            OpenPullRequestOnGitHub.Subscribe(x => DoOpenPullRequestOnGitHub((int)x));

            // Get the current pull request session and the selected repository. When the session's
            // repository is the same as our selected repository set CheckedOutPullRequest to the
            // current session's model, so that the checked out PR can be highlighted.
            Observable.CombineLatest(
                sessionManager.WhenAnyValue(x => x.CurrentSession),
                this.WhenAnyValue(x => x.SelectedRepository),
                (s, r) => new { Session = s, Repository = r })
            .Subscribe(x =>
            {
                CheckedOutPullRequest = x.Session?.RepositoryOwner == x.Repository?.Owner ?
                                        x.Session?.PullRequest : null;
            });

            constructing = false;
        }
        private static IObservableParser <TSource, IObservable <TResult> > AtLeast <TSource, TSeparator, TResult>(
            this IObservableParser <TSource, TResult> parser,
            string name,
            int count,
            int maximum = -1,
            IObservableParser <TSource, TSeparator> separator = null,
            bool nonGreedy = false)
        {
            Contract.Requires(parser != null);
            Contract.Requires(!string.IsNullOrEmpty(name));
            Contract.Requires(count >= 0);
            Contract.Requires(maximum == -1 || maximum >= count);
            Contract.Requires(maximum != 0);
            Contract.Ensures(Contract.Result <IObservableParser <TSource, IObservable <TResult> > >() != null);

            // TODO: Update this method to properly support multi-result parsers.

            /* The current implementation just uses Math.Max for the lengths and aggregates all of the results into a single list.
             * The correct behavior is more like a SelectMany query, so consider using the new SelectMany overload that AllObservableParser uses.
             */

            /* This method is optimized to prevent stack overflows due to two factors: recursion and using Skip to move the source cursor.
             *
             * The previous implementation used recursive calls to NoneOrMore, in which there was a linear relationship between the number
             * of stack frames and the number of elements in the input sequence.  As an input sequence grew and the parser continued matching
             * elements, the number of calls to the Skip operator (via the Remainder extension) grew linearly, and so did the number of branches
             * due to NoneOrMore using the Or operator, which not only added the Or operator to the stack but added all of the calls to the
             * quantified parser between the stack frames that Or added, for every subsequent element in the sequence that the parser matched.
             */
            return(parser.Yield <TSource, TResult, IObservable <TResult> >(
                       name,
                       (source, observer) =>
            {
                Contract.Requires(source.IsForwardOnly);

                var branch = source.Branch();

                var list = new List <TResult>();

                int total = 0;
                int totalLength = 0;

                Action onCompleted = () =>
                {
                    if (total >= count)
                    {
                        observer.OnNext(new ParseResult <IObservable <TResult> >(list.ToObservable(Scheduler.Immediate), totalLength));
                    }

                    observer.OnCompleted();
                };

                var subscription = new SerialDisposable();

                Func <IDisposable> start = () =>
                                           Scheduler.Immediate.Schedule(self =>
                {
                    bool hasResult = false;
                    bool hasSeparatorResult = false;

                    int length = 0;
                    int separatorLength = 0;

                    Action currentCompleted = () =>
                    {
                        if (hasResult)
                        {
                            totalLength += length + separatorLength;

                            if (total < (maximum == -1 ? count : maximum))
                            {
                                total++;
                            }

                            if (total != maximum && (separator == null || hasSeparatorResult))
                            {
                                if (nonGreedy && total >= count)
                                {
                                    var lookAhead = new LookAheadParseResult <IObservable <TResult> >(list.ToObservable(Scheduler.Immediate), totalLength);

                                    subscription.SetDisposableIndirectly(() => new CompositeDisposable(
                                                                             lookAhead,
                                                                             lookAhead.Subscribe(success =>
                                    {
                                        if (success)
                                        {
                                            onCompleted();
                                        }
                                        else
                                        {
                                            self();
                                        }
                                    })));

                                    observer.OnNext(lookAhead);
                                    return;
                                }
                                else
                                {
                                    self();
                                    return;
                                }
                            }
                        }

                        onCompleted();
                    };

                    subscription.SetDisposableIndirectly(() =>
                                                         parser.Parse(branch).Subscribe(
                                                             result =>
                    {
                        hasResult = true;
                        length = Math.Max(length, result.Length);

                        list.Add(result.Value);
                    },
                                                             observer.OnError,
                                                             () =>
                    {
                        branch.Move(length);

                        if (separator == null)
                        {
                            currentCompleted();
                        }
                        else
                        {
                            subscription.SetDisposableIndirectly(() =>
                                                                 separator.Parse(branch).Subscribe(
                                                                     separatorResult =>
                            {
                                hasSeparatorResult = true;
                                separatorLength = Math.Max(separatorLength, separatorResult.Length);
                            },
                                                                     observer.OnError,
                                                                     () =>
                            {
                                branch.Move(separatorLength);

                                currentCompleted();
                            }));
                        }
                    }));
                });

                if (nonGreedy && count == 0)
                {
                    var startSubscription = new SingleAssignmentDisposable();

                    var lookAhead = new LookAheadParseResult <IObservable <TResult> >(Observable.Empty <TResult>(), length: 0);

                    var lookAheadSubscription = lookAhead.Subscribe(success =>
                    {
                        if (success)
                        {
                            onCompleted();
                        }
                        else
                        {
                            startSubscription.Disposable = start();
                        }
                    });

                    observer.OnNext(lookAhead);

                    return new CompositeDisposable(branch, subscription, lookAhead, lookAheadSubscription, startSubscription);
                }
                else
                {
                    var startSubscription = start();

                    return new CompositeDisposable(branch, subscription, startSubscription);
                }
            }));
        }
示例#11
0
 public IObservable <IGpsReading> GetLastReading()
 => Observable.Empty <IGpsReading>();
示例#12
0
        public void Empty()
        {
            var material = Observable.Empty <Unit>().Materialize().ToArray().Wait();

            material.Is(Notification.CreateOnCompleted <Unit>());
        }
示例#13
0
        public void Subscribe_ArgumentChecking()
        {
            var someObservable = Observable.Empty <int>();

            ReactiveAssert.Throws <ArgumentNullException>(() => ObservableExtensions.Subscribe <int>(default));
示例#14
0
 public IObservable <DRMDescription> SetDrmConfiguration()
 {
     return(Observable.Empty <DRMDescription>());
 }
 public void Subscribe_OnNext_Empty()
 {
     Observable.Empty <int>(Scheduler.Immediate).Subscribe((int _) => { Assert.Fail(); });
 }
示例#16
0
 public Node(string id)
     : this(id, null, _ => Observable.Empty <Leaf>())
 {
 }
示例#17
0
 public static IObservable <T> WhereAsync <T>(this IObservable <T> observable, Func <T, IObservable <bool> > asyncPredicate)
 => observable.SelectMany(item =>
                          asyncPredicate(item)
                          .SingleAsync()
                          .SelectMany(include => include ? Observable.Return(item) : Observable.Empty <T>()));
示例#18
0
        public void Synchronize_ArgumentChecking()
        {
            var someObservable = Observable.Empty <int>();

            ReactiveAssert.Throws <ArgumentNullException>(() => Observable.Synchronize <int>(default));
示例#19
0
 public virtual IObservable <BleException> WhenConnectionFailed() => Observable.Empty <BleException>();
示例#20
0
 public IObservable <TReturn> HandleError <TException, TReturn>(TException e) where TException : Exception
 {
     return(Observable.Empty <TReturn>());
 }
        public IObservable <ElasticsearchMessage> Start(string[] additionalSettings = null)
        {
            if (!this.RunningIntegrations)
            {
                return(Observable.Empty <ElasticsearchMessage>());
            }

            this.Stop();
            var timeout = TimeSpan.FromMinutes(1);

#if DOTNETCORE
            var handle = new Signal(false);
#else
            var handle = new ManualResetEvent(false);
#endif

            if (_doNotSpawnIfAlreadyRunning)
            {
                var client    = TestClient.GetClient();
                var alreadyUp = client.RootNodeInfo();
                if (alreadyUp.IsValid)
                {
                    var checkPlugins = client.CatPlugins();

                    if (checkPlugins.IsValid)
                    {
                        foreach (var supportedPlugin in SupportedPlugins)
                        {
                            if (!checkPlugins.Records.Any(r => r.Component.Equals(supportedPlugin.Key)))
                            {
                                throw new Exception($"Already running elasticsearch does not have supported plugin {supportedPlugin.Key} installed.");
                            }
                        }

                        this.Started = true;
                        this.Port    = 9200;
                        this.Info    = new ElasticsearchNodeInfo(alreadyUp.Version.Number, null, alreadyUp.Version.LuceneVersion);
                        this._blockingSubject.OnNext(handle);
                        if (!handle.WaitOne(timeout, true))
                        {
                            throw new Exception($"Could not launch tests on already running elasticsearch within {timeout}");
                        }

                        return(Observable.Empty <ElasticsearchMessage>());
                    }
                }
            }

            var settingMarker = this.VersionInfo.ParsedVersion.Major >= 5 ? "-E " : "-D";

            var settings = new []
            {
                $"es.cluster.name=\"{this.ClusterName}\"",
                $"es.node.name={this.NodeName}",
                $"es.path.repo=\"{this.RepositoryPath}\"",
                $"es.script.inline=true",
                $"es.script.indexed=true",
                $"es.node.attr.testingcluster=true"
            }.Concat(additionalSettings ?? Enumerable.Empty <string>())
            .Select(s => $"{settingMarker}{s}");

            this._process = new ObservableProcess(this.Binary, settings.ToArray());

            var observable = Observable.Using(() => this._process, process => process.Start())
                             .Select(consoleLine => new ElasticsearchMessage(consoleLine));
            this._processListener = observable.Subscribe(onNext: s => HandleConsoleMessage(s, handle));

            if (!handle.WaitOne(timeout, true))
            {
                this.Stop();
                throw new Exception($"Could not start elasticsearch within {timeout}");
            }

            return(observable);
        }
        private async Task ConnectAsync(CancellationToken token)
        {
            try
            {
                await BackOff();

                _stateSubject.OnNext(GraphQLWebsocketConnectionState.Connecting);
                Debug.WriteLine($"opening websocket {_clientWebSocket.GetHashCode()} (thread {Thread.CurrentThread.ManagedThreadId})");
                await _clientWebSocket.ConnectAsync(_webSocketUri, token);

                _stateSubject.OnNext(GraphQLWebsocketConnectionState.Connected);
                Debug.WriteLine($"connection established on websocket {_clientWebSocket.GetHashCode()}, invoking Options.OnWebsocketConnected()");
                await(Options.OnWebsocketConnected?.Invoke(_client) ?? Task.CompletedTask);
                Debug.WriteLine($"invoking Options.OnWebsocketConnected() on websocket {_clientWebSocket.GetHashCode()}");
                _connectionAttempt = 1;

                // create receiving observable
                _incomingMessages = Observable
                                    .Defer(() => GetReceiveTask().ToObservable())
                                    .Repeat()
                                    // complete sequence on OperationCanceledException, this is triggered by the cancellation token on disposal
                                    .Catch <WebsocketMessageWrapper, OperationCanceledException>(exception => Observable.Empty <WebsocketMessageWrapper>())
                                    .Publish();

                // subscribe maintenance
                var maintenanceSubscription = _incomingMessages.Subscribe(_ => { }, ex =>
                {
                    Debug.WriteLine($"incoming message stream {_incomingMessages.GetHashCode()} received an error: {ex}");
                    _exceptionSubject.OnNext(ex);
                    _incomingMessagesConnection?.Dispose();
                    _stateSubject.OnNext(GraphQLWebsocketConnectionState.Disconnected);
                },
                                                                          () =>
                {
                    Debug.WriteLine($"incoming message stream {_incomingMessages.GetHashCode()} completed");
                    _incomingMessagesConnection?.Dispose();
                    _stateSubject.OnNext(GraphQLWebsocketConnectionState.Disconnected);
                });


                // connect observable
                var connection = _incomingMessages.Connect();
                Debug.WriteLine($"new incoming message stream {_incomingMessages.GetHashCode()} created");

                _incomingMessagesConnection = new CompositeDisposable(maintenanceSubscription, connection);
            }
            catch (Exception e)
            {
                _stateSubject.OnNext(GraphQLWebsocketConnectionState.Disconnected);
                _exceptionSubject.OnNext(e);
                throw;
            }
        }
示例#23
0
 //inform the system that the enum has changed
 protected override IObservable <object> GetEntriesChangedObservable()
 {
     return(Observable.Empty <object>());
 }
        /// <summary>
        /// Create a new subscription stream
        /// </summary>
        /// <typeparam name="TResponse">the response type</typeparam>
        /// <param name="request">the <see cref="GraphQLRequest"/> to start the subscription</param>
        /// <param name="exceptionHandler">Optional: exception handler for handling exceptions within the receive pipeline</param>
        /// <returns>a <see cref="IObservable{TResponse}"/> which represents the subscription</returns>
        public IObservable <GraphQLResponse <TResponse> > CreateSubscriptionStream <TResponse>(GraphQLRequest request, Action <Exception> exceptionHandler = null) =>
        Observable.Defer(() =>
                         Observable.Create <GraphQLResponse <TResponse> >(async observer =>
        {
            Debug.WriteLine($"Create observable thread id: {Thread.CurrentThread.ManagedThreadId}");
            await _client.Options.PreprocessRequest(request, _client);
            var startRequest = new GraphQLWebSocketRequest
            {
                Id      = Guid.NewGuid().ToString("N"),
                Type    = GraphQLWebSocketMessageType.GQL_START,
                Payload = request
            };
            var closeRequest = new GraphQLWebSocketRequest
            {
                Id   = startRequest.Id,
                Type = GraphQLWebSocketMessageType.GQL_STOP
            };
            var initRequest = new GraphQLWebSocketRequest
            {
                Id      = startRequest.Id,
                Type    = GraphQLWebSocketMessageType.GQL_CONNECTION_INIT,
                Payload = _client.WebSocketHeaders.Count > 0 ? _client.WebSocketHeaders : null
            };

            var observable = Observable.Create <GraphQLResponse <TResponse> >(o =>
                                                                              IncomingMessageStream
                                                                              // ignore null values and messages for other requests
                                                                              .Where(response => response != null && response.Id == startRequest.Id)
                                                                              .Subscribe(response =>
            {
                // terminate the sequence when a 'complete' message is received
                if (response.Type == GraphQLWebSocketMessageType.GQL_COMPLETE)
                {
                    Debug.WriteLine($"received 'complete' message on subscription {startRequest.Id}");
                    o.OnCompleted();
                    return;
                }

                // post the GraphQLResponse to the stream (even if a GraphQL error occurred)
                Debug.WriteLine($"received payload on subscription {startRequest.Id} (thread {Thread.CurrentThread.ManagedThreadId})");
                var typedResponse =
                    _client.JsonSerializer.DeserializeToWebsocketResponse <TResponse>(
                        response.MessageBytes);
                o.OnNext(typedResponse.Payload);

                // in case of a GraphQL error, terminate the sequence after the response has been posted
                if (response.Type == GraphQLWebSocketMessageType.GQL_ERROR)
                {
                    Debug.WriteLine($"terminating subscription {startRequest.Id} because of a GraphQL error");
                    o.OnCompleted();
                }
            },
                                                                                         e =>
            {
                Debug.WriteLine($"response stream for subscription {startRequest.Id} failed: {e}");
                o.OnError(e);
            },
                                                                                         () =>
            {
                Debug.WriteLine($"response stream for subscription {startRequest.Id} completed");
                o.OnCompleted();
            })
                                                                              );

            try
            {
                // initialize websocket (completes immediately if socket is already open)
                await InitializeWebSocket();
            }
            catch (Exception e)
            {
                // subscribe observer to failed observable
                return(Observable.Throw <GraphQLResponse <TResponse> >(e).Subscribe(observer));
            }

            var disposable = new CompositeDisposable(
                observable.Subscribe(observer),
                Disposable.Create(async() =>
            {
                // only try to send close request on open websocket
                if (WebSocketState != WebSocketState.Open)
                {
                    return;
                }

                try
                {
                    Debug.WriteLine($"sending close message on subscription {startRequest.Id}");
                    await QueueWebSocketRequest(closeRequest);
                }
                // do not break on disposing
                catch (OperationCanceledException) { }
            })
                );

            // send connection init
            Debug.WriteLine($"sending connection init on subscription {startRequest.Id}");
            try
            {
                await QueueWebSocketRequest(initRequest);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            Debug.WriteLine($"sending initial message on subscription {startRequest.Id}");
            // send subscription request
            try
            {
                await QueueWebSocketRequest(startRequest);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            return(disposable);
        }))
        // complete sequence on OperationCanceledException, this is triggered by the cancellation token
        .Catch <GraphQLResponse <TResponse>, OperationCanceledException>(exception =>
                                                                         Observable.Empty <GraphQLResponse <TResponse> >())
        // wrap results
        .Select(response => new Tuple <GraphQLResponse <TResponse>, Exception>(response, null))
        // do exception handling
        .Catch <Tuple <GraphQLResponse <TResponse>, Exception>, Exception>(e =>
        {
            try
            {
                if (exceptionHandler == null)
                {
                    // if the external handler is not set, propagate all exceptions except WebSocketExceptions
                    // this will ensure that the client tries to re-establish subscriptions on connection loss
                    if (!(e is WebSocketException))
                    {
                        throw e;
                    }
                }
                else
                {
                    // exceptions thrown by the handler will propagate to OnError()
                    exceptionHandler?.Invoke(e);
                }

                // throw exception on the observable to be caught by Retry() or complete sequence if cancellation was requested
                if (_internalCancellationToken.IsCancellationRequested)
                {
                    return(Observable.Empty <Tuple <GraphQLResponse <TResponse>, Exception> >());
                }
                else
                {
                    Debug.WriteLine($"Catch handler thread id: {Thread.CurrentThread.ManagedThreadId}");
                    return(Observable.Throw <Tuple <GraphQLResponse <TResponse>, Exception> >(e));
                }
            }
            catch (Exception exception)
            {
                // wrap all other exceptions to be propagated behind retry
                return(Observable.Return(new Tuple <GraphQLResponse <TResponse>, Exception>(null, exception)));
            }
        })
        // attempt to recreate the websocket for rethrown exceptions
        .Retry()
        // unwrap and push results or throw wrapped exceptions
        .SelectMany(t =>
        {
            Debug.WriteLine($"unwrap exception thread id: {Thread.CurrentThread.ManagedThreadId}");
            // if the result contains an exception, throw it on the observable
            if (t.Item2 != null)
            {
                return(Observable.Throw <GraphQLResponse <TResponse> >(t.Item2));
            }

            return(t.Item1 == null
                        ? Observable.Empty <GraphQLResponse <TResponse> >()
                        : Observable.Return(t.Item1));
        })
        // transform to hot observable and auto-connect
        .Publish().RefCount();
示例#25
0
        private IObservable <TdApi.Message> LoadAggregateMessages(
            Aggregate aggregate,
            AggregateLoadingState state)
        {
            var actualLimit = _limit;

            var list = aggregate.Chats.Select(f =>
            {
                var stackedCount = state.CountStackedMessages(f.ChatData.Id);

                return(Enumerable.Range(0, stackedCount)
                       .Select(_ => state.PopMessageFromStack(f.ChatData.Id)) // get stacked messages for this chat
                       .ToObservable()
                       .Concat(stackedCount < _limit
                        ? LoadChannelMessages(f, new ChatLoadingState // load messages from the server
                {
                    LastMessageId = state.GetLastMessageId(f.ChatData.Id)
                }, _limit, 0)
                        : Observable.Empty <TdApi.Message>())
                       .CollectToList()
                       .Do(l =>
                {
                    // api has no guarantees about actual number of messages returned
                    // actual limit would be equal to min number of messages for all feeds
                    // unless it is zero
                    if (l.Count > 0 && l.Count < actualLimit)
                    {
                        actualLimit = l.Count;
                    }
                })
                       .SelectMany(messages => messages));
            });

            return(list.Merge()
                   .CollectToList()
                   .SelectMany(l =>
            {
                // make sure all messages are unique
                var all = l.GroupBy(m => m.Id)
                          .Select(g => g.First())
                          .OrderByDescending(m => m.Date)
                          .ToArray();

                var toBeReturned = all.Take(actualLimit);
                var toBeStacked = all.Skip(actualLimit);

                // remember last message id
                foreach (var message in all.Reverse())
                {
                    state.SetLastMessageId(message.ChatId, message.Id);
                }

                // put into stack
                foreach (var message in toBeStacked.Reverse())
                {
                    state.PushMessageToStack(message.ChatId, message);
                }

                return toBeReturned;
            }));
        }
示例#26
0
        private IObservable <Unit> done()
        {
            var nameIsAlreadyTaken = currentWorkspace
                                     .SelectMany(workspace => dataSource.Projects.GetAll(project => project.WorkspaceId == workspace.Id))
                                     .Select(existingProjectsDictionary)
                                     .CombineLatest(currentClient, Name, checkNameIsTaken);

            var projectCreation = currentWorkspace.FirstAsync()
                                  .SelectMany(workspace => checkIfCanContinue(workspace)
                                              .SelectMany(shouldContinue => !shouldContinue
                        ? Observable.Empty <Unit>()
                        : getDto(workspace)
                                                          .SelectMany(dto => interactorFactory.CreateProject(dto).Execute())
                                                          .Do(createdProject => Close(createdProject.Id))
                                                          .SelectUnit()
                                                          )
                                              );

            return(nameIsAlreadyTaken.SelectMany(taken =>
            {
                if (taken)
                {
                    throw new Exception(Resources.ProjectNameTakenError);
                }

                return projectCreation;
            }));

            IObservable <bool> checkIfCanContinue(IThreadSafeWorkspace workspace)
            {
                if (initialWorkspaceId == workspace.Id)
                {
                    return(Observable.Return(true));
                }

                return(View.Confirm(
                           Resources.WorkspaceChangedAlertTitle,
                           Resources.WorkspaceChangedAlertMessage,
                           Resources.Ok,
                           Resources.Cancel
                           ));
            }

            IObservable <CreateProjectDTO> getDto(IThreadSafeWorkspace workspace)
            => Observable.CombineLatest(
                Name.FirstAsync(),
                Color.FirstAsync(),
                currentClient.FirstAsync(),
                interactorFactory.AreProjectsBillableByDefault(workspace.Id).Execute(),
                IsPrivate.FirstAsync(),
                (name, color, client, billable, isPrivate) => new CreateProjectDTO
            {
                Name        = name.Trim(),
                Color       = color.ToHexString(),
                IsPrivate   = isPrivate,
                ClientId    = client?.Id,
                Billable    = billable,
                WorkspaceId = workspace.Id
            }
                );

            Dictionary <long, HashSet <string> > existingProjectsDictionary(IEnumerable <IThreadSafeProject> projectsInWorkspace)
            => projectsInWorkspace.Aggregate(new Dictionary <long, HashSet <string> >(), (dict, project) =>
            {
                var key = project.ClientId ?? noClientId;
                if (dict.ContainsKey(key))
                {
                    dict[key].Add(project.Name);
                    return(dict);
                }

                dict[key] = new HashSet <string> {
                    project.Name
                };
                return(dict);
            });

            bool checkNameIsTaken(Dictionary <long, HashSet <string> > projectNameDictionary, IThreadSafeClient client, string name)
            {
                var key = client?.Id ?? noClientId;

                if (projectNameDictionary.TryGetValue(key, out var projectNames))
                {
                    return(projectNames.Contains(name.Trim()));
                }

                return(false);
            }
        }
示例#27
0
 public static IObservable <T> WhenAnyCommand <T, TRet>(this IObservable <IEnumerable <T> > listStream,
                                                        Func <T, IObservable <TRet> > selector)
 {
     return(listStream
            .Select(list => list?.Select(t => selector(t).Select(_ => t)).Merge() ?? Observable.Empty <T>())
            .Switch());
 }
示例#28
0
        public EditProjectViewModel(
            ITogglDataSource dataSource,
            IRxActionFactory rxActionFactory,
            IInteractorFactory interactorFactory,
            ISchedulerProvider schedulerProvider,
            INavigationService navigationService)
            : base(navigationService)
        {
            Ensure.Argument.IsNotNull(dataSource, nameof(dataSource));
            Ensure.Argument.IsNotNull(rxActionFactory, nameof(rxActionFactory));
            Ensure.Argument.IsNotNull(interactorFactory, nameof(interactorFactory));
            Ensure.Argument.IsNotNull(schedulerProvider, nameof(schedulerProvider));

            this.dataSource        = dataSource;
            this.interactorFactory = interactorFactory;

            Name      = new BehaviorRelay <string>("");
            IsPrivate = new BehaviorRelay <bool>(true);

            PickColor     = rxActionFactory.FromObservable <Color>(pickColor);
            PickClient    = rxActionFactory.FromObservable <IThreadSafeClient>(pickClient);
            PickWorkspace = rxActionFactory.FromObservable <IThreadSafeWorkspace>(pickWorkspace);

            var initialWorkspaceObservable = interactorFactory
                                             .GetDefaultWorkspace()
                                             .TrackException <InvalidOperationException, IThreadSafeWorkspace>("EditProjectViewModel.Initialize")
                                             .Execute()
                                             .SelectMany(defaultWorkspaceOrWorkspaceEligibleForProjectCreation)
                                             .Do(initialWorkspace => initialWorkspaceId = initialWorkspace.Id);

            currentWorkspace = initialWorkspaceObservable
                               .Merge(PickWorkspace.Elements)
                               .ShareReplay(1);

            currentClient = currentWorkspace
                            .SelectValue((IThreadSafeClient)null)
                            .Merge(PickClient.Elements)
                            .ShareReplay(1);

            WorkspaceName = currentWorkspace
                            .Select(w => w.Name)
                            .DistinctUntilChanged()
                            .AsDriver(schedulerProvider);

            CanCreatePublicProjects = currentWorkspace
                                      .Select(w => w.Admin)
                                      .DoIf(isAdmin => !isAdmin, _ => IsPrivate.Accept(true))
                                      .DistinctUntilChanged()
                                      .AsDriver(schedulerProvider);

            var clientName = currentClient
                             .Select(client => client?.Name ?? "")
                             .DistinctUntilChanged();

            ClientName = clientName
                         .AsDriver(schedulerProvider);

            Color = PickColor.Elements
                    .StartWith(getRandomColor())
                    .Merge(currentWorkspace
                           .SelectMany(customColorIsEnabled)
                           .SelectMany(customColorsAreAvailable => customColorsAreAvailable
                        ? Observable.Empty <Color>()
                        : Color.FirstAsync().Select(randomColorIfNotDefault)))
                    .DistinctUntilChanged()
                    .AsDriver(schedulerProvider);

            var saveEnabledObservable = Name.Select(checkNameValidity);

            var projectOrClientNameChanged = Observable
                                             .Merge(clientName.SelectUnit(), Name.SelectUnit());

            Save = rxActionFactory.FromObservable(done, saveEnabledObservable);

            Error = Save.Errors
                    .Select(e => e.Message)
                    .Merge(projectOrClientNameChanged.SelectValue(string.Empty))
                    .AsDriver(schedulerProvider);

            IObservable <IThreadSafeWorkspace> defaultWorkspaceOrWorkspaceEligibleForProjectCreation(IThreadSafeWorkspace defaultWorkspace)
            => defaultWorkspace.IsEligibleForProjectCreation()
                    ? Observable.Return(defaultWorkspace)
                    : interactorFactory.GetAllWorkspaces().Execute()
            .Select(allWorkspaces => allWorkspaces.First(ws => ws.IsEligibleForProjectCreation()));

            IObservable <bool> customColorIsEnabled(IThreadSafeWorkspace workspace)
            => interactorFactory
            .AreCustomColorsEnabledForWorkspace(workspace.Id)
            .Execute();

            Color getRandomColor()
            {
                var randomColorIndex = random.Next(0, Helper.Colors.DefaultProjectColors.Length);

                return(Helper.Colors.DefaultProjectColors[randomColorIndex]);
            }

            Color randomColorIfNotDefault(Color lastColor)
            {
                var hex = lastColor.ToHexString();

                if (DefaultProjectColors.Any(defaultColor => defaultColor == hex))
                {
                    return(lastColor);
                }

                return(getRandomColor());
            }

            bool checkNameValidity(string name)
            => !string.IsNullOrWhiteSpace(name) &&
            name.LengthInBytes() <= Constants.MaxProjectNameLengthInBytes;
        }
示例#29
0
        public static IObservable <Request> GetRequests(NetWorkSetting ns, Guid[] ids, Guid dmID)
        {
            if (ids.NullOrEmpty())
            {
                return(Observable.Empty <Request>());
            }

            var nullReqs = (Request[])null;
            var noError  = (Exception)null;

            return
                (Observable.Generate(
                     new { reqs = nullReqs, idss = new[] { ids }.AsEnumerable(), DataMartID = dmID, finish = false, error = noError },
                     st => !st.finish,
                     st =>
            {
                try
                {
                    if (st.error != null)
                    {
                        return new { st.reqs, st.idss, st.DataMartID, finish = true, st.error }
                    }
                    ;

                    var i = st.idss.FirstOrDefault();
                    var dm = st.DataMartID;
                    if (i == null)
                    {
                        return new { st.reqs, idss = st.idss, DataMartID = st.DataMartID, finish = true, error = noError }
                    }
                    ;

                    Request[] reqs = null;
                    using (var web = new Lpp.Dns.DataMart.Client.Lib.DnsApiClient(ns, FindCert(ns)))
                    {
                        var requests = AsyncHelpers.RunSync <IQueryable <DTO.DataMartClient.Request> >(() => web.GetRequests(i.Select(x => x).ToArray(), dm));

                        reqs = requests.ToArray();
                    }

                    return new { reqs, idss = st.idss.Skip(1), DataMartID = st.DataMartID, finish = false, error = noError };
                }
                catch (CommunicationException ex)
                {
                    if (ex.Message.ToLower().Contains("size quota"))
                    {
                        return st.idss.First().Length > 1         // When the next segment can be subdivided further, do it
                                    ? new
                        {
                            reqs = nullReqs,
                            idss = st.idss
                                   .SelectMany(i => new[] { i.Take(i.Length / 2).ToArray(), i.Skip(i.Length / 2).ToArray() })
                                   .Where(i => i.Any()),
                            DataMartID = st.DataMartID,
                            finish = false,
                            error = noError
                        }
                        // Otherwise, return error
                                    : new { reqs = nullReqs, idss = st.idss, DataMartID = st.DataMartID, finish = false, error = (Exception)ex };
                    }

                    throw;
                }
            },
                     st => st.error == null ? st.reqs.EmptyIfNull().ToObservable() : Observable.Throw <Request>(st.error),
                     System.Reactive.Concurrency.Scheduler.Default
                     )
                 .Catch(( Exception ex ) =>
            {
                _log.Error(string.Format("Unable to get requests for Network: {0}.", ns.NetworkName), ex);
                return Observable.Throw <IObservable <Request> >(new GetRequestsFailed(ex));
            })
                 .SelectMany(rs => rs));
        }
示例#30
0
        public void Await_ArgumentChecking()
        {
            ReactiveAssert.Throws <ArgumentNullException>(() => Observable.GetAwaiter <int>(default(IObservable <int>)));
            ReactiveAssert.Throws <ArgumentNullException>(() => Observable.GetAwaiter <int>(default(IConnectableObservable <int>)));

            ReactiveAssert.Throws <ArgumentNullException>(() => Observable.GetAwaiter(Observable.Empty <int>()).OnCompleted(null));
        }