Webflux: OnErrorResume after repeats are exhausted is not being triggered - reactive-programming

I am trying to execute the code after repeat exhaustion using onErrorResume but onErrorResume is not being trigger.
Here is the code sample
Mono.just(request)
.filter(this::isConditionSatified)
.map(aBoolean -> performSomeOperationIfConditionIsSatified(request))
.repeatWhenEmpty(Repeat.onlyIf(i -> true)
.exponentialBackoff(Duration.ofSeconds(5)), Duration.ofSeconds(10))
.timeout(Duration.ofSeconds(30)))
.delaySubscription(Duration.ofSeconds(10)))
.onErrorResume(throwable -> {
log.warn("Max timeout reached", throwable);
return Mono.just(false);
});
onErrorResume is never trigged. I am trying to use it as a fallback. My goal is if the repeat exhaustion is hit, return the false value.
My unit test complains of
expectation "expectNext(false)" failed (expected: onNext(false); actual: onComplete())
Any help or suggestion would be helpful.

since an empty source is valid by itself, repeatWhenEmpty doesn't necessarily propagate an exception after exhausting its attempts. The Repeat util from addons doesn't, even when the "timeout" triggers (as hinted in the timeout parameter's javadoc: "timeout after which no new repeats are initiated", ok that could be clearer).
since you're using repeatWhenEMPTY, I'm guessing that the empty case is always "irrelevant" to you and thus defaultIfEmpty(false) should be the acceptable solution.

Related

Gatling - Long Polling in a loop - asynchronous response - loop doesn't work as intended

This is my first question ever on this website, please bear with me patiently.
I'm trying to make an http long polling program for a project using Gatling. While crawling through many questions on stackoverflow, though I've been able to reunite separate concepts into a piece of syntactically correct code, sadly, it doesn't do what is intended to do.
When a status code of 200 is obtained after any request, the loop should break and the test would be considered as approved. If the status code is different to 200, it should keep the connection alive and polling, not failing the test.
When the .tryMax value is reached and all responses gave a status different to 200, the loop should break and the test should be considered as failed.
Using the difference operator (!=) doesn't work either, so then I took the decision to alternatively use .equals() and test the loop, to no avail.
Being new to both Gatling and Scala, I'm still trying to figure out what's wrong with this code, execution-wise:
def HttpPollingAsync() = {
asLongAs(session => session("statuss").validate[String].equals("200")) {
exec(
polling
.every(10 seconds)
.exec(
http("polling-async-response")
.post("/" + BaseURL + "/resource-async-response")
.headers(headers)
.body(RawFileBody("requestdata.json"))
.check(
status.is(200),
jsonPath("$.status").is("200"),
jsonPath("$.status").saveAs("statuss")
))
).exec(polling.stop)
}
}
val scn = scenario("asyncpolling")
.tryMax(60){
exec(HttpPollingAsync())
}
setUp(scn.inject(atOnceUsers(10))).protocols(httpProtocol)
The exception I get when running this piece of code is (it's just syntactically correct):
Exception in thread "main" java.lang.UnsupportedOperationException: There were no requests sent during the simulation, reports won't be generated
at io.gatling.charts.report.ReportsGenerator.generateFor(ReportsGenerator.scala:49)
at io.gatling.app.RunResultProcessor.generateReports(RunResultProcessor.scala:59)
at io.gatling.app.RunResultProcessor.processRunResult(RunResultProcessor.scala:38)
at io.gatling.app.Gatling$.start(Gatling.scala:81)
at io.gatling.app.Gatling$.fromArgs(Gatling.scala:46)
at io.gatling.app.Gatling$.main(Gatling.scala:38)
at io.gatling.app.Gatling.main(Gatling.scala)
So there's some part when it's never accessed or used.
Any bit of help or pointing me in the right direction would be appreciated.
Thank you!
an asLongAs loop condition is evaluated at the start of the loop - so on your first execution the condition will fail due to there being no session value for statuss.
the doWhile loop provides checking at the end of the loop.

How to trigger handle_info due to timeout in erlang?

I am using a gen_server behaviour and trying to understand how can handle_info/2 be triggered from a timeout occurring in a handle_call for example:
-module(server).
-export([init/1,handle_call/3,handle_info/2,terminate/2).
-export([start/0,stop/0]).
init(Data)->
{ok,33}.
start()->
gen_server:start_link(?MODULE,?MODULE,[]).
stop(Pid)->
gen_server:stop(Pid).
handle_call(Request,From,State)->
Return={reply,State,State,5000},
Return.
handle_info(Request,State)->
{stop,Reason,State}.
terminate(Reason,State)->
{ok,S}=file:file_open("D:/Erlang/Supervisor/err.txt",[read,write]),
io:format(S,"~s~n",[Reason]),
ok.
What i want to do:
I was expecting that if I launch the server and would not use gen_server:call/2 for 5 seconds (in my case) then handle_info would be called, which would in turn issue the stop thus calling terminate.
I see it does not happen this way, in fact handle_info is not called at all.
In examples such as this i see the timeout is set in the return of init/1.What I can deduce is that it handle_info gets triggered only if I initialize the server and issue nothing (nor cast nor call for N seconds).If so why I can provide Timeout in the return of both handle_cast/2 and handle_call/3 ?
Update:
I was trying to get the following functionality:
If no call is issued in X seconds trigger handle_info/2
If no cast is issued in Y seconds trigger handle_info/2
I thought this timeouts can be set in the return of handle_call and handle_cast:
{reply,Reply,State,X} //for call
{noreply,State,Y} //for cast
If not, when are those timeouts triggered since they are returns?
To initiate timeout handling from gen_server:handle_call/3 callback, this callback has to be called in the first place. Your Return={reply,State,State,5000}, is not executed at all.
Instead, if you want to “launch the server and would not use gen_server:call/2 for 5 seconds then handle_info/2 would be called”, you might return {ok,State,Timeout} tuple from gen_server:init/1 callback.
init(Data)->
{ok,33,5000}.
You cannot set the different timeouts for different calls and casts. As stated by Alexey Romanov in comments,
Having different timeouts for different types of messages just isn’t something any gen_* behavior does and would have to be simulated by maintaining them inside state.
If one returns {reply,State,Timeout} tuple from any handle_call/3/handle_cast/2, the timeout will be triggered if the mailbox of this process is empty after Timeout.
i suggest you read source code:gen_server.erl
% gen_server.erl
% line 400
loop(Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug) ->
Msg = receive
Input ->
Input
after Time ->
timeout
end,
decode_msg(Msg, Parent, Name, State, Mod, Time, HibernateAfterTimeout, Debug, false).
it helps you to understand the parameter Timeout

How to make Protractor's browser.wait() more verbose?

In Protractor tests I call many times browser.wait method for example to wait once the particular element will appear on the screen or it will be clickable.
In many cases tests passes on my local machine, but does not on other.
I receive very generic information about the timeout which doesn't help me a lot to debug / find a source of issue.
Is it possible to make a browser.wait more verbose, for example:
if at least defaultTimeoutInterval will elapse when waiting for particular element, will it be possible to console.log information about the element that it tried to wait for,
take a screenshot when the timeout error occurs,
provide full call stack when timeout appears in browser.wait
If the main issue is that you don't know for which element the wait timed out, I would suggest writing a helper function for wait and use it instead of wait, something like:
wait = function(variable, variableName,waitingTime){
console.log('Waiting for ' + variableName);
browser.wait(protractor.ExpectedConditions.elementToBeClickable(variablename),waitingTime);
console.log('Success');
}
Because protractor stops executing test after first fail, if wait timed out, console won't print success message after failing to load a certain element.
For screenshots I suggest trying out protractor-jasmine2-screenshot-reporter, it generates an easily readable html report with screenshots and debug information on failed tests (for example, in which code line the failure occured).
Look into using protractor's Expected Condition, you can specify what to wait for and how long to wait for it.
For screenshots there are npm modules out there that can take a screenshot when a test fails. This might help.
browser.wait returns a promise, so catch the error and print/throw something meaningful like:
await browser.wait(ExpectedConditions.visibilityOf(css), waitingTime).catch((error) =>
{
throw new CustomError(`Could not find ${css} ${error.message}`)
});

xmlStreamReader Evaluation Error: Wrapped java.lang.IllegalStateException

During debugging my DW script, When I debug xmlStreamReader I have tried to look for .hasNext() which will give me TRUE
but getting .next() will terminate the script, thus
I am not able to continue from .next() point after that.
I also faced the same problem, I have made the hasNext as Number variable.
The issue is with this -> orderXMLReader.next() == XMLStreamConstants.START_ELEMENT
Here orderXMLReader.next() return String value and it is compared with Number constant

protractor what does the timeout in expected conditions stand for?

Protractor: Version 1.8.0
browser.wait(EC.presenceOf(element), 3000);
what exactly does the 3 seconds stand for? and is there an error thrown when 3 seconds have passed and element cannot be found? or does the test just continue?
I ran a test with:
element(by.id('#input')).sendKeys('foo');
browser.wait(EC.presenceOf(element(by.xpath(BAD-LOCATOR)), 3000));
element(by.id('#input')).sendKeys('bar');
BAD-LOCATOR is just a xpath referencing a element that doesn't exists. but upon evaluating this line, the test waits beyond this time until it hits the jasmine defaultTimeoutInterval timeout (I set for 25sec). Why does it not fail in 3 secs since the promise did not get resolved in 3secs? I'm expecting the wait() to fail and the 2nd sendKeys command to execute since its next in control flow.
So the above block of code will print 'foo' into the textbox and on the next command wait until the jasmine timeout to error out (Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.). I'm expecting an error within 3secs. 'bar'never gets printed.
It's the time out, i mean after 3 seconds if the element isn't present until now it will time out.
For the jasmine error you are getting i suggest that you add the call back
describe("long asynchronous specs", function() {
beforeEach(function(done) {
done();
}, 1000);
You can also refer to Jasmine Asynchronous Support