feat(B06): [저장]·[확정] 정본을 서버가 다시 계산하도록 되돌림
2026-09-06 저녁 사용자 확정. 이유는 속도가 아니라 보안 — 저장 경로가 브라우저 계산이면 유토 배분·운반거리 코드(_balance 523 + _settle 235 = 758줄)가 번들에 남아야 해서 화면에서 안 그려도 뺄 수 없음. 서버가 정본을 내면 그 몫이 번들에서 빠짐. 대가는 저장 대기 850ms -> 약 980ms(Node 131ms) — 기다리는 조작이라 허용. - 저장·확정이 편집을 커밋한 **뒤** recompute_server_side 를 부름(전에는 편집 앞에서 Node 없이 보정만). 바뀐 벽·측점이 면적·유토곡선에 실림. - run_node 갈래 제거 — 이제 부르는 자리가 둘 다 Node 를 돎(체인·저장). 쓰이지 않게 된 enforce_stored_designs 래퍼 삭제. - 코리도 열쇠 질의: hash 를 isinstance 로 좁힘. 파이썬에서 곧바로 부르면 Query 기본값 객체가 들어오는데 truthy 라 열쇠 없는 호출이 통째로 stale 로 떨어졌음(보조 창 지적). 시험 395 통과·17 건너뜀. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,8 +6,12 @@
|
||||
② 그 면적을 쌓아 만드는 유토곡선.
|
||||
|
||||
왜 — 사용자가 B06 을 한 번도 안 열어도 **초기값**에는 이 값이 있어야 한다.
|
||||
여기(Node 실행)는 **초기값 산출 전용**이다 — 사용자가 화면을 만지는 동안과 [저장]·[확정]
|
||||
때의 계산은 브라우저 몫이다(2026-09-06 사용자 확정: 「일단은 브라우저 계산으로」).
|
||||
|
||||
**부르는 자리 둘** — 파일입력 자동설계 체인(초기값)과 [저장]·[확정](정본).
|
||||
사용자가 화면을 만지는 **동안**은 브라우저 몫이지만(왕복 없이 즉시 따라와야 한다),
|
||||
저장 시점은 서버가 다시 낸다(2026-09-06 저녁 사용자 확정). 이유는 속도가 아니라
|
||||
**보안**이다 — 저장 경로가 브라우저 계산이면 유토 배분·운반거리 코드가 번들에 남아야
|
||||
해서 화면에서 안 그려도 뺄 수 없다. 대가는 저장 대기 850ms → 약 980ms(Node 131ms).
|
||||
|
||||
**계산을 다시 짜지 않는다.** 화면이 쓰는 TS 를 Node 진입점(`B06_Section_Server_Calc_Node.ts`)
|
||||
으로 감싸 그대로 돌린다. 파이썬으로 포팅하면 같은 기하가 두 벌이 되어 「그림은 이런데
|
||||
@@ -82,22 +86,17 @@ def _enforce_stored_designs(
|
||||
enforce_ford_surface_drops(longitudinal, sections, project_root, standard)
|
||||
|
||||
|
||||
async def enforce_stored_designs(project_id: UUID | str, route_id: int) -> int:
|
||||
"""저장분 설계의 포장 구간·세월교 노면 하강만 바로잡는다(Node 실행 없음).
|
||||
|
||||
[저장]·[확정]이 부른다. 구조물 면적·유토곡선은 브라우저가 만들어 보내므로 여기서
|
||||
다시 만들지 않는다(2026-09-06 사용자 확정). 카드를 한 번도 안 그린 측점의 포장·
|
||||
세월교 보정만 서버가 챙긴다.
|
||||
"""
|
||||
return await _recompute(project_id, route_id, run_node=False)
|
||||
|
||||
|
||||
async def recompute_server_side(project_id: UUID | str, route_id: int) -> int:
|
||||
"""초기값 산출 — 위 보정에 더해 구조물 면적·유토곡선까지 Node 로 만들어 저장한다."""
|
||||
return await _recompute(project_id, route_id, run_node=True)
|
||||
"""포장 구간·세월교 노면 하강 보정에 더해 구조물 면적·유토곡선까지 Node 로 만들어 저장한다.
|
||||
|
||||
부르는 자리 둘 — 파일입력 자동설계 체인(초기값)과 [저장]·[확정](정본). 저장 때도
|
||||
서버가 내는 것으로 2026-09-06 저녁 되돌렸다(그 사이 잠깐 브라우저 계산이었다):
|
||||
이유는 속도가 아니라 **배분·운반거리 코드를 브라우저 번들에서 빼기 위해서**다.
|
||||
"""
|
||||
return await _recompute(project_id, route_id)
|
||||
|
||||
|
||||
async def _recompute(project_id: UUID | str, route_id: int, *, run_node: bool) -> int:
|
||||
async def _recompute(project_id: UUID | str, route_id: int) -> int:
|
||||
from B06_Section.B06_Section_Router import get_section_detail
|
||||
|
||||
project_uuid = UUID(str(project_id))
|
||||
@@ -128,15 +127,11 @@ async def _recompute(project_id: UUID | str, route_id: int, *, run_node: bool) -
|
||||
if json.dumps(item.get("design"), sort_keys=True, default=str) != before[index]
|
||||
]
|
||||
|
||||
output = (
|
||||
await asyncio.to_thread(
|
||||
run_bundle_json,
|
||||
BUNDLE,
|
||||
_NPM_SCRIPT,
|
||||
{"detail": detail, "context": _mass_haul_context()},
|
||||
)
|
||||
if run_node
|
||||
else {}
|
||||
output = await asyncio.to_thread(
|
||||
run_bundle_json,
|
||||
BUNDLE,
|
||||
_NPM_SCRIPT,
|
||||
{"detail": detail, "context": _mass_haul_context()},
|
||||
)
|
||||
if not isinstance(output, dict):
|
||||
output = {}
|
||||
|
||||
Reference in New Issue
Block a user