Layout refresh latency bug revised

This commit is contained in:
=
2026-06-04 19:47:18 +08:00
parent f9c3f12aea
commit 7ac76aaee9
7 changed files with 567 additions and 11 deletions
+19 -3
View File
@@ -1,6 +1,6 @@
# -----------------------------------------------------------------------------
# Description: Flask backend API server for authentication, project management, PDK library access, layout preview, and GDS build endpoints.
# Inside functions: no_cache_response, login_required_json, wrapper, request_ip, record_action, safe_name, user_layout_root, project_root, cell_file_path, cell_svg_path, cell_routes_path, write_route_points_sidecar, project_gds_path, technology_manifest_path_for_project, current_pdk_root, scoped_pdk_root_for_project, pdk_root_for_request_project, project_meta_path, read_project_meta
# Inside functions: no_cache_response, login_required_json, wrapper, request_ip, record_action, safe_name, user_layout_root, project_root, cell_file_path, cell_svg_path, file_version, cell_routes_path, write_route_points_sidecar, project_gds_path, technology_manifest_path_for_project, current_pdk_root, scoped_pdk_root_for_project, pdk_root_for_request_project, project_meta_path, read_project_meta
# Developer : Qin Yue @ 2026
# Organization : OptiHK Limited
# -----------------------------------------------------------------------------
@@ -9,6 +9,7 @@ import os
import re
import shutil
import json
import uuid
import yaml
from collections import OrderedDict
from functools import wraps
@@ -135,6 +136,12 @@ def cell_svg_path(project_name, cell_name):
return os.path.join(project_root(project_name), f"{safe_name(cell_name, 'canvas_1')}.svg")
def file_version(path):
"""Return a cache-busting version token for a completed file."""
stat = os.stat(path)
return f"{stat.st_mtime_ns}-{stat.st_size}"
def cell_routes_path(project_name, cell_name):
"""Return the route sidecar JSON path for a project cell."""
return os.path.join(project_root(project_name), f"{safe_name(cell_name, 'canvas_1')}.routes.yml")
@@ -739,24 +746,31 @@ def save_layout():
write_route_points_sidecar(content, cell_routes_path(project, cell))
svg_path = None
svg_version = None
preview_status = "not_requested"
preview_error = None
if create_preview:
svg_path = cell_svg_path(project, cell)
temp_svg_path = f"{svg_path}.building-{os.getpid()}-{uuid.uuid4().hex}.svg"
try:
create_routed_layout_svg(
content,
svg_path,
temp_svg_path,
pdk_root=current_pdk_root(),
project_dir=project_root(project),
technology_manifest_path=technology_manifest_path_for_project(project),
prefer_full_gds=prefer_full_gds_for_session(session),
)
os.replace(temp_svg_path, svg_path)
svg_version = file_version(svg_path)
preview_status = "generated"
except RouterStackUnavailable as e:
preview_status = "skipped"
preview_error = str(e)
svg_path = None
finally:
if os.path.exists(temp_svg_path):
os.remove(temp_svg_path)
record_action('layout.save', project=project, cell=cell, detail={"bytes": len(content), "svg": svg_path})
return jsonify({
@@ -765,7 +779,9 @@ def save_layout():
"cell": cell,
"path": save_path,
"svg_path": svg_path,
"svg_url": url_for('get_layout_svg', project_name=project, cell_name=cell) if svg_path else None,
"svg_url": url_for('get_layout_svg', project_name=project, cell_name=cell, v=svg_version) if svg_path else None,
"svg_ready": bool(svg_path and svg_version),
"svg_version": svg_version,
"preview_status": preview_status,
"preview_error": preview_error
}), 200