Two users' function calls interfering with each other?

was this ever resolved? I have two Anvil users passing variables to functions and got errors suggesting functions calls are interfering each other.

[split from this thread]

Can you provide more details?

I’m doubtful the kind of interference you describe is possible, unless perhaps you have a persistent server running and are using global variables in your server modules? My working assumption is that different users can only interact via Data Tables (and transactions are the way to avoid interference there).

p.s. Welcome to the forum!

The background behind this is that the file path is the variable passed and the functions were called through uplink from Jupyter Notebook, And I got the following error when Anvil app was run by another user:
PackageNotFoundError: Package not found at 'C:\Users*.docx’
at C:/Users/
/Anaconda3/lib/site-packages/docx/opc/phys_pkg.py, line 31
called from C:/Users/
/Anaconda3/lib/site-packages/docx/opc/pkgreader.py, line 32
called from C:/Users/
/Anaconda3/lib/site-packages/docx/opc/package.py, line 128
called from C:/Users/
**/Anaconda3/lib/site-packages/docx/api.py, line 25
called from , line 115

Sorry I am coming back to this query because lack of alternatives.

Yes, uplink, specifically anvil.server.wait_forever() is async code.

If you do not also write thread safe code, you can definitely run into this problem.

Mutable use of globals, singleton credentials or connection objects etc. will all have you running into this issue whenever it is possible for these objects to be used “at the same time”. (by being called more than once before the function that uses them has completed running)

One way to get around this is by having your calling code request some sort of lock that will tell all other requests to wait until that global lock is released. This is a very old-school way to do it and can run into many of its own issues.

Other ways also include having your client interact with a requests table, submitting its requests to that table, and using timers to check if that table has been updated with the results.
On the Notebook side, instead of anvil.server.wait_forever(), you run your own while loop with a sleep component to check the anvil table for new requests and handle them one at a time, writing back the results of each request to the correct row.

All of this introduces more complication including having to check if a request is “hanging” and taking forever, (this would block all other requests from ever completing) or other things like garbage collection if the “request” is never received by a client and sits in the table forever, eventually making the table run out of space.

2 Likes

With anvil.server.wait_forever() in your Uplink program, each incoming call (to the program’s remotely-callable functions) runs in its own thread. So any shared state – including global variables, database connections and files on disk – is asking for trouble. A new invocation can start before an earlier one ends.

In my case, I create a unique, new token (a database table row) to represent the incoming request, and queue up the requests for execution by an entirely separate program.

3 Likes