Provide explicit ways to prevent concurrency

Right, I feel like we’re really talking past each other, @junderhill and @stefano.menci. It seems you are both acknowledging that Anvil’s current behavior (in which JavaScript’s non-blocking, asynchronous nature bleeds through any time there is a server call) is not ideal. But, as experienced Anvil/JavaScript programmers, you have learned how to cope with this (undocumented) behavior with practices like:

That may seem simple to you, but for me as a newbie Python programmer coming to Anvil a few years ago trying to build my first app, it was bewildering to have this implicit concurrency be causing errors.

(Expand for more on my specific experience.)

My main form had a status attribute and a seconds_left attribute. In the “normal” status, the seconds_left was meant to be irrelevant, but in the waiting status, the seconds_left was meant to count down to zero, at which point a server call would be triggered to report that the user was unresponsive. A Timer called every 5 seconds would check whether the status was waiting and seconds_left was <= 0. (I also had another Timer whose job it was to just increment down the seconds_left toward zero, once every second, when the status was “waiting.”)

A button click would trigger the status change from “normal” to “waiting” and reset seconds_left to something like 30 seconds, along with sending some information to the server. Usually this worked fine. But occasionally when the button was clicked, the user would be unexpectedly be immediately shown the notification saying that the timer had run out.

Just as @p.colbert describes, I had trouble replicating the error, which made it difficult to debug. I made a number of changes to the code based on false theories of what was going wrong, wasting time and unnecessarily complicating the code.

Eventually, though, I did hit on the idea that the issue was caused by changing self.status to “waiting” before setting self.seconds_left to a positive number, so if the 5-second Timer happened to tick between those two attribute changes (which was apparently made more likely by a server call I had placed in between), it would find self.status == "waiting" and self.seconds_left == 0, wrongly inferring that the user was unresponsive. Thus I was finally able to prevent the issue (most of the time, at least–but I still wasn’t clear on how the implicit concurrency was working, so I wasn’t sure I had fully fixed it).

It has taken me years (of part-time coding/learning) to come to understand programming best practices–and even just terminology–well enough to formulate this feature request (as poorly worded as it still probably seems to those with more expertise). Anvil’s default behavior should (further) protect its users from this complexity, if possible.

2 Likes