@Override public Iterator<ChangeNotification<T>> iterator() { if (isDone()) { return EMPTY_ITERATOR; } try { notificationSubject.pause(); return _newIterator(); } finally { notificationSubject.resume(); } }
@Override public final void onNext(ChangeNotification<T> notification) { // Since we pause notifications during iterator creation, we will not get an onNext when iterator creation is in progress. addNotification(notification); }
@Override public final void onCompleted() { done = true; clearAllNotifications(); // Completion == shutdown, so after this, there isn't anything to be done. }
protected Index(final Interest<T> interest, final InitStateHolder<T> initStateHolder, final Subject<ChangeNotification<T>, ChangeNotification<T>> realTimeSource) { super(new OnSubscribe<ChangeNotification<T>>() { @Override public void call(Subscriber<? super ChangeNotification<T>> subscriber) { // We need to buffer all the changes while the init state is replayed. // Because new instance holder updates will be added while we replay them, they will be // partially visible by the subscriber. When we replay buffered real time updates, // they may overlap with what was already sent from the init holder. // TODO can we make this buffering cheaper? final PauseableSubject<ChangeNotification<T>> realTimeSubject = PauseableSubject.create(); realTimeSubject.pause(); realTimeSource.subscribe(realTimeSubject); realTimeSubject.mergeWith(Observable.from(initStateHolder).doOnCompleted(new Action0() { @Override public void call() { realTimeSubject.resume(); } })).subscribe(subscriber); } }); this.interest = interest; this.notificationsSubject = initStateHolder.getNotificationSubject(); this.notificationsSubject.subscribe(initStateHolder);// It is important to ALWAYS update init state first otherwise, we will lose data (see class javadoc) this.notificationsSubject.subscribe(realTimeSource); }
@Override public final void onError(Throwable e) { done = true; // Since, any one interested in this source will also be interested in the real time source, // we leave it to the real time source to propagate this error. We just return an empty iterator // whenever the upstream source is done (i.e. onComplete/onError on this instance) clearAllNotifications(); // Completion == shutdown, so after this, there isn't anything to be done. }