/// <summary> /// Creates a new automation /// </summary> /// <param name="name">The friendly name of the automation</param> /// <param name="host">The host that manages this automation</param> protected Automation(string id, string name, IAutomationHost host) { Id = id ?? name; Name = name ?? throw new ArgumentNullException(nameof(name)); Scheduler = host.Scheduler ?? throw new InvalidOperationException("Host's scheduler is 'null'."); _hostSubscription = Observable .DeferAsync(async ct => { await host.Initialized(ct, this); return(host.GetAndObserveIsEnabled(this)); }) .DistinctUntilChanged() .Do(isEnabled => { // Make sure to always abort the pending execution, even if 'Enable()' fails _automationSubscription.Disposable = null; if (isEnabled) { _automationSubscription.Disposable = new CompositeDisposable { // AsyncContext is used here mainly to propagate the IScheduler, but might flow in the subscriptions // made in the "Enable". So we make sure to dispose it only when the automation is disable. new AsyncContext(Scheduler), Enable() }; } this.Log().Info($"Automation '{Name}' is now enabled: {isEnabled}"); }) .Retry(Constants.DefaultRetryDelay, Scheduler) .Subscribe(); }
/// <summary> /// Constructor sets up queue and creates download folder if non-existing. /// </summary> public JobManager(IDatabaseManager databaseManager, IMessageManager messageManager, IThreadManager threadManager, ILogger logger, CrashManager crashManager) { _databaseManager = databaseManager; _messageManager = messageManager; _threadManager = threadManager; _logger = logger; _crashManager = crashManager; // setup transfer queue _queue = _jobs .Do(job => _logger.Info("----- Added job {0} to active transfers.", job.File.Name)) .ObserveOn(Scheduler.Default) .Select(job => Observable.DeferAsync(async token => Observable.Return(await ProcessDownload(job, token)))) .Merge(MaximalSimultaneousDownloads) .Subscribe(job => { _databaseManager.SaveJob(job); if (job.Status != Job.JobStatus.Aborted) { _whenDownloaded.OnNext(job); } }, error => { // todo treat error in ui _logger.Error(error, "Error: {0}", error.Message); }); // save job when status changes _whenStatusChanged.Sample(TimeSpan.FromMilliseconds(200)).Subscribe(_databaseManager.SaveJob); if (!Directory.Exists(_downloadPath)) { _logger.Info("Creating non-existing download folder at {0}.", _downloadPath); Directory.CreateDirectory(_downloadPath); } }
public IObservable <StatisticItem> GetStatisticItems() { if (null == task) { task = provider.GetStatisticAsync(CancellationToken.None); } var observable = Observable.DeferAsync( async cancellationToken => { var feed = await task; return(Observable.Create <StatisticItem>(observer => { foreach (var statisticItem in feed) { observer.OnNext(statisticItem); } observer.OnCompleted(); return Disposable.Create(() => task = null); })); } ); return(observable); }
/// <summary> /// サーバーへのリクエストの間隔が指定された時間を下回らないように、ブログエントリの一覧を非同期で取得します。 /// </summary> /// <param name="period">サーバーへのリクエストの最小間隔。</param> /// <returns>ブログエントリの一覧を非同期で列挙する、 <see cref="IObservable{T}"/> 型の通知プロバイダー。</returns> /// <exception cref="ResourceNotFoundException">存在しないリソースにアクセスしました。</exception> /// <exception cref="InternalServerErrorException">はてなブログ AtomPub で問題が発生しました。</exception> /// <exception cref="HttpRequestException">HTTP リクエストに失敗しました。</exception> public IObservable <Entry> GetEntriesAsObservable(TimeSpan period) { return(Observable.DeferAsync(async ct => { var requestUri = !_hasCurrentFeed ? _collectionUri : _currentFeed.NextRequestUri; var response = await _client.Value.GetAsync(requestUri, ct).ConfigureAwait(false); VerifyResponse(response); var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false); var xElement = XElement.Load(stream); _currentFeed = Feed.FromXElement(xElement); _hasCurrentFeed = true; return Observable.Return(_currentFeed); }) .TimeInterval() .Select(ti => Observable.FromAsync(async ct => { Debug.WriteLine(ti.Interval); var delay = Extensions.Max(TimeSpan.Zero, period - ti.Interval); await Task.Delay(delay, ct).ConfigureAwait(false); return ti.Value; })) .Concat() .SelectMany(f => f) .DoWhile(() => _currentFeed.NextRequestUri != null) .Finally(() => { _currentFeed = null; _hasCurrentFeed = false; })); }
public FileWatchingDocument(IFileSystem fs, AbsoluteFilePath path, IScheduler scheduler = null) { _fs = fs; _path = path; _scheduler = scheduler ?? Scheduler.Default; var contents = fs.Watch(path) .StartWith(Unit.Default) .CatchAndRetry(delay: TimeSpan.FromSeconds(1), scheduler: _scheduler) .Throttle(TimeSpan.FromSeconds(1.0 / 30.0), _scheduler) .Select( notifyTime => Observable.DeferAsync( async token => Observable.Return( await ReadAllBytesAndRetryOnError(token)))) .Switch() .Replay(1); var externalChanges = contents .Where(bytes => _lastKnownChanges.Value.Select(bytes.SequenceEqual).Or(false) == false) .Do(bytes => _lastKnownChanges.OnNext(bytes)) .Replay(1); _garbage = Disposable.Combine( externalChanges.Connect(), contents.Connect()); Contents = contents; ExternalChanges = externalChanges; }
private static IObservable <bool> requestPermission( IObservable <bool> permissionChecker, Func <Task <Tuple <bool, NSError> > > permissionRequestFunction, bool force) => Observable.DeferAsync(async cancellationToken => { var permissionGranted = await permissionChecker; if (permissionGranted) { return(Observable.Return(true)); } if (force) { //Fact: If the user changes any permissions through the settings, this app gets restarted //and in that case we don't care about the value returned from this method. //We care about the returned value in the case, when user opens settings //and comes back to this app without altering any permissions. In that case //returning the current permission status is the correct behaviour. OpenAppSettings(); return(Observable.Return(false)); } return(Observable .FromAsync(permissionRequestFunction) .Select(tuple => tuple.Item1)); });
public void DeferAsync_WithCancel_Cancel() { var N = 10;// 0000; for (int i = 0; i < N; i++) { var e = new ManualResetEvent(false); var called = false; var xs = Observable.DeferAsync <int>(ct => Task.Factory.StartNew(() => { e.Set(); while (!ct.IsCancellationRequested) { ; } return(Observable.Defer(() => { called = true; return Observable.Return(42); })); })); var d = xs.Subscribe(_ => { }); e.WaitOne(); d.Dispose(); Assert.False(called); } }
public static async Task LimitConcurrencyGoodExample() { var rng = new Random(); await Observable .Range(1, 10, TaskPoolScheduler.Default) .Select( range => Observable .DeferAsync( async ct => { WriteToConsoleWithColor((ConsoleColor)range, $"{range} - Started at {DateTimeOffset.Now.ToUnixTimeMilliseconds()}"); var delay = rng.Next(10, 300); await Task.Delay(delay); WriteToConsoleWithColor((ConsoleColor)range, $"{range} - Finished after {delay}ms"); return(Observable.Return(range)); })) .Merge(1) .Do( range => { WriteToConsoleWithColor((ConsoleColor)range, $"{range} - Received Notification at {DateTimeOffset.Now.ToUnixTimeMilliseconds()}"); }); }
/// <summary> /// Creates a new automation /// </summary> /// <param name="name">The friendly name of the automation</param> /// <param name="host">The host that manages this automation</param> protected Automation(string id, string name, IAutomationHost host) { Id = id ?? name; Name = name ?? throw new ArgumentNullException(nameof(name)); Scheduler = host.Scheduler ?? throw new InvalidOperationException("Host's scheduler is 'null'."); _hostSubscription = Observable .DeferAsync(async ct => { await host.Initialized(ct, this); return(host.GetAndObserveIsEnabled(this)); }) .Do(isEnabled => { // Make sure to always abort the pending execution, even if 'Enable()' fails _automationSubscription.Disposable = null; if (isEnabled) { using (new AsyncContext(Scheduler)) // AsyncContext is used here only to propagate the IScheduler { _automationSubscription.Disposable = Enable(); } } this.Log().Info($"Automation '{Name}' is now enabled: {isEnabled}"); }) .Retry(Constants.DefaultRetryDelay, Scheduler) .Subscribe(); }
public DeferByAsync() { Obs = Observable.Interval(TimeSpan.FromSeconds(3)) .Select(item => Observable.DeferAsync(async token => { return(await ExpensiveTask(token, item)); })) .Switch(); }
private IObservable <Unit> selectWorkspace(SelectableWorkspaceViewModel workspace) => Observable.DeferAsync(async _ => { await interactorFactory.SetDefaultWorkspace(workspace.WorkspaceId).Execute(); accessRestrictionStorage.SetNoDefaultWorkspaceStateReached(false); await navigationService.Close(this, Unit.Default); return(Observable.Return(Unit.Default)); });
public void DeferAsync_WithCancel_Simple() { var xs = Observable.DeferAsync <int>(ct => Task.Factory.StartNew(() => Observable.Return(42))); var res = xs.ToEnumerable().ToList(); Assert.True(new[] { 42 }.SequenceEqual(res)); }
SideEffectLast <T>(this IObservable <T> source, Func <CancellationToken, Task> last) => source .Concat( Observable.DeferAsync( async ct => { await last(ct).ConfigureAwait(false); return(Observable.Empty <T>()); }));
public IObservable <Unit> DeleteMesh(string meshName, string resourceGroupName) { return(Observable.DeferAsync(async token => { await _serviceFabricMeshManagementClient.Application.DeleteWithHttpMessagesAsync( resourceGroupName, meshName, cancellationToken: token); return Observable.Return(Unit.Default); })); }
public static IObservable <TOut> OnEachExecuteCancellingPrevious <TIn, TOut>(this IObservable <TIn> This, Func <TIn, CancellationToken, Task <TOut> > func) { return (This .Select(item => Observable.DeferAsync(async token => { var val = await func.Invoke(item, token); return Observable.Return(val); })) .Switch()); }
public static IObservable <T> DeferAndThrowIfPermissionNotGranted <T>(this IObservable <bool> permissionGrantedObservable, Func <IObservable <T> > implementation) => Observable.DeferAsync(async cancellationToken => { var isAuthorized = await permissionGrantedObservable; if (!isAuthorized) { return(Observable.Throw <T>( new NotAuthorizedException("You don't have permission to schedule notifications") )); } return(implementation()); });
public IObservable <bool> GetDeferredObservable(object connection) { return(Observable.DeferAsync <bool>(token => { return Task.Factory.StartNew(() => { Console.WriteLine("UNDERLYING ENGAGED"); Thread.Sleep(1000); // Let's pretend there's some static on the line... return Observable.Return(true) .Concat(Observable.Return(false)) .Concat(Observable.Return(true)); }, token); })); }
/// <summary> /// Allows cancellation of a call to `selector` when the input observable produces a new value. /// </summary> /// <typeparam name="TIn"></typeparam> /// <typeparam name="TOut"></typeparam> /// <param name="o"></param> /// <param name="selector"></param> /// <returns></returns> public static IObservable <TOut> SelectAsync <TIn, TOut>(this IObservable <TIn> o, Func <TIn, CancellationToken, Task <TOut> > selector) { return(o .Select(x => Observable.DeferAsync(async ct => { try { var result = await selector(x, ct); return Observable.Return(result); } catch (OperationCanceledException) { return Observable.Empty <TOut>(); } }) ) .Switch()); }
public IObservable <string> CreateOrEditMesh(string applicationResourceName, string imageRegistryServer, string imageRegistryUsername, string imageRegistryPassword, string imageName, string azurePipelinesUrl, string azurePipelinesToken, string resourceGroupName, int?replicaCount = null) { return(Observable.DeferAsync(async token => { var applicationResourceDescription = CreateApplicationResourceDescription(imageRegistryServer, imageRegistryUsername, imageRegistryPassword, imageName, azurePipelinesUrl, azurePipelinesToken, replicaCount); var createMeshResponse = await _serviceFabricMeshManagementClient.Application.CreateWithHttpMessagesAsync( resourceGroupName, applicationResourceName, applicationResourceDescription, cancellationToken: token); _logger.Verbose("CreateMeshResponse.Body {@ResponseBody}", createMeshResponse.Body); return Observable.Return(applicationResourceName); }).SubscribeOn(_schedulerProvider.TaskPool)); }
private IObservable <IList <IProject> > searchProjects(long workspaceId, long[] projectIds) => Observable.DeferAsync(async cancellationToken => { if (projectIds.Length == 0) { return(Observable.Return(new List <IProject>())); } var projectsInDatabase = await projectIds .Select(tryGetProjectFromDatabase) .Aggregate(Observable.Merge) .ToList(); var notInDatabaseIds = projectsInDatabase.SelectAllLeft().ToArray(); var databaseProjectsObservable = Observable.Return(projectsInDatabase.SelectAllRight().ToList()); return(notInDatabaseIds.Length == 0 ? databaseProjectsObservable : databaseProjectsObservable .Merge(searchMemoryAndApi(workspaceId, notInDatabaseIds)) .SelectMany(list => list) .ToList()); });
public IObservable <object> GetTrigger(BlockConfig trigger, IFlowContext context) { try { var(connector, connection, name) = GetConnection(trigger, context); var flowTrigger = connector.GetTrigger(name); if (flowTrigger is null) { throw new FlowException($"Unable to acquire trigger \"{trigger.Type}\".", context); } return(Observable.DeferAsync(async _ => { var flowTriggerConfiguration = await Resolve(trigger.Arguments, flowTrigger.ArgumentsType, context); return flowTrigger.GetEvents(context, connection, flowTriggerConfiguration); })); } catch (Exception e) when(e is not FlowException) { throw new FlowException($"Error while getting trigger \"{trigger.Type}\".", context, e); } }
ParserService(ITextBuffer textBuffer) { TextBuffer = textBuffer; WeakEventDispatcher.Connect(this, textBuffer); _parserObs = Observable.FromEventPattern <EventArgs>( handler => RebuildTriggered += handler, handler => RebuildTriggered -= handler) .Select(_ => CreateBuildResultArgs()) .Throttle(ServiceProperties.ParserServiceThrottleTime) .Select(args => Observable.DeferAsync(async token => { var parseResult = await BuildAsync(args, token).ConfigureAwait(false); return(Observable.Return(parseResult)); })) .Switch() .ObserveOn(SynchronizationContext.Current) .Subscribe(TrySetResult); _waitingForAnalysis = true; // Initiales Parsen antriggern Invalidate(); }
public void DeferVsDeferAsyncTest() { const string NOT_AUTH = "not authenticate"; var xs = Observable.Interval(TimeSpan.FromSeconds(0.5)) .Take(20) .Publish(); // convert into hot observable xs.Monitor("Source", 1).Subscribe(); xs.Connect(); var ds = Observable.Defer(() => xs); ds = ds.Monitor("Defer", 2); var ds1 = Observable.DeferAsync <long>((ct) => { return(Task.Factory.StartNew(() => { if (Authenticate("user", ct)) { return xs; } else { return Observable.Throw <long>(new SecurityException("not authenticate")); } })); }); ds1 = ds1.Monitor("Defer Async User", 3); var ds2 = Observable.DeferAsync <long>((ct) => { return(Task.Factory.StartNew(() => { if (Authenticate("admin", ct)) { return xs; } else { return Observable.Throw <long>(new SecurityException(NOT_AUTH)); } })); }); ds2 = ds2.Monitor("Defer Async Admin", 4); ds.Subscribe(); ds1.Subscribe(); ds2.Subscribe(); try { ds.Wait(); ds1.Wait(); ds2.Wait(); } #region Exception Handling catch (SecurityException ex) { Assert.AreEqual(NOT_AUTH, ex.Message); } #endregion Exception Handling }
public (IObservable <Unit> request, IObservable <bool> ready, Func <(IObservable <Unit> request, IObservable <Unit> complete)> stop) Start(string applicationResourceName, string imageRegistryServer, string imageRegistryUsername, string imageRegistryPassword, string imageName, string azurePipelinesUrl, string azurePipelinesToken, string resourceGroupName, bool outputContainerLogs = true, bool outputComponentStatus = true) { var autoResetEvent = new AutoResetEvent(false); var disposable = new CompositeDisposable(); var readySubject = new Subject <bool>(); var request = Observable.DeferAsync(async token => { _logger.Information("Starting Mesh {Mesh}", applicationResourceName); await _observableMeshClient.CreateOrEditMesh(applicationResourceName, imageRegistryServer, imageRegistryUsername, imageRegistryPassword, imageName, azurePipelinesUrl, azurePipelinesToken, resourceGroupName); var startPollingSubject = new Subject <Unit>(); var startPollingObservable = startPollingSubject.AsObservable(); var applicationFailedSubject = new Subject <Unit>(); var applicationFailedObservable = applicationFailedSubject.AsObservable(); var pollApplicationStatus = _observableMeshClient .PollApplicationStatus(applicationResourceName, resourceGroupName) .Replay(); var pollServiceStatus = _observableMeshClient .PollServiceStatus(applicationResourceName, resourceGroupName, startPollingObservable, applicationFailedObservable) .Replay(); var pollAgentStatus = _observableMeshClient .PollAgentStatus(applicationResourceName, resourceGroupName, startPollingObservable, applicationFailedObservable, 0, outputContainerLogs) .Replay(); var pollReplicaStateSubscription = pollAgentStatus .SubscribeOn(_schedulerProvider.TaskPool) .Subscribe(agentStateEnum => { }, exception => { _logger.Error("Container Logs Error: {Message}", exception.Message); }); var applicationStateObservable = pollApplicationStatus .SubscribeOn(_schedulerProvider.TaskPool) .Subscribe(applicationStatusEnum => { }, exception => { _logger.Error("Application Error: {Message}", exception.Message); }); var serviceDataSubscription = pollServiceStatus .SubscribeOn(_schedulerProvider.TaskPool) .Subscribe(serviceStatusEnum => { }, exception => { _logger.Error("Service Error: {Message}", exception.Message); }); var combinedSubscription = pollApplicationStatus.CombineLatest(pollServiceStatus, pollAgentStatus, (applicationStatus, serviceStatus, agentStatus) => (applicationStatus, serviceStatus, agentStatus)) .DistinctUntilChanged() .SubscribeOn(_schedulerProvider.TaskPool) .Subscribe(tuple => { var(applicationStatus, serviceStatus, agentStatus) = tuple; if (outputComponentStatus) { _logger.Information( "Mesh {Mesh} Application {Application,8} Service {Service,8} Agent {Agent,8}", applicationResourceName, applicationStatus, serviceStatus, agentStatus); } if (applicationStatus == ApplicationStatusEnum.Ready && serviceStatus == ServiceStatusEnum.Ready && agentStatus == AgentStatusEnum.Ready) { readySubject.OnNext(true); readySubject.OnCompleted(); return; } if (applicationStatus == ApplicationStatusEnum.Failed && serviceStatus == ServiceStatusEnum.Failed && agentStatus == AgentStatusEnum.Failed) { readySubject.OnNext(false); readySubject.OnCompleted(); return; } if (applicationStatus == ApplicationStatusEnum.Failed) { applicationFailedSubject.OnNext(Unit.Default); applicationFailedSubject.OnCompleted(); return; } if (applicationStatus == ApplicationStatusEnum.Creating) { startPollingSubject.OnNext(Unit.Default); startPollingSubject.OnCompleted(); return; } }, () => { _logger.Debug("Streams completed"); autoResetEvent.Set(); }); pollApplicationStatus.Connect(); pollServiceStatus.Connect(); pollAgentStatus.Connect(); disposable.Add(pollReplicaStateSubscription); disposable.Add(applicationStateObservable); disposable.Add(serviceDataSubscription); disposable.Add(combinedSubscription); disposable.Add(readySubject); disposable.Add(startPollingSubject); disposable.Add(applicationFailedSubject); return(Observable.Return(Unit.Default)); }).SubscribeOn(_schedulerProvider.TaskPool); Func <(IObservable <Unit> request, IObservable <Unit> complete)> stop = () => { var completeObservable = Observable.Defer(() => { autoResetEvent.WaitOne(); _logger.Information("Stopped"); disposable.Dispose(); disposable = null; return(Observable.Return(Unit.Default)); }).SubscribeOn(_schedulerProvider.TaskPool); ; var stopRequest = Observable.DeferAsync(async token => { _logger.Information("Stopping"); await _observableMeshClient.DeleteMesh(applicationResourceName, resourceGroupName); return(Observable.Return(Unit.Default)); }).SubscribeOn(_schedulerProvider.TaskPool); return(stopRequest, completeObservable); }; var ready = readySubject.AsObservable(); return(request, ready, stop); }
public void DeferAsync_ArgumentChecking() { ReactiveAssert.Throws <ArgumentNullException>(() => Observable.Defer(default(Func <Task <IObservable <int> > >))); ReactiveAssert.Throws <ArgumentNullException>(() => Observable.DeferAsync(default(Func <CancellationToken, Task <IObservable <int> > >))); }