public async Task RunAsync(CancellationToken token) { try { Log.Info("Starting up"); _monitor.JournalFileWatch.Where(x => x.Action == JournalWatchAction.Started).Subscribe( e => _notifier.Notify(NotificationPriority.High, NotificationEventType.FileSystem, $"Started watching '{e.File.FullName}'") ); _statusManager.ControlStateObservable .Throttle(TimeSpan.FromSeconds(1)) .Subscribe(_ => _notifier.Notify(NotificationPriority.High, NotificationEventType.Update, "Updated control status")); var startTime = _state.LastEntrySeen ?? DateTimeOffset.MinValue; var source = new JournalEntrySource(_parser, startTime, _monitor); var publisher = new JournalEntryPublisher(source); var publication = publisher.Observable.Publish(); _statusManager.SubscribeTo(publication); _processor.StartListening(token); publication.Subscribe(t => _updateSubject.OnNext(t.Entry.Timestamp)); Updates .Subscribe(e => { var lastEntry = e.Value; var lastChecked = e.Timestamp; Log.Info($"Updated at {lastChecked}, last entry stamped {lastEntry}"); _state.Update(lastChecked, lastEntry); }); using (publication.Connect()) { while (!token.IsCancellationRequested) { await Task.Delay(TimeSpan.FromSeconds(1)).ConfigureAwait(false); publisher.Poll(); } } } catch (Exception e) { Log.Fatal(e); throw; } }
public void Run(CancellationToken token) { Log.Info("Starting up"); var username = _config["Username"]; var password = _config["Password"]; // Try username and password from configuration, if possible try { var nowAuthenticated = _client.Authenticate(username, password); } catch (MatrixException ex) { Log.Warn(ex.Message); } var startTime = _state.LastEntrySeen ?? DateTimeOffset.MinValue; var source = new JournalEntrySource(_parser, startTime, _logMonitor, _liveMonitor); var publisher = new JournalEntryPublisher(source); var publication = publisher.Observable.Publish(); _gameContext.SubscribeTo(publication); _location.SubscribeTo(publication); _ship.SubscribeTo(publication); _session.SubscribeTo(publication); _logMonitor.JournalFileWatch.Subscribe( e => { switch (e.Action) { case JournalWatchAction.Started: _notifier.Notify(NotificationPriority.High, NotificationEventType.FileSystem, $"Started watching '{e.File.FullName}'"); break; case JournalWatchAction.Stopped: _notifier.Notify(NotificationPriority.Medium, NotificationEventType.FileSystem, $"Stopped watching '{e.File.FullName}'"); break; } }); _location.Observable .Subscribe(l => { if (_location.TryBuildUri(_gameContext.CommanderName, _gameContext.GameVersion, out var uri)) { _notifier.Notify(NotificationPriority.Low, NotificationEventType.Update, $"Pushed {nameof(LocationState)} update"); _client.Push(uri, l); } }); _ship.Observable .Subscribe(s => { if (_ship.TryBuildUri(_gameContext.CommanderName, _gameContext.GameVersion, out var uri)) { _notifier.Notify(NotificationPriority.Low, NotificationEventType.Update, $"Pushed {nameof(ShipState)} update"); _client.Push(uri, s); } }); _session.Observable .Subscribe(s => { if (_session.TryBuildUri(_gameContext.CommanderName, _gameContext.GameVersion, out var uri)) { _notifier.Notify(NotificationPriority.Low, NotificationEventType.Update, $"Pushed {nameof(SessionState)} update"); _client.Push(uri, s); } }); Updates .Subscribe(x => { var lastEntry = x.Value; var lastChecked = x.Timestamp; _state.Update(lastChecked, lastEntry); _notifier.Notify(NotificationPriority.Low, NotificationEventType.JournalEntry, "Journal entries applied"); }); var readyForNextBatch = new ManualResetEventSlim(true); using (publication.Connect()) { while (!token.IsCancellationRequested) { Task.Delay(TimeSpan.FromSeconds(1)).Wait(); publisher.Poll(); readyForNextBatch.Reset(); _client.StartUploading(token).Subscribe(t => { _notifier.Notify(NotificationPriority.Low, NotificationEventType.Update, "Uploaded data"); _updateSubject.OnNext(t); }, async ex => { if (ex is MatrixAuthenticationException) { _notifier.Notify(NotificationPriority.High, NotificationEventType.Error, "Authentication failure"); Log.Warn(ex.Message); // Block further processing until we at least attempt authentication try { var authenticated = await _authenticator.RequestAuthentication(); } catch (MatrixException mex) { _notifier.Notify(NotificationPriority.Medium, NotificationEventType.Error, "Authentication failure"); Log.Warn(mex.Message); } } else { Log.Error(ex.Message); } readyForNextBatch.Set(); }, () => { // Upload was successful, can proceed with another poll Log.Debug("Completed pending uploads"); readyForNextBatch.Set(); }, token); // Wait until either no longer blocked, or the app is being shut down WaitHandle.WaitAny(new[] { readyForNextBatch.WaitHandle, token.WaitHandle }); } } }