Wild Race Conditions in Kinetic - Anyone seen this?

I’ve encountered 2 race conditions today.

#1

I’ve had a kinetic-function calling and getting a string.
I then used a row-update to grab {actionResult.returnObj} and put that in a dataview. (Both hung on and off the success branch)
It would not do it.
Debug showed it was in the actionResult dataview.

However, if I moved the row-update to an event-next or a button, it would work fine.


#2

For what I was wanting to do, I changed tactics, and went with a merging dataset, and then decided to use row-find with the row index to another dv to find my row, and then a row-current-set with the dv.field etc. It would not do it…

Again, doing the row-current-set in an event-next or a button worked fine…

Music Video Wtf GIF

For some more context, I believe this is entirely down to the Kinetic Functions reporting success, when they have not completed their actions.

I moved my event-next to after my functions returned on my dataset based ones, and did the row-find, row-current-set, and console-write all in line, and it all worked flawlessly.

But if there is no break between the function “success” and the next chain, it dies a quick death.

team america vomit GIF

A “success” branch should be synchronous.

Yes. Success branch is queued on response received but actionResult hydration is late and row-update eval is early. This should be well documented but is not, AFAIK.

I believe row-update is intentionally eager. Values are immediately evaluated then the action is queued. Meanwhile actionResult is still hydrating.

I believe a reliable pattern is function > success set-variable = actionResult > success > row-update. Or bind function response to a dataview to avoid row-update. Or delay.

I believe this is similar to your post. Honestly there were a lot of words so I may be on a tangent here…

I’ve had some timing issues before as well, but I think it was things not behaving well during the loading phase. Will probably never be documented.

I do believe you are correct.

I have a couple of tests to run today to see why I haven’t encountered this before.

I created a BPM that calls a BPM form giving the user the option to cancel or proceed on Post in costing WB. The kinetic form would send the toast popup that it was posted even when it was canceled…

Similar issue where it reads as a success even when it was not.

So, I created an event in the application instead and am forcing users to use kinetic for this :slight_smile:

Similar root cause?

Further analysis of row-update shows it’s not a timing thing.

I think the erp-function action drops returnObj is it’s of type object.

processRestResponse(s) {
    if (!s || !s.length)
        return;
    const r = s[0].result.result;
    this.processParameterResponse(r),
    this.processReturnObjResponse(r),
    this.processFunctionResponse(s[0], r),
    this.processMessageResponse(s[0], r)
}
processParameterResponse(s) {
    null == s.parameters || (s.parameters.errorsOccurred ? trans.set("sysGlobalVariable.errorsOccurred", s.parameters.errorsOccurred) : Object.keys(s.parameters).forEach(r => {
        "object" != typeof s.parameters[r] && trans.set("actionResult.".concat(r), s.parameters[r])
    }
    ))
}
processReturnObjResponse(s) {
    null != s.returnObj ? "object" != typeof s.returnObj &&
     trans.set("actionResult.returnObj", s.returnObj)  // ← never fires if returnObj is an object
     : trans.set("actionResult.returnObj", null)
}
processFunctionResponse(s, r) {
    this.isFunctionRequest(s) && Object.keys(r).forEach(p => {
        trans.set("actionResult.".concat(p), r[p])
    }
    )
}

it like it only wants top-level response keys or scalars :person_shrugging:

No, if there is a delay, it works, so it is timing.

And same behavior if using a different output parameter.

Yeah I think you’re right a delay helps because of a likely async commit gap between processRestReponse > trans.set(…) and what trans.get(…) sees when Row-Update runs.

:thinking: OR maybe current row isn’t yet set on actionResult.

What do you get with this immediate console-log in success branch?

trans.dataView("actionResult").viewRow

-1 = cursor hasn’t advanced
0 = curDataRow is first row

-1 before function -1 immediately after

run again 0 then 0, because it has a row, and has advanced

I set the row myself, row-current-set, does not work, so I set it with javascript, and it still won’t pull it unless it’s in another event. (with console-write etc)

I can pull it with js in the same event.

What a shitshow.

I’m familiar. It’s kinda how life goes in the age of “web dev is easy now so don’t engage experienced programmers”.

Epicor’s developers are using the same tools, they’re experiencing the same issues, which are escaping into production, which means it’ll be an increasing thorn in developer’s sides, and hopefully they’ll have more ability than users to lobby for fixing things.

couple more debug tests if you’ve not tried already

raw data table length: (1 = row exists)

trans.dataView("actionResult").dataTable.data.length

direct table read bypassing curDataRow: (a value proves there’s an index zero, just not accesbile via cursor)

trans.dataView("actionResult").dataTable.get("returnObj", 0)

again, immediate console-log inside success branch

ps - curious whether reading on the js-eval path differs from the binding-resolution path (used by row-update)

#_ trans.get("actionResult.returnObj") _#

I don’t know if this applies, but here you go.

I’m doing a bunch of dashboards where we’re using the rest-kinetic widget to execute the BAQ and pass parameters.

In the execution parameters, we pass the parameter and whether it’s empty like this:

{
	"ExecutionParameter": [
		{
			"ParameterID": "QuoteNum",
			"ParameterValue": "{FilterDV.QuoteNum}",
			"IsEmpty": "{TransView.QuoteNumIsEmpty}",
			"ValueType": "int"
		}
	]
}

So we do a row update right before the rest-kinetic widget to set the “isempty” part of the parameter.

I did find a race condition happening sometimes, so I always go from row update to rest widget like this:

My hypothesis is that it forces the row update to finish before proceeding, and seems to work for me.

FWIW, YMMV. No warranty expressed or implied.

Joe

Yeah, in my case, on success was the default, and made no difference.