Understanding anvil.server.session

I’m attempting to register a few server functions dynamically - something similar to:

import anvil.server
from functools import partial

def _greeter(greeting, name):
    print(f"{greeting}, {name}")


def register_callables():
    for greeting in ["Hello", "Hi", "Welcome"]:
        func = partial(_greeter, greeting)
        name = f"say_{greeting.lower()}"
        anvil.server.callable(name)(func)

register_callables()

That gives me three registered server functions - say_hello, say_hi and say_welcome which will each take a name argument and print the relevant greeting.

However, register_callables is called each time a call is made to any of the resulting functions.

Two questions…

  1. I have persistent server enabled. Why is register_callables being called every time I make any server call? Shouldn’t that happen once per session?

  2. In an attempt to check whether it has already been run within a session, I tried using anvil.server.session but that is None at the point where register_callables is called. Why is that?

1 Like

Hi @owen.campbell,

This approach seems reasonable (albeit advanced).

Yes, that does sound odd! With Persistent Server enabled, Server Modules are imported only once at interpreter startup, and the interpreter is then reused. The sample code you’ve written calls register_callables() once at module load time, which ought to run them only once.

Then again, your sample code does not have any print() calls or other way to tell that register_callables() is being called on every call, which means it must have been simplified from the “real thing”. I would double-check whatever complexities you have simplified away for this example! It might be worth coming up with a minimum cloneable example to reproduce the issue.

This is because any given interpreter might be used to serve multiple sessions (indeed, multiple sessions simultaneously). That’s the whole point of Persistent Server - you don’t need to load all your code into a new interpreter every time a new user visits your site! As a result, anvil.server.session is a thread-local value that is only defined during a call to a server function.

2 Likes

MWE gets added to today’s todo list…

And, of course, I can’t make the MWE behave the same way! It’s all working just as I’d expect.

This one could take a while to narrow down…

I think this is to do with the Python version.

If I use 3.10, all works perfectly but if I’m on Basic Python 3, I get the repeated registration.

Here’s a clone link:

That’s from my personal account where I don’t have persistent server available but if you switch that on and then swap the python version around, you should see it misbehaving.

Oh, yes! Persistent Server and Basic Python 3 don’t mix (the PyPy sandbox can’t do multithreading, so there’s no way for one instance to handle multiple requests). 3.10 or Full Python are your best options!

1 Like