/// <summary> /// Starts observing the real-time Database. Events will be fired both when change is done locally and remotely. /// </summary> /// <returns> Stream of <see cref="FirebaseEvent{T}"/>. </returns> public IObservable <FirebaseEvent <T> > AsObservable() { if (this.observable == null) { var initialData = this.Database.Count == 0 ? Observable.Return(FirebaseEvent <T> .Empty(FirebaseEventSource.Offline)) : this.Database .Where(kvp => !string.IsNullOrEmpty(kvp.Value.Data) && kvp.Value.Data != "null" && !kvp.Value.IsPartial) .Select(kvp => new FirebaseEvent <T>(kvp.Key, kvp.Value.Deserialize <T>(), FirebaseEventType.InsertOrUpdate, FirebaseEventSource.Offline)) .ToList() .ToObservable(); this.observable = initialData .Merge(this.subject) .Merge(this.GetInitialPullObservable() .RetryAfterDelay(TimeSpan.FromSeconds(10)) .SelectMany(e => e) .Do(this.SetObjectFromInitialPull) .Select(e => new FirebaseEvent <T>(e.Key, e.Object, FirebaseEventType.InsertOrUpdate, FirebaseEventSource.Online)) .Concat(Observable.Create <FirebaseEvent <T> >(observer => this.InitializeStreamingSubscription(observer)))) .Replay() .RefCount(); } return(this.observable); }
/// <summary> /// Starts observing the real-time Database. Events will be fired both when change is done locally and remotely. /// </summary> /// <returns> Stream of <see cref="FirebaseEvent{T}"/>. </returns> public IObservable <FirebaseEvent <T> > AsObservable() { if (this.observable == null) { var initialData = this.Database.Count == 0 ? Observable.Return(FirebaseEvent <T> .Empty(FirebaseEventSource.Offline)) : this.Database .Where(kvp => !string.IsNullOrEmpty(kvp.Value.Data) && kvp.Value.Data != "null" && !kvp.Value.IsPartial) .Select(kvp => new FirebaseEvent <T>(kvp.Key, kvp.Value.Deserialize <T>(), FirebaseEventType.InsertOrUpdate, FirebaseEventSource.Offline)) .ToList() .ToObservable(); this.observable = initialData .Merge(this.subject) .Merge(this.GetInitialPullObservable() .RetryAfterDelay <IReadOnlyCollection <FirebaseObject <T> >, FirebaseException>( this.childQuery.Client.Options.SyncPeriod, ex => ex.StatusCode == System.Net.HttpStatusCode.OK) // OK implies the request couldn't complete due to network error. .SelectMany(e => e) .Do(this.SetObjectFromInitialPull) .Select(e => new FirebaseEvent <T>(e.Key, e.Object, FirebaseEventType.InsertOrUpdate, FirebaseEventSource.Online)) .Concat(Observable.Create <FirebaseEvent <T> >(observer => this.InitializeStreamingSubscription(observer)))) .Do(next => { }, e => this.observable = null, () => this.observable = null) .Replay() .RefCount(); } return(this.observable); }
/// <summary> /// Starts observing the real-time Database. Events will be fired both when change is done locally and remotely. /// </summary> /// <returns> Stream of <see cref="FirebaseEvent{T}"/>. </returns> public IObservable <FirebaseEvent <T> > AsObservable() { if (!this.isSyncRunning) { this.isSyncRunning = true; Task.Factory.StartNew(this.SynchronizeThread, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } if (this.observable == null) { var initialData = Observable.Return(FirebaseEvent <T> .Empty(FirebaseEventSource.Offline)); if (this.Database.TryGetValue(this.elementRoot, out OfflineEntry oe)) { initialData = Observable.Return(oe) .Where(offlineEntry => !string.IsNullOrEmpty(offlineEntry.Data) && offlineEntry.Data != "null" && !offlineEntry.IsPartial) .Select(offlineEntry => new FirebaseEvent <T>(offlineEntry.Key, offlineEntry.Deserialize <T>(), FirebaseEventType.InsertOrUpdate, FirebaseEventSource.Offline)); } else if (this.Database.Count > 0) { initialData = this.Database .Where(kvp => !string.IsNullOrEmpty(kvp.Value.Data) && kvp.Value.Data != "null" && !kvp.Value.IsPartial) .Select(kvp => new FirebaseEvent <T>(kvp.Key, kvp.Value.Deserialize <T>(), FirebaseEventType.InsertOrUpdate, FirebaseEventSource.Offline)) .ToList() .ToObservable(); } this.observable = initialData .Merge(this.subject) .Merge(this.GetInitialPullObservable() .RetryAfterDelay <IReadOnlyCollection <FirebaseObject <T> >, FirebaseException>( this.childQuery.Client.Options.SyncPeriod, ex => ex.StatusCode == System.Net.HttpStatusCode.OK) // OK implies the request couldn't complete due to network error. .Select(e => this.ResetDatabaseFromInitial(e)) .SelectMany(e => e) .Do(this.SetObjectFromInitialPull) .Select(e => new FirebaseEvent <T>(e.Key, e.Object, e.Object == null ? FirebaseEventType.Delete : FirebaseEventType.InsertOrUpdate, FirebaseEventSource.OnlineInitial)) .Concat(Observable.Create <FirebaseEvent <T> >(observer => this.InitializeStreamingSubscription(observer)))) .Do(next => { }, e => this.observable = null, () => this.observable = null) .Replay() .RefCount(); } return(this.observable); }