Is it safe to just subscribe to Publishers in the assembly phase and leave it at that? - project-reactor

I've asked in Gitter already but looks like it's not too active these days..
I was curious, is it safe to use such constructs in production code:
private Mono<Void> someHandler() {
someService.registerPlayer(internalPlayer)
.subscribe();
return Mono.empty();
}
and then just use this Publisher from WebFlux controller method, for example?
do we have anything in the official documentation about it? All the examples I could find in the Reference, seem to be examples of calling reactive code from blocking code and observing behavior.
I guess this Disposable returned here will be GC-ed quite soon, right?
and what would be the right way to achieve similar result (emitting on the outer Publisher without having to wait till the inner Publisher completes; but making sure it's completed nevertheless)

If I understand you correctly, then it is basically a fire-and-forget scenario, but nothing prevents you from using additional operators on that chain to process the results.
If by "to beconfident that the subscription will complete" you mean "do something if it is completed successfully" or "do something if it is completed with error" then:
If you want to start some processing in a separate thread and return immediately, and also be confident in completion of that sepapate processing, then you can use both subscribeOn() and put some operators to that chain to handle the results of success or errors of that processing, just as you do when you build any reactive chain.
To handle the results you can use, for example, .map(), doOnNext(), flatMap(), switchIfEmpty(), etc., whatever fits your requirements,
To handle errors, you can use, for example, onErrorResume(), onErrorContinue(), onErrorMap(), onErrorReturn(), doOnError(), etc., whatever fits your requirements.
Here is an example how it would look like:
private Mono<Void> someHandler() {
someService.registerPlayer(internalPlayer)
// handle results
.doOnNext(...)
// handle errors
.orErrorResume(...)
// the whole subscription process will happen on the thread provided by the Scheduler you specified
.subscribeOn(Schedulers.boundedElastic())
.subscribe();
// return immediately
return Mono.empty();
}

Related

How to handle blocking calls when using reactor in a JAX-RS-powered server?

To process HTTP requests, we have to make blocking calls (e.g. JDBC calls) as part of a Mono/Flux-based process. Our current plan looks something like this:
// I renamed getSomething to processJaxrsHttpRequest
CompletionStage<String> processJaxrsHttpRequest(String input) {
return Mono.just(input)
.map(in -> process(in))
.flatMap(str -> Mono.fromCallable(() -> jdbcCall(str)).subscribeOn(fixedScheduler))
.flatMap(str -> asyncHttpCall(str))
.flatMap(str -> Mono.fromCallable(() -> jdbcCall(str)).subscribeOn(fixedScheduler))
.toFuture();
}
where fixedScheduler is used concurrently across HTTP requests.
We were hoping to get some feedback on this strategy for handling block calls within a decent number of fluxes. Of course, we understand that if all our requests were flowing through these blocking calls then we might as well not use reactor (outside of the admittedly nice processing API).
Update: Thanks bsideup for this answer. However, I should have been a little more specific with my questions.
My overall question is how to effectively have a blocking call used across multiple fluxes were these fluxes can be created/subscribed to in large numbers. We tried the suggested approach, but it results in an explosion of threads and quickly OOMs. So we are thinking to use a shared scheduler. So.. here are my questions.
Is using a shared scheduler (fixedScheduler) what you would suggest in the situation I describe? If not, will you point me in any directions?
If using a shared scheduler is good, would this be a good implementation of it: Schedulers.newParallel("blocking-scheduler", maxNumThreads)?
Update 2: Just dug a big on Schedulers#newParallel and realize that won't work since it 'rejects' blocking calls.
Really appreciate any tips!
While subscribeOn is indeed one way of handling blocking calls and your usage is okay, you can as well use publishOn.
It moves processing to the provided Scheduler, unless other publishOn is specified:
CompletionStage<String> getSomething(String input) {
return Mono.just(input)
.map(in -> process(in)) // process must be non-blocking, or go after publishOn
.publishOn(Schedulers.boundedElastic())
.map(::jdbcCall)
.flatMap(str -> asyncHttpCall(str))
.publishOn(Schedulers.boundedElastic())
.map(::jdbcCall)
.toFuture();
}
As you can see, you can continue using async calls too. Just make sure you're not blocking non-blocking schedulers (in that example, I use publishOn again after flatMap because asyncHttpCall may complete from non-blocking scheduler)

How to deal with checking for valid state in every method call

I have encountered some code that looks like this.
member this.Send (data:array<byte>) =
if tcpClient.Connected then
// Send something.
member this.Open () =
if not tcpClient.Connected then
// Connect.
It's a potential bug hive with constantly checking to see if the TcpClient is connected before performing an operation on it.
A similar problem would be to check whether or not something is null before performing an operation on that something.
What is the general approach to dealing with this?
I was thinking along the lines of a monad that abstracts this boring checking away.
EDIT:
Potentially I can write many methods that each will have to check if we are connected.
member this.SendName name =
if tcpClient.Connected then
// Send name
member this.ThrottleConnection percent =
if tcpClient.Connected then
// Throttle
member this.SendAsTest text =
if tcpClient.Connected then
// Send as text.
So, it depends on whether you want to do the check inside the wrapper class or outside of it. Doing the check inside the class, I don't see how a computation expression is really relevant; you're not binding operations.
A workflow expression would only be useful if you're doing the check outside the wrapper class (i.e. from the calling function). If you create a connected builder together, the resulting code would look like
connected {
do! wrapper.Send(..)
do! wrapper.Throttle(..)
do! wrapper.SendAsTest(..)
}
However, that is really no simpler than
if wrapper.connected do
wrapper.Send(..)
wrapper.Throttle(..)
wrapper.SendAsTest(..)
So, kind of, what's the point, right?
It'd make more sense if you had multiple tcpClient wrapper objects and needed them all to be connected within your workflow. That's more what the "monadic" approach is for.
connected {
do! wrapper1.Send(..)
do! wrapper2.Throttle(..)
do! wrapper3.SendAsText(..)
}
However, specific to your example of doing the checks inside the wrapper class, like I said earlier, monads would not be applicable. One neat approach to that specific problem would be to try mimicking some preconditions like the following link http://laurent.le-brun.eu/site/index.php/2008/03/26/32-design-by-contract-with-fsharp. I don't know if it's much more intuitive than the if statements, but if you're looking for an fsharp-y way of doing things interestingly, that's the best I can come up with.
Ultimately your existing code is about as compact as it gets. Presumably not all of your functions would start with the same if statement, so there's nothing unnecessarily repetitive there.

Is this MVC Fire and Forget approach bad Design?

I have a controller's action that performs a task and at the end, it sends a confirmation e-mail to the user. The e-mail part of it is not very important, so I do not want to make my action break if the sending of the e-mail throws an exception, and I don't want my HTTP response to wait for the e-mail to be sent either. I want this to be a fire and forget thing.
In a nutshell, this is how I approached it:
public async Task<ActionResult> MyAction(){
// Do stuff
await DoStuff();
Thread sendEmailThread = new Thread(SendEmail);
sendEmailThread.Start();
return result;
}
private async void SendEmail(){
await smtpClient.SendMessageAsync();
}
Is this approach proper?
It is not a good idea to start a new Thread whenever a new email is arrived.
Alternative Approach (especially for Email)
We normally run a background scheduling system behind the application. For example, Quartz.NET
Then we queue email in a queue (or database), and let the background thread pick up from queue (or database), and preform the process.
By doing so, we can re-send emails if SMTP has an error.
It's unnecessary to start a new thread for sending the email as that method will return as soon as the async operation is kicked off and the thread will end before the operation is complete.
Async operations do not use a thread so you are best off to just return a Task from that method and await it. Async void returning methods are a bad idea as well as no exceptions propagate out of them and you can't tell when the operation is completed. See Best Practices in Async programming for more details.
If you really want to do a fire and forget task, see Stephen Cleary's blog on the subject.
I can't give you a direct solution but the fire and forget thing is implemented by open source eCommerce solution for asp.net and is called nopCommerce. I really love their solution, i just wanted to share it with you.
Here is the codeplex code;
Go to Src -> Libraries -> Nop.Services -> Tasks
https://nopcommerce.codeplex.com/SourceControl/latest#src/Libraries/Nop.Services/Tasks/TaskManager.cs
Now have a look at the TaskManager class. You can check the demo online here.
Go to Admin Panel -> System Menu -> Schedule Tasks
Explanation
They are using this class as queue emails, keep alive, clear caching, exchange rates auto update and deleting many other things. And it works exactly you wanted. If any exception occurs, it will just retry and it won't stop or break the app. You can check the demo.

Synchronization in ActionScript

Despite my best efforts, I am unable to produce the kind of synchronization effects I would like to in ActionScript. The issue is that I need to make several external calls to get various pieces of outside information in response to a user request, and the way items will be laid out on the page is dependent on what each of these external calls returns. So, I don't care that all of these calls return asynchronously. However, is there any way to force some amount of synchronization on ActionScript, so that at least calling the method for doing the final layout and placement of items on the page is dependent on all of my calls finishing?
If I understand the question right, event listeners are probably your best bet. Most loader classes throw an Event.COMPLETE message when they finish doing everything behind the scenes. If you wrote those external calls, it would be easy to dispatch a complete event at the end.
So when you make all these external calls, have a function that listens to when those calls complete. This function would keep track of how many calls have been made, and when there's none left to run, continue building your layout.
Rough Sketch to explain below:
var numProcesses:int = 0;
slowthing.addEventListener(Event.COMPLETE,waitForSlowest);
numProcesses++;
slowthing.load();
quickThing.addEventListener(Event.COMPLETE,waitForSlowest);
numProcesses++;
quickthing.load();
function waitForSlowest(e:Event)
{
numProcesses--;
if(numProcesses == 0)
finalizeLayout();
}

Can a 'while loop' be used in actionscript to monitor an event dispatch?

I am creating an action script library.I am calling some APIs which parses some xml and gets me the result. It dispatches an Event.COMPLETE when the parsing is done. I want to monitor whether this event is dispatched in some while loop like "while(eventnotdispatched)"
is it possible? I know the other way would be to addeventlistener. But please let me know if the other thing is possible.
Thanks
NO, it is not possible. Actionscript is single threaded. Thus while you are waiting in your while loop, that is the only thread running, and the process you are waiting for can never complete. This is why everything is done with events, so that's what you should use. If you need to update your display periodically while you are waiting for something to complete...again, use events. Create a Timer object which generates a TIMER event every so often, and use that to make your updates.
EDIT: Davr is right, you would not be able to use the while loop like this. You would need a timer.
Yes, it is possible to poll for it. BUT you will still need to create an event listener. It will work something like this:
private var loadCompleted = false;
private var timer:Timer= new Timer(1);
private function onInitCompleted(event:Event):void
{
timer.addEventListener(TimerEvent.TIMER, timerHandler);
timer.start();
}
private function loadCompleteEventHandler(event:Event):void
{
loadCompleted = true;
...
}
private function timerHandler()
{
if(!loadCompleted)
{
... // stop the timer or something.
timer.stop();
}
}
Please note, this is VERY BAD code. I would NEVER use it in production because Actionscript is a event driven language. There should be absolutely NO REASON for you to need to do this. Whatever you are trying to do could be accomplished using another method much simpler. Tell me what you are trying to accomplish with this and I will present a better solution.
Sorry for yelling, it's late and I am sleepy.
Doing that means forcing a synchronous model of execution on the underlying asynchronous model (that works with callbacks).
What are you trying to achieve exactly, and why not use a callback?
I agree with the statements about it probably being a bad idea and a while loop will certainly not work this way in ActionScript. However, there may be legitimate reasons for doing what you are attempting to do. Only you can prevent bad code. Instead of judging, I'll just get to an answer for your question.
First I'm going to make an assumption, that what you really want to do is monitor a property and for some reason the API for this object does not dispatch an event when this property changes. I'm making this assumption because if you have the event available, I assume you would just use the event.
So... you have an object weirdXmlObj with a property loaded that defaults to false but goes to true when the XML is loaded.
In this case with slight modifications the code posted by CookieOfFortune would in fact work. You wouldn't need the loadCompleteEventHandler function (which was never attached anyway) and in the timer handler you would simply check if( weirdXmlObj.loaded ) and then branch however you wanted to.
Ah but there may be a simpler way, depending on what you are doing.
If you have a display object handy. (i.e. something that makes sense, not just some random object.) You can attach your code to the stage's EnterFrame event instead of using a timer.
myDisplayObject.stage.addEventListner(Event.ENTER_FRAME,frameEnterHandler);
A couple of things to be aware of:
You don't really even need to go to the stage level, all display objects support the EnterFrame event, but it's a nice place to attach the event listener.
You really should keep whatever the function calls to a minimum. In particular the actual frameEnterHandler function should do nothing more than do the if( weirdXmlObj.loaded ) check.
You are attempting to circumvent event-driven programming, which is not a good idea. This is often the case when someone approaches from an older model and does not yet have a good frame of reference to appreciate the elegance of event-driven programming.
Events are your friends. They work very well. Your loadCompleteHandler is all that is required. Want to do something else in response? Add the call in that handler:
private function loadCompletedHandler(event:Event):void
{
waitingObject.fileWasLoadedSoGoDoThatThing();
}
There is no need to make it any more complicated than that. No need for a semaphore or a loop to check the semaphore. Unnecessary environmental semaphores can break the encapsulation that could shield you from unwanted side effects.

Resources