What I’m trying to do:
I’m learning how to make good use of home-grown Dependencies. This Dependency grew from a desire to consolidate nearly-identical code from multiple Apps. Only a handful of App-specific parameters exist, but they do need to be passed to the Dependency.
The trick is, the Client code is calling the Dependency directly. We can’t trust the Client to pass these parameters; it might have been hacked. And the Dependency can’t directly call the App’s server-side code, to get them. (I suppose it could do its own anvil.server.call
to get them, but that would be slow.)
But both App and Dependency share anvil.server.session
, so that looked promising. All we need is a way for the App code to insert values, before the anvil.server.callable
function starts running.
What I’ve tried and what’s not working:
Setting a value in anvil.server.session
immediately on startup of the App’s server-side code.
Code Sample:
"""Server Module init_server.
Sets App-specific values (context) for our Dependencies to read.
"""
import anvil.server
anvil.server.session['app_name'] = 'mgmt'
In principle, since this code executes unconditionally, before the first anvil.server.callable
starts, it should work in all cases:
- regular server instances, persistent instances, or background tasks
- server instances started on a different physical computer, than the session originally used, due to load-balancing.
- My reasoning: The previously-persisted contents of
anvil.server.session
might not make it from the old computer to the new. (This is a really hard scenario to test!) But even in that case, the code above would still ensure proper app-specific values.
- My reasoning: The previously-persisted contents of
When the Client does its first anvil.server.call
(i.e., into the Dependency), the App’s server module above is executed, as planned, before invoking the anvil.server.callable
. But the above code produces the following error messages:
AttributeError: 'NoneType' object has no attribute '__setitem__'
at /downlink/anvil/_threaded_server.py:97
called from init_server, line 6
So the session
member exists, but it isn’t yet a dict
. It will become one later, with values from the current session (if accessible on this server), so any values I might put in here would (probably) get overwritten.
Bad timing, on my part.
Plausible workarounds
One way around this is for the Client to never call the Dependency directly. Instead, the App should intercept the necessary calls, so that they can pass the right (App-specific) context along to the Dependency.
I might yet do this, as it is simple, and accommodates a wide variety of conditions. For example, if any context (deliberately) varies, from one version, branch, or runtime Environment, to the next (e.g., an App Version number), the Dependency still receives the correct details.
This is much more difficult if the Dependency is called directly, from the Client.
Lesson learned
The best thing, in the long term, is to limit the amount of context that the Dependency needs.