How does Anvil know what uplink to disconnect?

I have two Anvil apps MainApp and OtherApp.

From the MainApp’s UI a user calls uplink code in UplinkApp. UplinkApp starts the uplink with

anvil.server.connect(uplinkkey1)
:
anvil.server.wait_forever()

Within this code I use uplink calls to OtherApp. These are short-lived and hence use a context manager:

@contextmanager
def open_anvil_connection(uplink_key):
    anvil.server.connect(uplink_key)
    yield
    anvil.server.disconnect()

with open_anvil_connection(uplinkkey2):
    anvil.server.call('some_func')

How does Anvil know that it should close only the uplink to OtherApp and not MainApp?
(As you may have guessed I’m having trouble with disconnected Uplinks).

As far as I know, you can’t have one uplink script connect with two apps at the same time.

Perhaps you can first disconnect from the first app, then connect to the second, do your job, then disconnect and reconnect to the first one, but… I have no clue about what happens if you do that from a server.callable function that has been called by an app.

For example:

  • App1 calls a function in Uplink
  • Uplink, which is waiting forever, starts the function
  • While App1 is waiting for Uplink to say “your function has finished its job, here is the result”, Uplink disconnects from App1 and connects to App2
  • App1 is still waiting, but it lost the connection…

Will App1 keep waiting and be seamlessly satisfied after Uplink reconnects?
I doubt.
This is just my feeling, I’ve never tried, you can try and see if I’m wrong.

1 Like

you should probably be running two instances of the python interpreter instead of one. If the code is the same, maybe use an argument value (sys.argv[]) to change what uplink key will be used at runtime.

If you need them to communicate, you should be using some other method, there are so many out of the box solutions that avoid all the edge cases you are running into.
(anvils use of async, the GIL, global values in general, registered functions, etc etc :brain: :hammer: )

Now that i’m thinking about it, someone besides me who actually knows how to use the multiprocessing module and pooling features of python could probably get away with having one “main” uplink, and spinning off a pool that uses a context manager to open, then close a completely separate io connection to anvil.
All from within one script.

…it might be like swatting a fly with a cannon though, depending on what you are really trying to do.

When using databases, and asking for a database connection, the request usually returns a connection object. This is what allows multiple connections to multiple databases at the same time. You can explicitly identify each connection and tell it to close.

With

there is a single, implicit, global connection object. This means that an Uplink program has at most one such object at a time, and so it can can receive calls on behalf of only one App at a time.

Oh, that’s unfortunate. If only anvil.server.connect returned a connection object for the cases where that is relevant.
I can imagine having just one global ‘listening’ uplink, and 1 or more ‘sending’ uplinks.

I guess I’ll have to convert my uplinks to HTTP apis.