diff --git a/src/myfasthtml/auth/routes.py b/src/myfasthtml/auth/routes.py
index 9c99494..26a4cc6 100644
--- a/src/myfasthtml/auth/routes.py
+++ b/src/myfasthtml/auth/routes.py
@@ -16,6 +16,7 @@ from ..auth.utils import (
logout_user,
get_user_info
)
+from ..core.instances import InstancesManager
def setup_auth_routes(app, rt, mount_auth_app=True, sqlite_db_path="Users.db", base_url=None):
@@ -181,6 +182,9 @@ def setup_auth_routes(app, rt, mount_auth_app=True, sqlite_db_path="Users.db", b
if refresh_token:
logout_user(refresh_token)
+ # release memory
+ InstancesManager.clear_session(session)
+
# Clear session
session.clear()
diff --git a/src/myfasthtml/controls/InstancesDebugger.py b/src/myfasthtml/controls/InstancesDebugger.py
index 5c9d8c7..7428b0d 100644
--- a/src/myfasthtml/controls/InstancesDebugger.py
+++ b/src/myfasthtml/controls/InstancesDebugger.py
@@ -8,12 +8,13 @@ class InstancesDebugger(SingleInstance):
super().__init__(parent, _id=_id)
def render(self):
+ s_name = InstancesManager.get_session_user_name
instances = self._get_instances()
nodes, edges = from_parent_child_list(
instances,
- id_getter=lambda x: f"{InstancesManager.get_session_id(x.get_session())}-{x.get_id()}",
- label_getter=lambda x: x.get_prefix(),
- parent_getter=lambda x: x.get_parent().get_id() if x.get_parent() else None
+ id_getter=lambda x: x.get_full_id(),
+ label_getter=lambda x: f"{s_name(x.get_session())}-{x.get_prefix()}",
+ parent_getter=lambda x: x.get_full_parent_id()
)
for edge in edges:
edge["color"] = "green"
diff --git a/src/myfasthtml/core/instances.py b/src/myfasthtml/core/instances.py
index 7bab51f..cd74baa 100644
--- a/src/myfasthtml/core/instances.py
+++ b/src/myfasthtml/core/instances.py
@@ -86,6 +86,13 @@ class BaseInstance:
def get_prefix(self) -> str:
return self._prefix
+ def get_full_id(self) -> str:
+ return f"{InstancesManager.get_session_id(self._session)}-{self._id}"
+
+ def get_full_parent_id(self) -> Optional[str]:
+ parent = self.get_parent()
+ return parent.get_full_id() if parent else None
+
@classmethod
def compute_prefix(cls):
return f"mf-{pascal_to_snake(cls.__name__)}"
@@ -177,10 +184,33 @@ class InstancesManager:
return "** UNKNOWN USER **"
return session["user_info"].get("id", "** INVALID SESSION **")
+ @staticmethod
+ def get_session_user_name(session):
+ if session is None:
+ return "** NOT LOGGED IN **"
+ if "user_info" not in session:
+ return "** UNKNOWN USER **"
+ return session["user_info"].get("username", "** INVALID SESSION **")
+
@staticmethod
def reset():
InstancesManager.instances.clear()
+ @staticmethod
+ def clear_session(session):
+ """
+ Remove all instances belonging to the given session.
+ :param session:
+ :return:
+ """
+ session_id = InstancesManager.get_session_id(session)
+
+ InstancesManager.instances = {
+ key: instance
+ for key, instance in InstancesManager.instances.items()
+ if key[0] != session_id
+ }
+
@staticmethod
def dynamic_get(parent: BaseInstance, component_type: str, instance_id: str):
logger.debug(f"Dynamic get: {component_type=} {instance_id=}")
diff --git a/src/myfasthtml/core/network_utils.py b/src/myfasthtml/core/network_utils.py
index 0d2074a..bb23880 100644
--- a/src/myfasthtml/core/network_utils.py
+++ b/src/myfasthtml/core/network_utils.py
@@ -147,7 +147,7 @@ def from_parent_child_list(
id_getter: Callable = None,
label_getter: Callable = None,
parent_getter: Callable = None,
- ghost_color: str = "#ff9999",
+ ghost_color: str = "#cccccc",
root_color: str | None = "#ff9999"
) -> tuple[list, list]:
"""