2.x: Custom stream types
See original GitHub issueIntended as a discussion
We often find ourselves creating an observable somewhere and exposing it later. While this is fine for local construction+usage, we lose important behavioral information about upstream behavior when we expose these downstream. Two large examples of where we run into this are around threading and BehaviorSubject
-backed Observables.
- For threading, some streams might implicitly be acting on a specific scheduler. For instance, Retrofit 1 (and optionally on 2) will
subscribeOn
the returned stream before returning it to a background scheduler of some sort. We have some internal APIs for local storage that do the same. This information is lost to the consumer, who may either not observe on a main thread if necessary or try to force a background thread not knowing that they’re already on one. - For subjects, the behavior is useful information to the consumer but we don’t want to expose it as a Subject directly to avoid leaking its API and allowing downstream consumers to call their own events. The “behavior” portion is often an important detail that leads to subtle bugs when not actively accounted for.
For threading, one might expose the observable downstream as a “BackgroundObservable” of sorts. For BehaviorSubject-backed ones - BehaviorObservable. It would probably be shallow at best, but the only other thing I can think of to solve this would maybe be with annotations, which isn’t as nice as leveraging the type system.
My early thinking would be to basically copying how ObservableHide
works, and impose our own tooling (lint, error-prone, etc) to try to enforce some level of protection if we recognize that a returned observable exhibits traits like what I mentioned above. Would be curious to know if and how others have handled this case. We have over a hundred engineers using a monorepo with extensive Rx APIs, so good documentation about the behavior of APIs is essential. A hide-style approach still induces some overhead though, and operators like map
still upconvert the type to Observable
even though it doesn’t change the behavior of the underlying stream (i.e. customObservable.map(_ -> stuff())
should ideally still be recognized as a CustomObservable
type).
Issue Analytics
- State:
- Created 7 years ago
- Comments:7 (7 by maintainers)
I am blind
Alright, going to close this. Think
to()
and the approach above is probably going to get us the best mileage for now. Thanks for the discussion all