Prevent observables from being started unless another observable finishes it's job - reactive-programming

In my app client uses services backed by Observables. Each service call is session based, so that a session has to be started before a business-service method can be called.
In order to init session I made an Observable that does it. My problem is that whenever client uses more than one business-service in parallel, session initialization gets duplicated. Client code is session-agnostic. I need a way to init session in such a way that the session observable only gets called once(when the first business-service method gets called). Basically all subsequent business-observers have to wait for condition(session initialization). Can you draw a pattern for it?
Client code would look like:
protected void onCreate(Bundle savedInstanceState) {
itemService.getItems(10).subscribe(new Observer<List<Item>>() {..});
userService.getProfile().subscribe(new Observer<List<Profile>>() {..});
}
While there're 2 calls, I need to make the session Observable execute once only and make business Observables wait for the session initialization to complete and then start doing its' job.
Thanks.

If the session initialization is an Observable, then you can delay all other Observables that depend on it, using the delay operator with the session initialization Observable as parameter: http://reactivex.io/RxJava/javadoc/rx/Observable.html#delay%28rx.functions.Func1%29

Since you already have a session Observable implemented, one possible solution would be to convert it to an AsyncSubject. It would execute only once and would emit only the last item (or only item) to each subscriber.
Depending on how your session initialization code works, it may be more elegant to use one of the Async operators such as Async.start() or Async.startFuture() to create your session observable.

Related

GCD serial queue like approach using swift async/await api?

I am adopting the new async/await Swift API. Things work great.
Currently in my apps I am using GCD serial queues as a pipeline to enforce tasks to happen serially.
For manipulating data of some critical models in the app I use a serial queue accessible from anywhere in the app:
let modelQueue = DispatchQueue(label: "com.myapp.updatemodelqueue")
Anytime a model needs to modify some model data I dispatch to that queue:
modelQueue.async {
// ... model updates
}
With the new async/await changes I am making I still want to force model actual updates to happen serially. So, for example, when I import new model data from the server I want to make sure they happen serially.
For example, I may have a call in my model that looks like this:
func updateCarModel() async {
let data = await getModelFromServer()
modelQueue.async {
// update model
}
}
Writing that function using that pattern however would not wait for the model update changes because of the modelQueue.async. I do not want to use modelQueue.sync to avoid deadlocks.
So then after watching WWDC videos and looking at documentation I implemented this way, leveraging withCheckedContinuation:
func updateCarModel() async {
let data = await getModelFromServer()
await withCheckedContinuation({ continuation in
modelQueue.async {
// update model
continuation.resume()
}
})
}
However, to my understanding withCheckedContinuation is really meant to allow us to incrementally transition to fully adopt the new async/await Swift API. So, it does not seem to be what I should use as a final approach.
I then looked into actor, but I am not sure how that would allow me to serialize any model work I want to serialize around the app like I did with a static queue like shown above.
So, how can I enforce my model around the app to do model updates serially like I used to while also fully adopting the new await/async swift API without using withCheckedContinuation?
By making the model an actor, Swift synchronizes access to it' shared mutable state. If the model is written like this:
actor Model {
var data: Data
func updateModel(newData: Data) {
data = newData
}
}
The updateModel function here is synchronous, it's execution is uninterrupted after it's invoked. Because Model is an actor, Swift restricts you to treat it as if you are calling an asynchronous funtion from the outside. You'd have to await, which results in suspension of your active thread.
If in case you'd want to make updateModel async, the code within will always be synchronous unless if you explicitly suspend it by calling await. The order of execution of multiple updateModel calls is not very deterministic. As far as you don't suspend within the updateModel block, it is sure that they execute serially. In such case, there is no use making the updateModel async.
If your update model code is synchronous you can make your model actor type to synchronize access. Actors in swift behave similar to serial DispatchQueue, they perform only one task at a time in the order of submission. However, current swift actors are re-entrant, which means if you are calling any async method actor suspends the current task until the async function completes and proceeds to process other submitted tasks.
If your update code is asynchronous, using an actor might introduce data race. To avoid this, you can wait for non-reentrant actor support in swift. Or you can try this workaround TaskQueue I have created to synchronize between asynchronous tasks or use other synchronization mechanisms that are also created by me.

DispatcherTimer in MVVM with Prism?

I'm working on a multi-platform MVVM app, and I want to keep the ViewModel platform-agnostic.
I need to make use of DispatcherTimer or any other timer. Since the DispatcherTimer is not part of .NET Standard/Core, I was wondering if there are better alternatives to use so I can keep the VM clean of plat-specific code (I want it to depend only on .NET Core)?
The way it works is that the ViewModel implements an interface that exposes an event that the View is listening to, and responds to it accordingly.
The timer raises this event upon each tick.
The first option would be to just use classic Timer, which does fire on a non-UI thread and then just use Dispatcher manually in the consuming view. This is however not that convenient.
Other option would be to provide an interface, that consumers of your library could implement, which would have a method like RunOnUiThread(Action action) and which you would just use to make sure the view-specific code runs on the UI thread.
The best solution would probably be to get inspiration in Prism itself. For example the EventAggregator in the library can publish events on the UI thread - it first captures the current thread's synchronization context (see here on GitHub):
var syncContext = SynchronizationContext.Current;
This must be done for example during the View model construction, on the UI thread. And then you can invoke an action on this UI synchronization context even from another thread (see here on GitHub):
syncContext.Post((o) => action(), null);
This way you could just use one of the .NET Standard Timer classes and from their callback then use the SynchronizationContext to run an action on UI thread.
The other way you should know about DispatcherTimer is sometimes we may use DispatcherTimer to do something alternately.
We can use Task.Delay to replace DispatcherTimer sometimes.
Such as we need to run the code A every 5 seconds.
public async void Foo()
{
while (true)
{
// run a every 5 seconds
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(5));
A();
}
}
private void A()
{
}
And the A will run in the main thread if the main thread calls the Foo and I think you
can consider using this method in the framework.

Castle IoC - do not add interceptor when object injected

How can I add interceptor to an interface registration so that it is executed when I call a method from resolved instance (IoC.Resolve) but not when I use an instance that has been injected (as constructor argument) from the inside of my class/object?
In our infrastructure we add an interceptor that opens/closes nhibernate session for every call but then the injected proxy instance will open a session inside of a session and cause deadlocks if you query the same entity in outer and inner session.
I've had a look at this and I don't see any easy way to change the behavior of the interceptor depending on the context in which it is called.
What you could do is create an interceptor that wraps a component with a singleton lifetime that creates a single session and returns the same session while it is not closed. When trying to create a second session, it returns the initial session and increments a sessionCreated counter. When trying to close a session it decrements the sessionCreated counter and only closes it if it is 0

dart js-interop FunctionProxy callback relationship to js.context

I have a Dart js-interop callback that in turn takes a javascript callback as an argument. The dart callback implementation looks like this:
void callBackToDartCode(String query, js.FunctionProxy completionCallback) {
js.context.completionCallback = completionCallback;
doSomethingAscyn(query).then(
(result) {
// hand the query result back to the javascript code
js.context.completionCallback(js.map(result));
});
This works. The key to making this work is to save the FunctionProxy in the js.context so that it is available when it comes time to execute it in the async "then" method. This line of code is important:
js.context.completionCallback = completionCallback;
If that's not done then the completeCallback is not retained and hence cannot be called when the async operation completes.
I have not seen examples like this and I am not sure I have really done this properly.
It raises questions:
How do I disassociate "completeCallback" from js.context after I've called it? Does it remain associated with js.context forever?
It appears there will be conflicting use of the name "completionCallback" within js.context if multiple async operations are in progress at the same time. That strikes me as a common problem. Does js-interop have a way to deal with that or is it my job to manage that?
With js-interop all proxies are scoped to prevent memory leaks. This means that Proxy will lost its JS object reference at the end of its associated scope. If scoped((){}) function is not use explicitely a lazy scope is initialized the first time an interop operation is done and the scope is automatically closed at the end of the current event loop. If you want to make a Proxy to live longer than its associated scope, you have to retain it. This can be done with js.retain(proxy). Once your proxy is no longer needed, you can release it with js.release(proxy).
Thus your code should be :
void callBackToDartCode(String query, js.FunctionProxy completionCallback) {
js.retain(completionCallback);
doSomethingAscyn(query).then(
(result) {
// hand the query result back to the javascript code
completionCallback(js.map(result));
// completionCallback is no longer used
js.release(completionCallback);
});
}
About your question about disassociate "completeCallback" from js.context you could have done it with js.deleteProperty(js.context, "completeCallback")

Autofac scope in web app in timer

I use autofac web integration and it works just great to resolve lifetime bound components. But one piece of code is invoked from timer and I'm getting null reference exception somewhere in Autofac.Integration.Web.ContainerProvider.AmbientRequestLifetime.get(). Obviously it is because in timer there is no HttpContext and lifetime can not be obtained.
According to documentation I need to invoke "container.BeginLifetimeScope" and use this lifetime to resolve my component. But the component is quite low-level (networking, messaging) and it has no access to asp's Global object to access container object. Global object also has no access to so low-level component to inject container manually.
To make the problem more difficult, this component can be invoked from web pages and need web request lifetime and it needs to be invoked from timer with manually constructed lifetime (or IDispose+using would be fine too).
How do I deal with situation when 2 types of life time scope is required?
Two things might help you get started in the right direction.
First, builder.Register(...).InstancePerLifetimeScope() will give you 'per-request' as well as 'per-custom-lifetime' scoping.
Second, if you're kicking things off under a timer, create a new lifetime scope manually at the entry point of the timer method wherever it happens to be:
void OnTimer()
{
using (var timerScope = ApplicationContainer.BeginLifetimeScope())
{
var someComponent = timerScope.Resolve(...);
someComponent.DoWork();
}
}
Here, the ApplicationContainer is the one you built in Global.asax when the web request started up - you need to find some way to get at it when the timer ticks.