Layout refresh latency bug revised
This commit is contained in:
+19
-3
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user