perf: Avoid checking server script map (#29057)

If I have to hazard a guess, 99% API calls are not server scripts, then
why check it first and pay the costs?

This PR first checks if method is a real method in python code and if
it's not found then only attempts to fetch it from server script map.

I'll revert this if I can bring the costs in acceptable limits with
client-side caching.
This commit is contained in:
Ankush Menat 2025-01-06 13:10:20 +05:30 committed by GitHub
parent 675ca02942
commit 55a55e7f7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 9 deletions

View file

@ -9,6 +9,7 @@ Note:
"""
import json
from contextlib import suppress
from typing import Any
from werkzeug.routing import Rule
@ -38,10 +39,15 @@ def handle_rpc_call(method: str, doctype: str | None = None):
method = hook
break
method_exists = False
with suppress(Exception):
method_exists = bool(frappe.get_attr(method))
# via server script
server_script = get_server_script_map().get("_api", {}).get(method)
if server_script:
return run_server_script(server_script)
if not method_exists:
server_script = get_server_script_map().get("_api", {}).get(method)
if server_script:
return run_server_script(server_script)
try:
method = frappe.get_attr(method)

View file

@ -2,6 +2,7 @@
# License: MIT. See LICENSE
import os
from contextlib import suppress
from mimetypes import guess_type
from typing import TYPE_CHECKING
@ -66,10 +67,15 @@ def execute_cmd(cmd, from_async=False):
cmd = hook
break
method_exists = False
with suppress(Exception):
method_exists = bool(get_attr(cmd))
# via server script
server_script = get_server_script_map().get("_api", {}).get(cmd)
if server_script:
return run_server_script(server_script)
if not method_exists:
server_script = get_server_script_map().get("_api", {}).get(cmd)
if server_script:
return run_server_script(server_script)
try:
method = get_attr(cmd)

View file

@ -291,20 +291,20 @@ class TestOverheadCalls(FrappeAPITestCase):
def test_ping_overheads(self):
self.get(self.method("ping"), {"sid": "Guest"})
with self.assertRedisCallCounts(10), self.assertQueryCount(self.BASE_SQL_CALLS):
with self.assertRedisCallCounts(9), self.assertQueryCount(self.BASE_SQL_CALLS):
self.get(self.method("ping"), {"sid": "Guest"})
def test_ping_overheads_authenticated(self):
sid = self.sid
self.get(self.method("ping"), {"sid": sid})
with self.assertRedisCallCounts(10), self.assertQueryCount(self.BASE_SQL_CALLS):
with self.assertRedisCallCounts(9), self.assertQueryCount(self.BASE_SQL_CALLS):
self.get(self.method("ping"), {"sid": sid})
def test_list_view_overheads(self):
sid = self.sid
self.get(self.resource("ToDo"), {"sid": sid})
self.get(self.resource("ToDo"), {"sid": sid})
with self.assertRedisCallCounts(24), self.assertQueryCount(self.BASE_SQL_CALLS + 1):
with self.assertRedisCallCounts(16), self.assertQueryCount(self.BASE_SQL_CALLS + 1):
self.get(self.resource("ToDo"), {"sid": sid})
def test_get_doc_overheads(self):