LVRS Storyboard Frame
backend/Backend.svx
Path: backend/Backend.svx
백엔드
위치: backend/io/backend.h / backend/io/backend.cpp
Backend는 파일 시스템 유틸리티 및 미러링된 런타임 이벤트 캐싱을 위한 QML 브리지 싱글턴입니다. 의도적으로 단순합니다. 정책이 많은 분석이 아닌 전송 및 한계가 설정된 캐싱입니다.
1. 범위 및 비범위
Backend 소유:
- 원자적 텍스트 저장/읽기 도우미,
- 비차단 UI 흐름을 위한 비동기 작업자 풀 기반 파일/작업 디스패치,
- 쓰기 가능한 위치 조회 브리지,
- 런타임-이벤트 후크 수명주기가
RuntimeEvents로, - 유형별 카운터가 있는 한계가 설정된 미러링 이벤트 캐시,
- 마지막으로 알려진 입력 상태 릴레이.
Backend는 ****를 소유하지 않습니다.
- 전역 이벤트 캡처 자체(
RuntimeEvents가 이를 소유함), - 텍스트 읽기/쓰기 이상의 파일 형식 구문 분석 의미,
- 장기 지속성/이력 저장.
2. 속성 API 계약
| 속성 | 유형 | 의미 체계 | 에지/클램프 |
|---|---|---|---|
lastError |
string |
마지막 작업 오류 메시지입니다. 운전 시작 시 클리어됩니다. | 빈 문자열은 현재 오류가 없음을 의미합니다. |
userEventHooked |
bool |
런타임 이벤트 스트림에 연결된 경우 참입니다. | 런타임가 파괴되거나 연결 해제되면 거짓입니다. |
hookedEventCount |
int |
현재 미러링된 이벤트 수입니다. | hookedEventCapacity를 상한으로 제한한다. |
hookedEventCapacity |
int |
유지할 최대 미러링 이벤트입니다. | 범위로 제한한다: [64, 32768]. |
lastHookedEvent |
map |
가장 최근에 미러링된 이벤트입니다(hookEpochMs 사용). |
첫 번째 이벤트 이전에는 비어 있습니다. |
lastHookedInputState |
map |
페이로드/런타임 대체 경로의 최신 입력 스냅샷입니다. | 후크를 풀면 오래될 수 있습니다. |
asyncJobsInFlight |
int |
대기/실행 중인 비동기 요청 수입니다. | 0를 하한으로 제한한다. |
asyncMaxConcurrency |
int |
레인 풀을 파생하는 데 사용되는 전역 비동기 동시성 예산입니다. | 범위로 제한한다: [1, 64]. |
asyncIoMaxConcurrency |
int |
IO 레인 풀의 파생 동시성입니다. | 1를 하한으로 제한한다. |
asyncUtilityMaxConcurrency |
int |
유틸리티 레인 풀의 파생 동시성입니다. | 1를 하한으로 제한한다. |
asyncRenderMaxConcurrency |
int |
렌더링 레인 풀의 파생 동시성입니다. | 1를 하한으로 제한한다. |
asyncQueueDepth |
int |
레인 전체에서 현재 대기 중인 요청 수입니다. | 0를 하한으로 제한한다. |
asyncQueuePeakDepth |
int |
프로세스 시작 이후 관찰된 최대 대기열 깊이입니다. | 단조 증가. |
asyncQueueDepthLimit |
int |
배압에 대한 레인당 대기 깊이 제한. | 범위로 제한한다: [1, 16384]. |
asyncBackpressureDropCount |
uint64 |
배압으로 인해 거부된 요청 수입니다. | 단조 증가. |
asyncMergedRequestCount |
uint64 |
병합으로 병합된 요청 수입니다. | 단조 증가. |
asyncCanceledRequestCount |
uint64 |
취소된 것으로 완료된 요청 수입니다. | 단조 증가. |
performanceMetrics |
map |
집계된 비동기 대기 시간/큐 지표 스냅샷입니다. | 스키마: lvrs.performance.v1. |
performanceTraceCapacity |
int |
Max는 성능 추적 이벤트를 유지했습니다. | 범위로 제한한다: [128, 16384]. |
performanceTraceCount |
int |
현재 보유된 성능 추적 이벤트입니다. 용량별 | 한계가 설정된. |
readTextCacheTtlMs |
int |
TTL(메모리 내 텍스트 읽기 캐시용) | 범위로 제한한다: [100, 3600000]. |
readTextCacheCapacityBytes |
int64 |
텍스트 캐시의 최대 메모리 예산입니다. | 범위로 제한한다: [64, 536870912]. |
readTextCacheBytes |
int64 |
현재 텍스트 캐시 메모리 사용량입니다. | 0를 하한으로 제한한다. |
readTextCacheEntryCount |
int |
현재 텍스트 캐시 항목 수입니다. | 0를 하한으로 제한한다. |
3. 메소드 계약(상세)
3.1 파일 API
saveTextFile(path, text): bool
- 원자 쓰기 의미 체계에
QSaveFile를 사용합니다. - 페이로드 바이트에 대한 UTF-8 인코딩입니다.
- 열기/쓰기/커밋 실패 시
false를 반환하고lastError를 설정합니다.
실패 사례:
- 비어 있음/공백
path, - 디렉토리가 누락되어 호출자 워크플로에서 생성할 수 없습니다.
- 허가가 거부되었습니다.
- 부분적인 쓰기/커밋 실패.
readTextFile(path): string
- 텍스트 파일을 UTF-8 바이트로 읽습니다.
- 실패 시 빈 문자열을 반환하고
lastError를 설정합니다.
ensureDir(path): bool
- 없으면 재귀적으로 디렉토리를 생성합니다 (
mkpath(".")). - 이미 존재하는 경우
true를 반환합니다. - 실패 시
false+lastError를 반환합니다.
writableLocation(location): string
QStandardPaths::writableLocation에 직접 브리지를 연결하십시오.- 비어 있지 않은 경로의 검증과 디렉터리 생성은 호출자의 책임이다.
3.2 비동기 API(다중 스레드, UI 비차단)
saveTextFileAsync(path, text): qulonglong
- 백엔드 작업자 스레드 풀에 원자성 UTF-8 텍스트 저장을 대기열에 추가합니다.
- 요청 ID를 즉시 반환합니다.
- 발생시키는 신호:
asyncRequestQueued(requestId, "saveTextFile", path)- 완료 시
asyncRequestFinished(...).
- 완료
result맵에는 다음이 포함됩니다:bytes
readTextFileAsync(path): qulonglong
- 백엔드 작업자 스레드 풀에서 읽은 UTF-8 텍스트를 대기열에 넣습니다.
- 요청 ID를 즉시 반환합니다.
- 대기 중/완료 신호를 내보냅니다.
- 완료
result맵에는 다음이 포함됩니다:textlength
ensureDirAsync(path): qulonglong
- 작업자 풀에 재귀 디렉터리 보장(
mkpath("."))을 대기열에 추가합니다. - 요청 ID를 즉시 반환합니다.
- 완료
result맵에는 다음이 포함됩니다:ensured(bool)
dispatchAsyncTask(taskName, payload = {}, delayMs = 0): qulonglong
- UI 오케스트레이션을 위한 범용 비동기 작업 디스패처입니다.
payload.lane또는 작업 이름 접두사를 사용하여 레인 풀로 라우팅합니다.ioutilityrender
- 기본적으로 즉시 실행으로 실행됩니다(
delayMs는 메타데이터 호환성 필드로 유지됨). - 선택 사항인
payload.workMs는 오케스트레이션/테스트를 위한 한계가 설정된 백그라운드 작업을 시뮬레이션합니다. - 병합 지원:
payload.coalesce=true(기본값)를 설정하고,- 대기 중인 중복 작업을 병합하려면
payload.coalesceKey를 설정하세요.
- 차선 대기열 깊이가
asyncQueueDepthLimit를 초과하면 배압이 적용됩니다. delayMs는 호환성을 위해 메타데이터 입력(requestedDelayMs)으로 허용됩니다.- 요청 ID를 즉시 반환합니다.
- 완료
result맵은 페이로드를 에코하고 추가합니다.taskNamedelayMs(항상0)requestedDelayMslanecoalescedmergedIntoRequestId(병합 시)
setAsyncMaxConcurrency(value): void
- 전역 동시성 예산을 제어합니다.
- 런타임는 이 값에서 레인당 풀 크기(
io/utility/render)를 파생합니다.
setAsyncQueueDepthLimit(value): void
- 레인 수준 대기 깊이 배압 임계값을 제어합니다.
- 한도를 초과하는 요청은 배압 오류로 인해 거부됩니다.
cancelAsyncRequest(requestId, reason = "Canceled by request"): bool
- 요청 취소 토큰을 표시합니다.
- 요청이 시작되지 않은 경우 취소된 상태로 즉시 완료됩니다.
- 이미 실행 중인 경우 최종 완료는 취소된 결과로 정규화됩니다.
setPerformanceTraceCapacity(value): void
- P0 타임라인 추적 크기를 유지하도록 제어합니다.
- 용량이 줄어들면 이전 항목은 FIFO에서 제거됩니다.
setReadTextCacheTtlMs(value): void
readTextFile*에 대한 TTL 기반 캐시 만료를 제어합니다.- 만료된 항목은 액세스/업데이트 시 정리됩니다.
setReadTextCacheCapacityBytes(value): void
- 읽기 캐시 메모리 예산을 바이트 단위로 제어합니다.
- 캐시는 예산 초과 시 TTL + LRU와 유사한 가장 오래된 액세스 제거를 사용합니다.
3.3 런타임 후크 수명 주기 API
hookUserEvents(): bool
수명주기:
RuntimeEvents싱글턴를 해결합니다.- 런타임 데몬을 시작합니다.
- 이전 후크 링크를 분리합니다.
RuntimeEvents::eventRecorded에 연결합니다.- 런타임 소멸 핸들러를 연결합니다.
- 백엔드 미러에 런타임
recentEvents()를 수집합니다. userEventHooked=true를 설정합니다.
런타임 싱글턴를 사용할 수 없는 경우 false를 반환합니다.
unhookUserEvents(): void
- 이벤트 연결을 끊고 연결을 파괴합니다.
- 런타임 포인터를 지웁니다.
userEventHooked=false를 설정합니다.- 기존 미러링된 이벤트 캐시를 지우지 않습니다.
clearHookedUserEvents(): void
- 미러링된 이벤트, 유형 카운터, 마지막 후크된 스냅샷을 지웁니다.
hookedEventsChanged를 방출합니다.
3.4 쿼리 API
hookedUserEvents(limit = -1): list
limit <= 0또는limit >= count-> 전체 목록.- 양수 제한은 최신 N개 항목을 반환합니다.
hookedUserEventSummary(): map
포함:
- Hook 상태, 이벤트 개수, 용량,
- 마지막 이벤트,
- 현재 입력 스냅샷,
- 유형별 개수,
- 런타임 이벤트 시퀀스(런타임 포인터가 살아 있을 때).
currentUserInputState(): map
- 런타임 포인터를 사용할 수 있는 경우 라이브 런타임 입력 상태를 반환합니다.
- Else는 마지막으로 캐시된 입력 상태를 반환합니다.
performanceMetrics(): map
포함:
- 스키마/구성요소/에포크,
asyncJobsInFlight,asyncMaxConcurrency,asyncIoMaxConcurrency,asyncUtilityMaxConcurrency,asyncRenderMaxConcurrency,asyncQueueDepth,asyncQueuePeakDepth,asyncQueueDepthLimit,asyncBackpressureDropCount,asyncMergedRequestCount,asyncCanceledRequestCount,performanceTraceCount,performanceTraceCapacity,readTextCacheTtlMs,readTextCacheCapacityBytes,readTextCacheBytes,readTextCacheEntryCount,asyncLaneMetrics(io/utility/render대기 중/실행 중/최대/피크),- 작업별 대기 시간 요약(
avg,p50,p95,p99,max,failureRate).
recentPerformanceTrace(limit = -1): list
- 최신 성능 타임라인 이벤트를 반환합니다.
- 이벤트 스키마:
lvrs.performance.trace.v1. - 일반적인 단계:
queuedstartedfinishedcanceled
clearPerformanceTrace(): void
- 보관된 성능 타임라인 이벤트를 지웁니다.
4. 미러링된 캐시 의미론
미러링된 각 이벤트:
- 런타임 이벤트 맵을 복사합니다.
- 미러링 시간에
hookEpochMs를 추가합니다. - 유형별 카운터 업데이트,
- 페이로드 입력이 있는 경우 마지막 입력 스냅샷을 업데이트합니다.
- 용량이 초과되면 가장 오래된 항목을 제거합니다.
퇴거 정책:
- 게재 순서에 따라 엄격한 FIFO,
- 삭제된 항목에 대한 유형별 카운터가 감소합니다.
성능 추적 의미:
- 프로세스 범위의 추가 전용 시퀀스 ID(
sequence), - 한계가 설정된
performanceTraceCapacity에 의한 FIFO 보존, - 요청당 단계 순서:
queued -> started -> finished, - 취소는
canceled추적 및finished(canceled=true)로 표시됩니다.
5. 오류 모델
범주별 일반적인 lastError 값:
| 카테고리 | 일반적인 트리거 |
|---|---|
| 인수 검증 | 빈 경로 입력 |
| 파일 시스템 | 열기/읽기/쓰기/커밋 실패 |
| 런타임 통합 | 런타임 싱글턴 사용할 수 없음 |
lastError는 새로운 작업이 시작될 때마다 덮어쓰여집니다. 기록 오류가 필요한 호출자는 외부에서 지속되어야 합니다.
6. 사용 패턴
6.1 런타임-후크 + 내보내기
import LVRS 1.0 as LV
Component.onCompleted: {
if (!LV.Backend.hookUserEvents())
console.warn("hook failed:", LV.Backend.lastError)
}
function exportEvents(path) {
const payload = JSON.stringify(LV.Backend.hookedUserEvents(512), null, 2)
if (!LV.Backend.saveTextFile(path, payload))
console.warn("save failed:", LV.Backend.lastError)
}
6.2 비동기 비차단 UI 워크플로
import LVRS 1.0 as LV
Component.onCompleted: {
LV.Backend.asyncMaxConcurrency = 4
}
Connections {
target: LV.Backend
function onAsyncRequestFinished(requestId, operation, subject, ok, result, error, elapsedMs) {
if (!ok) {
console.warn(operation, "failed:", error)
return
}
if (operation === "readTextFile")
console.log("loaded text:", result.text)
}
}
function refreshModelFromFile(path) {
LV.Backend.readTextFileAsync(path)
}
6.3 측정 창 재설정 패턴
function beginMeasurementWindow() {
LV.Backend.clearHookedUserEvents()
if (!LV.Backend.userEventHooked)
LV.Backend.hookUserEvents()
}
7. 오류/문제 해결 매트릭스
| 증상 | 예상 원인 | 검증 | 조치 |
|---|---|---|---|
hookUserEvents() 실패 |
런타임 싱글턴 누락 | lastError 검사 |
후크 전에 런타임 모듈 싱글턴 존재 여부 확인 |
| 반영된 이벤트는 성장하지 않습니다 | 후크되지 않거나 런타임 이벤트가 없음 | userEventHooked , hookedEventCount 확인 |
런타임 후크하고 런타임 시작 여부 확인 |
| 유형별 개수 불일치 예상 | 용량 제거 발생 | 개수 대 용량 비교 | 버스트 창에 대한 용량 증가 |
| 오래된 입력 상태 | 런타임 분리됨/후크 해제됨 | 확인 userEventHooked |
다시 후크 또는 직접 읽기 런타임 싱글턴 |
| 저장이 간헐적으로 실패함 | 경로/권한 문제 | lastError 콘텐츠 검사 |
디렉터리 + 권한 + 디스크 상태 확인 |
| 파일/작업 워크플로 중 UI 끊김 현상 | 동기화 API가 핫 경로에서 사용되었습니다. | saveTextFile/readTextFile/ensureDir에 대한 호출을 검사합니다. |
비동기 API로 마이그레이션하고 완료 신호를 처리합니다. |
8. Codex 중심 플레이북
8.1 Codex용 안전한 패치 주문
hookUserEvents()수명 주기 순서를 유지합니다(해결 -> 시작 -> 다시 연결 -> 캐시 수집).hookedEventCapacity클램핑 및 FIFO 제거를 유지합니다.- 작업 진입점에서
lastError지우기 동작을 유지합니다. hookedUserEventSummary()에서 스키마 호환성을 유지합니다.
8.2 Codex 안티 패턴
unhookUserEvents()내부의 미러링된 캐시를 자동으로 지우지 마십시오. 이는 API 의미를 변경합니다.- 런타임 후크 상태에서 파일 API를 차단하지 마십시오.
hookEpochMs를 제거하지 마십시오. 하위 소비 측 툴링은 이에 의존할 수 있습니다.
8.3 코덱스 회귀 체크리스트
수정 후:
- 후크/후크 해제가
userEventHooked를 올바르게 전환합니다. - 용량 클램프 + 제거 동작은 결정적으로 유지됩니다.
- 비동기 대기열은 안정적인 스키마로 대기/완료 신호를 내보냅니다.
- 요약 맵에는 예상 키가 포함됩니다.
- 파일 저장/읽기 실패 경로가 여전히
lastError로 설정되어 있습니다. - 성능 추적 시퀀스는 단조롭게 유지됩니다.
9. 검증 체크리스트
- 런타임 후크는 활성 런타임 싱글턴를 사용하여 성공합니다.
- 미러링된 수는 용량 한계를 따릅니다.
- 유형 카운터는 추가 및 제거 모두에서 조정됩니다.
- 비동기 작업은
asyncJobsInFlight를 올바르게 업데이트합니다. - 파일 도우미 API는 원자적으로 작동하고 오류를 올바르게 보고합니다.
10. 관련 API
RuntimeEvents: 소스 이벤트 데몬.DebugLogger: 선택적 이벤트/로그 스트림 관찰자.ApplicationWindow: 런타임 후크 흐름을 트리거할 수 있는 일반적인 시작 호스트입니다.