[SOLVED] AsyncPostFromString is blocking

I am using

AsyncPostFromString

to do a non-blocking request.

This request is a logger service for analytics and we collect basic information to help troubleshoot customers with issues.

The service works as expected but there is an issue with

AsyncPostFromString

as it is suppose to be non-blocking but that does not seem to be the case. I have the service wait for 5 seconds to verify it’s non-blocking but it always waits until the logger request is complete.

My logs show:

Channel Initialized - START Logger
Waiting for response...
Sucessful Response
END Logger
InitTheme Start - InitTheme End - MainContentList Start - MainContentList End

I am expecting:

Channel Initialized - START Logger
Waiting for response...
InitTheme Start - InitTheme End - MainContentList Start - MainContentList End 
Sucessful Response
END Logger

It is obvious that it is waiting until the request is complete. The issue here seems to be the while loop. When I remove it, I get what I expect but then I have no way to gracefully handle a rogue request and that could cause many issues.

Hopefully I am missing something simple.

I am using

request.setport(port)

and I tested also with

request.setMessagePort(port)

but no change.

Thanks for any help you can provide.
Jeremy

The method I am using is below:

Sub Logger(event, value="")
    print "START Logger"
    
    ' Get Device Info
    di = CreateObject("roDeviceInfo")
    ' Make sure there is an active connection
    if (di.GetLinkStatus()) then 
        
        ' Define timeout
        timeout = 2000
        
        ' Define URL
        url="https://my.super.secret.url"
        
        ' Get Device Info
        di = CreateObject("roDeviceInfo")
        
        ' Create transfer object
        request=createobject("roURLTransfer")
        request.SetCertificatesFile("common:/certs/ca-bundle.crt")
        request.InitClientCertificates()
        request.AddHeader("Content-Type", "application/json")
        request.seturl(url)
    
        ' Event monitoring
        port=createobject("roMessagePort")
        request.setport(port)
    
        ' Timer for timeout
        timer=createobject("roTimeSpan")
        timer.mark()
        
        ' Build data object
        data = {
            "entityName": "Roku App",
            "entityEvent": event,
            ' Device info (https://sdkdocs.roku.com/display/sdkdoc/ifDeviceInfo)
            "entityID": di.GetDeviceUniqueId(),
            "entityMeta": {
                "modelDisplayName": di.GetModelDisplayName(),
                "model": di.GetModel(),
                "softwareVersion": di.GetVersion(),
                "displayType": di.GetDisplayType(),
                "displayMode": di.GetDisplayMode(),
                "displayAspectRatio": di.GetDisplayAspectRatio(),
                "timezone": di.GetTimeZone(),
                "ip": di.GetIPAddrs(),
                "locale": di.GetCurrentLocale(),
                "countryCode": di.GetCountryCode(),
                "timeSinceLastKeyPress": di.TimeSinceLastKeypress(),
                "videoPlaybackResolution": di.GetVideoMode(),
                "isHDMIConnected": di.IsHDMIConnected(),
                "audioOutputChannel": di.GetAudioOutputChannel(),
                "activeNetwork": di.GetLinkStatus(),
                "connectionType": di.GetConnectionType()
            }
        }
        
        ' Only add value if provided
        if (value <> "") then
            data.entityValue = value
        end if
    
        ' Format to JSON
        jsonData = FormatJson(data)
        print "jsonData: " ; jsonData
    
        ' Send Requests
        request.AsyncPostFromString(jsonData)
    
        print "Waiting for response..."
        
        ' Gracefully handle the request
        while true    
            msg=wait(100,port) '100 millisecond pause
            if type(msg)="roUrlEvent" then
       
                if msg.getresponsecode()=200 then
                    print "Sucessful Response"
                    exit while
                else
                    print "Response Code" ; msg.getresponsecode()
                    request.asynccancel()
                end if
                
            end if
            ' Set timeout
            if timer.totalmilliseconds() > timeout then
                print "timeout exceeded"
                exit while
            end if
        end while
        
    else
        print "No active Internet connection. Logger is being skipped."
    end if
    
    print "END Logger"
End Sub

What it means to say that AsyncPostFromString is asynchronous is that it returns immediately, before the request is complete. Your code verifies that this happens, since the “waiting for response” message appears and shows that AsyncPostFromString has returned. If you want to do other activity while waiting for the post to complete, you should call request.SetMessagePort with the same port you use in your main loop, rather than creating a new port. Then add the roUrlEvent handling code to your main loop.

–Mark

Thanks, I knew it had to be something simple.

One last question… I can no longer do a timeout since this is in the main loop. There are multiple roUrlEvent’s so there isn’t a way (that I noticed) to identify which is which. Is this something I need to handle in the code or does roUrlEvent handle this internally? Personally, I’d like to log the event for later use but that’s not really an issue.

Thanks again

“SoN9ne” wrote:
One last question… I can no longer do a timeout since this is in the main loop. There are multiple roUrlEvent’s so there isn’t a way (that I noticed) to identify which is which. Is this something I need to handle in the code or does roUrlEvent handle this internally? Personally, I’d like to log the event for later use but that’s not really an issue.
roUrlTransfer has a GetIdentity() method that returns a unique identifier for that request. roUrlEvent has a companion GetSourceIdentity() method that returns that same ID, so you can identify which request the event is for.

Awesome, thank for your help

Your question helps me to make a POST request. Thanks.