My use case is that I have many client app instances and one server app instance. Both apps are written in Anvil
Client instances need to send a message to the server, lets say it is:
client_id, message
What I have tried that does not work:
Using the anvil.server.connect() with the server’s client uplink key. connect() is not available from the anvil app
Making the server app a dependency of the client app. The call happens, but its context is the client app’s. ex: if the call references a table on the server, it can’t see it because it is trying to write to the client app’s database. Even print() statements go to the client app and don’t seem to execute on the server app.
I do not want to share data tables, or actually trust the client app in the server app code
I can imagine writing an http endpoint on the server and then calling it from the client, but I thought there might be a more “out of the box” way.
Sharing the data tables is the standard way. When you do this, combined with using the server app as a dependency, it’ll work.
However, it sounds like you have a non-standard setup to begin with (separating the client and server into two apps, having multiple deployments for client apps?). In that case, HTTP endpoints would work, but I’d question why you’re setting it up that way to begin with.
Many, if not most, Anvil apps contain both server-side and client-side code. The client-side code invokes the server-side code, and trusts it to do the right thing. The server-side code does not have to trust the client-side code.
An instance of the client-side code runs in each browser that opens the app. When the client code calls its server code, a client-specific server instance is spun up, temporarily, to execute the called server-side function.
Within the same app, instances can communicate with each other via the app’s database tables.
As @yahiakalabs points out, the standard way for instances of two different apps to communicate is via a shared database table. (This might be the only table that the two apps share.) This requires polling the table, periodically, for incoming messages, but is otherwise simple.
It sounds like you’re setting up a different kind of architecture, though. What problem(s) are you trying to solve, with this architecture? What requirements are you trying to fulfil?
I should have not used client and server as the descriptions of my apps.
Each customer has their own instance of “App A” in their own environment. So there are many instances of App A. (The reasons for this are historical, hard to change, and outside the scope of my question)
App B is a separate app that monitors events from all the instances of App A, so I wanted to be able to have App A send a message to App B when something noteworthy happens.
It sounds like the easiest way to do that is via a shared table. There are privacy issues with that as App A(customer 1) is not permitted to see rows that App A(customer 2) writes, but that feels solvable with careful implementation (or maybe user-row locking?).
Might be better for me to do http endpoints.
Thanks everyone. Hope this clears up what I’m trying to accomplish.
Update: I tried the shared database table, and it worked. I don’t like it, and I’m not sure why I don’t like it, but it definitely works.
As far as our security requirements, we control the source code for both applications, so we can handle it via a policy (ex: App A only writes to the table, never reads from it).
In Anvil’s model, Environments don’t contain Apps; Apps contain Environments! As described in Deployment Environments. Which is why your description feels “backwards” to me. I’m used to Anvil’s way of thinking and describing things.
The good news is that you don’t have to rely on policy alone. You can also explicitly set the server-side Permissions for that table, for each Database it appears in: