B4J Question How do I detect a Http_job has timed out when I use Wait For

JackKirk

Well-Known Member
Licensed User
Longtime User
I have a Http_job, the bare bones of the relevant code to execute it are:

B4X:
    Private XXX_job As Http_Job

    XXX_job.Initialize("List", Me)
    
    wrk_URI stuff here

    XXX_job.Download(wrk_URI)

    XXX_job.GetRequest.Timeout = 30 * DateTime.TicksPerSecond      'I know this is the default
    
    wrk_Authorization stuff here
 
    XXX_job.GetRequest.SetHeader("Authorization", wrk_Authorization)

    Wait For (XXX_job) JobDone (Job As Http_Job)

Occasionally this hangs on the Wait For - I am assuming it is timing out.

How do I detect this?

Thanks...
 
Last edited:

Ganiadi

Active Member
Licensed User
Longtime User
I have a Http_job, the bare bones of the relevant code to execute it are:

B4X:
    Private XXX_job As Http_Job
   
    XXX_job.GetRequest.Timeout = 30 * DateTime.TicksPerSecond      'I know this is the default

    Wait For (XXX_job) JobDone (Job As Http_Job)

Occasionally this hangs on the Wait For - I am assuming it is timing out.

How do I detect this?

Thanks...
Hi Jack

I do it using below code

B4X:
Private XXX_job As Http_Job 
    XXX_job.GetRequest.Timeout = 30 * DateTime.TicksPerSecond      'I know this is the default
    Wait For (XXX_job) JobDone (Job As Http_Job)
    If XXX_job.Success Then
       log("SUCCESS")
    Else
       Log("Error: " & XXX_job.ErrorMessage)
    Endif
End Sub
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
I do it using below code
Ganiadi, thanks for your interest but you are missing the point.

Execution never gets to the other side of the Wait For.
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
Execution never gets to the other side of the Wait For.
not with the code you posted above.

You are not sending any request here. Not a Get request and even not a Post or any other request.
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
not with the code you posted above.
DonManfred, as I said "bare bones" - the real code is some 500 lines with lots of comments and all sorts of checks - I can post an edited version but I don't think it will help with finding what is going on.

This is an occasional problem, I have log traced it to the Wait For never returning.

When I dig into the Http_Job, Http_Utils2_Service modules and the OkHttp library there does not appear to be a way to handle a timeout.

Can you see one?

If a timeout caused some error response from these then presumably the Wait For would fire and I would get a Success = False - but this is not happening.
 
Upvote 0

alwaysbusy

Expert
Licensed User
Longtime User
DonManfred, as I said "bare bones" - the real code is some 500 lines with lots of comments and all sorts of checks - I can post an edited version but I don't think it will help with finding what is going on.
Maybe just add the request itself to your code (it should not be runnable code), but at least we could see where the call itself is done. Maybe your are setting the timeout before the call (or maybe not, but it is guessing at this point). It has to be done after e.g. j.Download btw.
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
Maybe just add the request itself to your code
not with the code you posted above.

Ok, I have made the "bare bones" more elaborate in post #1

I'm a bit cagey with this because this code is part of the account creation code for my big project - I don't want to leave a trail for some deviant to hack into.

This particular code is doing a regular check to see if certain emails have arrived.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Something like this might be made to work but I'm not absolutely sure.
EDIT: Yes, I think it will work.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Also look at this
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
Something like this might be made to work but I'm not absolutely sure.
agraham, I could be wrong, but I think the example you reference actually adds a timeout capability to Astream_NewData which looks like it doesn't have a native timeout.

In the case I outlined in post #1 we seem to have a function that has a native timeout that does not appear to work - or at least I can't get it to work.

Before I started the thread I toyed with adding a Timer to fire if the Wait For didn't.

I don't like this because I couldn't find a way to cancel the Http_Job that was supposed to have timed out - and I wonder what sort of impact this would have on memory consumption if there are numerous Http_Jobs hanging in space.

Is there a way to cancel Http_Jobs? - Http_Job.Release just deletes a file.
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
Also look at this
I think I have similar comments to the previous post and I agree with Erel's comment in the thread you referenced:

"In most cases it is a mistake to create a layer above Sleep or Wait For. It makes things more complicated, it might add subtle bugs and it is unlikely to fit many use cases."
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
It does but it should be adaptable to any Wait For, with or without a native timeout.
What happens if you used a Timer override on a Http_Job that never completes?
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
The resumable sub class instance that is being waited on sits in memory waiting for an event on the message loop to restarts it. If the event never arrives then that instance object won't be garbage collected and will sit there occupying as small amount of memory and no CPU cycles. I haven't looked very deeply into the actual mechanism to know if theoretically it could be destroyed, Erel would need to comment on that as it would be done in low-level Java anyway.

However It is puzzling that your HttpJob doesn't time out when it should so prompting this discussion in the first place. Have you tried setting the timeout and invoking the download immediately before the wait for?
 
Upvote 0

JackKirk

Well-Known Member
Licensed User
Longtime User
However It is puzzling that your HttpJob doesn't time out when it should
I agree entirely - it seems to be a bug? - I am reluctant to report it as such because Erel regularly shoots my "bug reports" down in flames - but it might be the only way to get his attention.
Have you tried setting the timeout and invoking the download immediately before the wait for?
I don't think I can change the order of statements in post #1 - my understanding is that the statement:

XXX_job.GetRequest.SetHeader("Authorization", wrk_Authorization)

is what causes the job to fire - I could be wrong though.
 
Upvote 0

drgottjr

Expert
Licensed User
Longtime User
follow post #4 from https://www.b4x.com/android/forum/threads/okhttp-cancel-download.61239/
you'll have to do a little work to make it fit your scenario.

also, the failure to time out with ok is apparently not unknown.
ok provides 4 time out settings:

Java:
    OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(5, TimeUnit.SECONDS)
        .writeTimeout(5, TimeUnit.SECONDS)
        .readTimeout(5, TimeUnit.SECONDS)
        .callTimeout(30, TimeUnit.SECONDS)
        .build();
our okhttp.jar sets 3 of them. i've played around with setting them variously. anyway, the issue - when it occurs - is said to ignore all 4. you can follow the online discussion starting at google. at my last read, i didn't see a definitive resolution. or even a definitive explanation as to why it occurs at all.

ok also has an automatic retry feature which can be turned off (should that feature be involved). people who have experienced the failure to time out have turned the automatic retry off, the the hanging was not solved...

cancelling the socket connection with a modified okhttputils2 (per post above) and a timer would seem to be a way out.
 
Upvote 0

OliverA

Expert
Licensed User
Longtime User
XXX_job.GetRequest.SetHeader("Authorization", wrk_Authorization)

is what causes the job to fire - I could be wrong though.
No. The Wait For is what is causing the HTTP request to process. Please note: all statements between xxx.Download and the Wait For for that particular job must be blocking calls. Otherwise the event queue is processed and the download event occurs and may finish before you set up your Wait For. If that occurs, your Wait For will seem to hang, since the event that it is waiting for has already happened.
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
follow post #4 from https://www.b4x.com/android/forum/threads/okhttp-cancel-download.61239/
you'll have to do a little work to make it fit your scenario.

also, the failure to time out with ok is apparently not unknown.
ok provides 4 time out settings:

Java:
    OkHttpClient client = new OkHttpClient.Builder()
        .connectTimeout(5, TimeUnit.SECONDS)
        .writeTimeout(5, TimeUnit.SECONDS)
        .readTimeout(5, TimeUnit.SECONDS)
        .callTimeout(30, TimeUnit.SECONDS)
        .build();
our okhttp.jar sets 3 of them. i've played around with setting them variously. anyway, the issue - when it occurs - is said to ignore all 4. you can follow the online discussion starting at google. at my last read, i didn't see a definitive resolution. or even a definitive explanation as to why it occurs at all.

ok also has an automatic retry feature which can be turned off (should that feature be involved). people who have experienced the failure to time out have turned the automatic retry off, the the hanging was not solved...

cancelling the socket connection with a modified okhttputils2 (per post above) and a timer would seem to be a way out.
 
Upvote 0

TILogistic

Expert
Licensed User
Longtime User
You can add parameters to the builder, see the link
B4X:
Public Sub SetRequestTimeOut(ConnectTime As Long, CallTime As Long, ReadTime As Long)
    Dim jo As JavaObject = HttpUtils2Service.hc
    Dim builder As JavaObject = jo.RunMethod("sharedInit", Array("hc"))
    Dim TimeUnit As JavaObject
    TimeUnit.InitializeStatic("java.util.concurrent.TimeUnit")
    builder.RunMethod("connectTimeout", Array(ConnectTime, TimeUnit.GetField("MILLISECONDS")))
    builder.RunMethod("callTimeout", Array(CallTime, TimeUnit.GetField("MILLISECONDS")))
    builder.RunMethod("readTimeout", Array(ReadTime, TimeUnit.GetField("MILLISECONDS")))
    jo.SetField("client", builder.RunMethod("build", Null))
End Sub
 
Upvote 0
Top