[Done] Print warning when two server callables have the same name

Please show a warning in the app console when a server callable is defined twice in the same app.

This should (especially) include callables defined in dependencies.

PROS
You don’t risk to define a callable that has already been defined in the same module, in another module or in a dependency.

CONS
I don’t see any. I don’t see a good reason for defining two callables with the same name, and if you really want, you will need to live with that warning appearing when the app loads.


While debugging a failure in an app, I found out that the get_rows server callable was failing because the app was calling a callable with the same name defined in a custom component the app depends from.

This explains why all the the server callable in all the apps made by an ex-colleague follow an ugly naming convention: AppName_ModuleName_function_name. I had forgotten. Now I remember.

4 Likes

This should definitely be doable if they decide to implement it, when the server uses a function they call register() it literally writes the name as a key to a dictionary called registrations.

You could just check if the key already exists and raise the warning.

I know people do sometimes register the same function twice, like if they want a fallback to an uplink registered callable, but it’s just a warning so why not raise it anyway.

Only alternative I can think of is a warning in the editor (through linting), since I can’t think of a good reason the same callable name should be used twice within the exact same server. Or both things.

You found the only reason (so far) why the same callable could be defined more than once. There could be multiple uplinks, all registering the same function with the same name. And that function could also be defined in a server module.

So perhaps the warning message should not include callables defined in uplinks. Or perhaps it should. It’s just a warning, visible only in the IDE, and that’s a little piece of information that doesn’t hurt anyway.

The behavior of callable registered in both uplink and server modules is predictable: the uplink always wins, and multiple uplinks are randomly picked. There is also a setting to manage that: “Send server calls from other environments to this uplink”.

The behavior of a callable registered in multiple server modules or in dependencies, is not predicatable.

This other FR is related: Show list of registered functions in account

1 Like

Great strategy, broadly applicable. For example, I’m having to do the same sort of thing with names of (shared) database tables. To represent the physical hierarchy, something like AppName_DatabaseName_TableName. (A logical/functional hierarchy might use different terms, in a different order.)

I’ve tried to abbreviate, but with so much else to keep track of, I can no longer remember the abbreviations. In cases like this, explicit really is better than implicit.

1 Like

I agree!

I have 4 different Projects tables.

According to app A a project is different from what it is for app B. When I made app A I didn’t think about my colleague’s app B (or viceversa). Everything was great until the day app C needed both tables. So now I have tables with duplicated names, and different apps sharing the same tables with different python names.

IT’S A MESS!!

I could now think of a better name for each table, now that I know that they represent slightly different incarnations of a project. But, since ain’t broke won’t fix it, I will keep living with this mess for the foreseeable future.
:person_facepalming:

Perhaps being able to identify the tables with their optional parent / namespace / context would help?
Something like:

projects.search()
database1.projects.search()
app2.database1.projects.search()

which feels similar to SQL syntax:

SELECT name FROM ...
SELECT projects1.name, projects2.name FROM ...

Food for another FR?

I think so.

In the meantime, note that the Anvil name of a table is global, across your entire account. Change it in one App, and that change is visible across all your Apps. This is independent of its local (per-database) Python name. So changing the global name shouldn’t break any code.

I have a standing Feature Request for access to the Account’s complete set of Tables, across all Apps and Databases. Without it, you can’t get a complete picture anywhere. I suppose one could manually create a tracking app, but it will always be extra work to maintain, and forever at risk of being out-of-sync with reality (as Anvil defines it).

Same principle applies to anvil.server.callables, I should think.

2 Likes