how to save into a variable and start a process at the same time?

I have a feature where the user clicks a link to run a process in the background and perform some actions. What I want to do is to display a message to the user while the PM is running so they know that something is going on. However, I found out that you can't do any other saves until the onSuccess is run. I want to run the following code.

a!dynamicLink(
showWhen: not(ri!inProgress),
value: true,
saveInto: {
a!save(ri!showMessage, true),
a!startProcess(
processModel: cons!WM_PM_SYNC_HOLDS_DATA,
processParameters: {
siteAcronym: ri!siteAcronym,
siteId: ri!siteId,
writeType: ri!writeType,
user: loggedInUser(),
lastSyncDate: ri!lastSyncDate
},
onSuccess: {
a!save(
ri!processInstance,
fv!processInfo.pp.id
)
},
onError: a!save(ri!error, "error")
),
}
),

In the code above, a!save(ri!showMessage, true) is not executed until the onSuccess() in the starProcess() is run even though it's outside of the startProcess. I've tried chaining the process and without any chaining and that save always waits for the PM on success or onError(). Is there a way to get around this? I know there is other ways like using a process report which is what I'm doing, I just want to know if this scenario is possible.

  Discussion posts and replies are publicly visible

  • 0
    Certified Lead Developer

    Unfortunately I don't think you're going to find a very good solution for this without changing up your desired design at least a bit.  One thing you could try is a 2-click approach, which can more gracefully handle certain situations like this where you might otherwise want one click to update the state of the local form in 2 separate ways several moments apart.

    Also I'd point out, in case you can pivot to using a!buttonWidget() instead of a link, the new feature in 21.2 in which you can turn on a "loading indicator", sorta handles this sort of thing inherently.  It doesn't exactly allow you to show a custom message, but it allows you to indicate to your user that activity is going on in the background (up until process chaining breaks).

  • I believe what is occurring here is that your form will not refresh until all of the saveInto's are complete, including the a!startProcess.  That would mean, unfortunately, you might not be able to achieve this exact scenario of having your interface re-evaluate in between a!save's.  How long roughly is this synch running?

    Without chaining, the onSuccess and onError (when applicable) should be executing as soon as the process starts (does so in my tests), thus will not give you access to any updated PV values that change down stream however, but you will have pp!id available.  With chaining, these evaluate after chaining is completed (however in my tests, it is maxing at around 50 chains even though we have our chaining limit increased to 100 via custom.properties...)

    One thought is to have your main process call a sub process asynchronously which does the synch, but you would lose access to some details then and you would need to auto refresh a variable that checks completion, or have a manual Refresh button available for the user.  And of course the shortest a!refreshVariable() setting is 30 seconds currently (..hoping we get access to shorter intervals in the future).

    Another thought is to combine some refreshing with a confirmMessage within a button containing these saves/synching, something like "Synch will begin now...form will update in 30 seconds...yadda yadda".

    Neither are as good for UX as your initial idea here, but just throwing some thoughts out there..

  • Also I'd point out, in case you can pivot to using a!buttonWidget() instead of a link, the new feature in 21.2 in which you can turn on a "loading indicator", sorta handles this sort of thing inherently.  It doesn't exactly allow you to show a custom message, but it allows you to indicate to your user that activity is going on in the background (up until process chaining breaks).

    Yes, definitely looking forward to this!  Would be a nice option in this scenario, cofirmMessage+loading indicator. 

  • One possible way might be to have the PM write a "I'm now running" value to a DB table, and have your interface have a refreshVariable (set to auto-refresh every 30s say) that is fetching that value from the DB, and then an interface widget that displays the appropriate message. When the process ends it can then change the value in the DB to a "I'm done" value, the refreshVariable will then eventually fetch that value and your interface widget can now display a different message.

  • 0
    Certified Lead Developer
    in reply to Stewart Burchell

    This is a good example of why the timer-based auto refresh should have much lower options than the current minimum of 30 seconds.  This sort of example would be best served by a 5 second refresh interval, for example.  A relatively trim query would have basically no negative impact on system performance by being run every 5 seconds.

  • Totally agree and this is the reason why I asked this question. We are using a refresh variable to pull from the process report. Unfortunately there is that instance when the user can run the process at the right as to make them wait an extra 30 seconds causing an unnecessary delay even though things have completed. It would be nice to have this updated  on a future release

  • Another case we tried was to have the 30 second refresh, but have that local variable also refresh on another variable change. So we chained the process model and updated a variable inside the onSuccess() to trigger the local variable refresh but that didn't quite behave as expected. Even after the onSuccess() was done and the reference variable changed, sometimes the timer would still take over and force it to wait longer.

  • Instinctively I'd want to flip the model and have the Server send the relevant event to the waiting client rather than client "polling" the server. I see there's something called SSE (https://ably.com/topic/server-sent-events) so will do some digging to see if this is on the radar/road-map.

  • This sound like a good idea. I think this would be the way. Instead of the client trying to guess when something happens, let the server inform the client when that something has happened. 

  • 0
    Certified Lead Developer
    in reply to Jose H.
    So we chained the process model and updated a variable inside the onSuccess() to trigger the local variable refresh but that didn't quite behave as expected.

    The issue here lies in Appian's behind-the-scenes variable value-setting execution (just based on what I've been able to observe from external evidence).  Sometimes chainings of updates like this fail to work how we expected, in seemingly unintuitive ways, because while we assume Appian will do everything in order, it really attempts to execute everything (or at least many of the things) all at once.