본문으로 건너뛰기

Flow 변경 검토와 적용

plan

python
client.plan_flow_change(flow: FlowRef, *, commands: list | tuple) -> dict

client.save(flow)가 반환한 FlowRef를 기준으로 변경을 검증합니다. 결과 dict에는 target, expectedGeneration, commands, diff, impact, touchedSemanticPaths, planRef, planDigest, expiresAt, base, atomic이 들어 있습니다. 검토 시점에는 Flow head를 바꾸거나 계산을 실행하지 않습니다.

지원 명령은 공통 Flow command 계약을 따릅니다. 새 저장소나 자유 형식 문서 덮어쓰기가 아닙니다. 다른 Project의 참조, 오래된 revision, 잘못된 결과 연결, 지원하지 않는 명령은 거절합니다. 설치·의존성·실행 정책은 그대로 적용됩니다.

python
from pipelinexlab import px

# saved = client.save(flow)로 받은 정확한 FlowRef입니다.
plan = client.plan_flow_change(saved, commands=[{
    "kind": "SetResultViewer",
    "viewerKey": "properties",
    "viewer": {
        "renderer": {"key": "core.result", "version": 1},
        "results": ["properties"],
        "position": {"x": 640, "y": 400},
    },
}])
print(plan["diff"], plan["impact"])

SetResultViewer는 완전한 viewer 정의를 추가하거나 교체합니다. 같은 key로 위치나 출력 순서를 바꾸고 새 key로 복제할 수 있습니다. results는 같은 Flow의 공개 result key 목록이며 비어 있거나 중복될 수 없습니다. 내부 Node port를 직접 지정하지 않습니다.

RemoveResultViewerviewerKey로 존재하는 뷰어를 제거합니다. 여러 명령은 한 묶음으로 검증·적용됩니다. 하나라도 잘못되면 일부만 저장하지 않습니다. 뷰어를 모두 제거해도 파일 버전은 V2로 유지하고 Run 결과나 원본 파일을 삭제하지 않습니다.

apply

python
client.apply_flow_change(plan: dict, *, command_id: str) -> FlowRef

검토한 Plan을 적용하고 새 revision의 FlowRef를 반환합니다. Plan 이후 다른 편집으로 head가 바뀌면 충돌을 반환합니다. 자동으로 최신 revision에 다시 적용하지 않습니다.

python
updated = client.apply_flow_change(plan, command_id="place_properties_1")
client.export_documents("./after-edit", flows={"analysis.pxflow": updated})

remove = client.plan_flow_change(updated, commands=[{
    "kind": "RemoveResultViewer", "viewerKey": "properties",
}])
removed = client.apply_flow_change(remove, command_id="remove_properties_1")

재시도하려면 원래 Plan dict와 같은 command_id를 보관합니다. JSON으로 저장한 Plan은 같은 Project의 새 Client에서도 사용할 수 있습니다. 응답 유실 시 새 Plan을 만들지 않고 원래 Apply를 재전송하면 저장된 receipt를 조회합니다. 같은 ID에 다른 Apply 요청을 보내면 거절합니다. 아직 적용하지 않은 Plan이 만료됐거나 충돌했다면 다시 검토하고 새 명령 ID로 적용합니다.

Plan의 commandsdiff를 고쳐도 서버에 저장된 Plan은 바뀌지 않습니다. 변경 내용이 달라지면 반드시 새 Plan을 만듭니다. 적용 후 되돌리기는 새 head에 대한 역방향 명령 묶음이며, 과거 revision을 삭제하거나 head를 몰래 되감지 않습니다. 화면의 Undo 연결은 후속 제품 작업입니다.

오류는 px.Error의 typed diagnostics로 처리합니다. Apply 응답이 유실되면 command_idoutcome_unknown=True를 보존합니다. 이때 적용 실패를 단정하지 않고 보관한 Plan과 명령 ID로 다시 조회·적용합니다. 이 API는 client.save의 초기 저장 규칙을 바꾸지 않습니다. 편집한 FlowRef는 client.run(updated, **inputs)로 직접 실행할 수 있습니다. 정확한 revision 실행과 재시도를 따르며 화면의 선택 Run 연결은 후속 작업입니다.

input-draft

read-input-draft

python
client.read_flow_input_draft(flow: FlowRef) -> dict

현재 사용자·Project·Flow의 편집 중인 입력 문자열을 보존합니다. Flow 문서와 Run은 별도이며 빈 문자열이나 미완성 숫자를 저장해도 계산이 시작되지 않습니다. 입력 key는 그 revision의 선언을 따릅니다.

save-input-draft

python
client.save_flow_input_draft(flow: FlowRef, values: dict, *, expected_version: str | None, command_id: str | None = None) -> dict
python
current = client.read_flow_input_draft(saved)
draft = current["draft"]
same_inputs = draft is None or draft["inputSchemaRef"] == current["inputSchemaRef"]
# same_inputs가 False이면 기존 초안을 새 선언에 자동 적용하지 않습니다.
updated = client.save_flow_input_draft(
    saved, {"width": "250", "height": "300"},
    expected_version=draft["version"] if draft else None,
    command_id="inputs_1",
)
run = client.run(saved, width=250.0, height=300.0)

반환값은 {draft, inputSchemaRef}이며 draft가 있으면 저장 원본 revision, 입력 선언 digest, 정확한 문자열 values와 version을 포함합니다. 배치만 바뀐 Flow는 같은 선언 digest를 유지합니다. 동시에 다른 저장이 있으면 expected_version 충돌로 거절합니다. 오류의 outcome_unknown이 참이면 원래 FlowRef·values·expected_version·command_id를 그대로 재사용합니다. 읽힌 최신 version으로 바꿔 재시도하지 않습니다. 이전 요청의 receipt는 후속 저장 이후에도 원래 저장 결과를 반환합니다.