runlot
참조API

데이터베이스

데이터베이스 카테고리의 API 작업 13개를 다룹니다.

메서드경로설명
GET/v1/orgs/{orgSlug}/projects/{projectName}/database데이터베이스 사용 가능 여부
POST/v1/orgs/{orgSlug}/projects/{projectName}/database데이터베이스를 생성합니다(runlot deploy\"database\": true 선언을 읽을 때 호출됨)
GET/v1/orgs/{orgSlug}/projects/{projectName}/database/connectpsql 또는 드라이버로 연결하는 데 필요한 정보
GET/v1/orgs/{orgSlug}/projects/{projectName}/database/endpoint자격 증명 없는 연결 정보(runlot port-forward)
GET/v1/orgs/{orgSlug}/projects/{projectName}/database/tokens유효한 단기 자격 증명 목록
POST/v1/orgs/{orgSlug}/projects/{projectName}/database/tokens단기 자동화용 자격 증명을 발급합니다(runlot pg token)
DELETE/v1/orgs/{orgSlug}/projects/{projectName}/database/tokens/{tokenUser}단기 자격 증명을 폐기합니다
POST/v1/orgs/{orgSlug}/projects/{projectName}/database/export진단 이미지를 생성합니다(runlot pg export)
GET/v1/orgs/{orgSlug}/projects/{projectName}/database/generations백업 세대 목록(runlot pg generations)
POST/v1/orgs/{orgSlug}/projects/{projectName}/database/restore특정 세대로 복원합니다(runlot pg restore)
POST/v1/orgs/{orgSlug}/projects/{projectName}/database/delete데이터베이스를 삭제합니다(runlot pg delete)
GET/v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}작업 하나의 진행 상황
POST/v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}/abort진행 중인 작업을 중단합니다(runlot pg abort)

GET /v1/orgs/{orgSlug}/projects/{projectName}/database

응답은 단순히 {db: bool}입니다. 크기나 세대 같은 물리적 상태는 여기에 없는데, 그것은 노드가 진실의 원천이기 때문입니다.

자격 증명(비밀번호)은 이 응답에 없습니다. 이 경로는 viewer도 허용합니다 — 연결 세부 정보는 /database/connect로 분리되었습니다.

operationId getDatabase

상태 코드설명응답 본문
200데이터베이스 사용 가능 여부object
403
404

POST /v1/orgs/{orgSlug}/projects/{projectName}/database

데이터베이스 구성 레코드의 존재가 곧 사용 가능 여부를 나타냅니다. 구성이 완료되면 node-agent는 다음 수렴 시점에 프로젝트의 workerd를 env.db가 연결된 구성으로 교체합니다. 배포나 epoch 변경은 필요하지 않습니다.

이 작업은 멱등이며 비밀번호를 회전시키지 않습니다. 두 번째 호출은 행에 이미 있는 값을 다시 읽어 같은 연결 정보를 반환합니다. 비밀번호를 회전시키면 첫 응답에서 기록된 연결 문자열이 조용히 무효화되며, 그것이 죽었다는 유일한 신호는 다음 로그인 실패뿐입니다.

operationId createDatabase

상태 코드설명응답 본문
200자격 증명 및 연결 정보DatabaseConnect
403
404

GET /v1/orgs/{orgSlug}/projects/{projectName}/database/connect

/database에서 분리된 이유는 역할입니다. 데이터베이스가 존재하는지는 viewer도 알 수 있지만, 비밀번호는 그렇지 않습니다. 만약 하나의 응답이 둘 다 담고 역할에 따라 필드를 제거하는 방식이었다면, 제거를 빠뜨린 경로 하나가 곧 유출이 됩니다. member 이상만 받을 수 있습니다.

operationId getDatabaseConnect

상태 코드설명응답 본문
200연결 정보DatabaseConnect
403
404프로젝트가 존재하지 않거나, 데이터베이스가 아직 생성되지 않았습니다Error

GET /v1/orgs/{orgSlug}/projects/{projectName}/database/endpoint

host, port, database, sslmode뿐입니다. viewer 접근도 허용됩니다 — 여기에는 비밀이 없습니다. runlot port-forward는 로그인 세션을 사용해 연결하므로(front가 세션을 검증합니다, docs/pg-driver-support.md §4.4) 비밀번호가 필요 없고, 이 엔드포인트만으로 충분합니다.

operationId getDatabaseEndpoint

상태 코드설명응답 본문
200엔드포인트object
403
404

GET /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens

비밀번호와 검증자는 포함되지 않습니다. member 이상이 사용할 수 있습니다.

operationId listDatabaseTokens

상태 코드설명응답 본문
200목록 조회object
403
404

POST /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens

연결 문자열에 사용할 사용자/비밀번호 쌍입니다. 비밀번호는 이 응답에서만 나타납니다 — CP는 SCRAM 검증자만 보관하므로, 잃어버린 비밀번호는 재발급해야 합니다. 세션은 여전히 프로젝트의 역할 아래에서 열립니다: 토큰 사용자는 인증에 쓰이는 이름일 뿐, 엔진 역할이 아닙니다. member.

operationId createDatabaseToken

요청 본문: application/json · object

상태 코드설명응답 본문
201발급된 자격 증명DatabaseToken
400
403
404

DELETE /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens/{tokenUser}

이후의 연결은 거부됩니다. 존재하지 않는 자격 증명을 삭제하려 하면 404를 반환합니다. member 이상이 사용할 수 있습니다.

operationId deleteDatabaseToken

상태 코드설명응답 본문
204폐기됨
403
404

POST /v1/orgs/{orgSlug}/projects/{projectName}/database/export

백업이 아닙니다(docs/env-db-assembly.md §5). 이것이 만드는 것은 현재 (project, epoch) 아래의 불변 진단 키이며, latest, freshness, retention 포인터 중 어느 것도 옮기지 않고, 다음 자동 백업의 이름에도 영향을 주지 않습니다.

이제 예약 백업이 실행됩니다(Phase 5, docs/phase5.md): node-agent가 스케줄러와 노드 전체 세마포어를 소유하며, 단계별 세대는 RPO 1시간 격자에 맞춰 생성됩니다. 이 세대들은 gen/<project>/<epoch>/ 아래에 저장되며, …/database/generations에서 목록을 확인하고 …/database/restore에서 하나를 선택합니다. 이 엔드포인트가 만드는 진단 이미지는 그 네임스페이스 밖에 머무릅니다 — restore는 그것을 선택할 수 없고, pruning도 이를 세지 않으며, latest를 옮길 수도 없습니다.

멱등이 아닙니다. 서버가 요청마다 새 스탬프를 만들기 때문에, 호출할 때마다 이미지가 하나씩 더 생성됩니다. 멱등하게 흡수되는 유일한 것은 스탬프가 노드에 도달한 뒤의 같은 스탬프 재시도뿐입니다.

member 이상만 요청할 수 있습니다. 이 이미지는 데이터베이스 전체이므로, viewer가 한 번의 호출로 가져와야 할 대상이 아닙니다.

느립니다. 응답은 덤프가 끝나야 도착하며 — 크기에 비례합니다 — 그동안 프로젝트의 액터가 점유됩니다.

operationId exportDatabase

상태 코드설명응답 본문
200생성된 진단 키DatabaseExport
403
404프로젝트가 존재하지 않거나, 데이터베이스가 아직 생성되지 않았습니다Error
409배치가 중단된 상태입니다(suspended). 진단 내보내기는 실행 중인 incarnation에서만 생성됩니다. 중단된 프로젝트의 데이터를 가져오려면 복원 경로를 사용해야 합니다.Error
502노드가 이미지 빌드에 실패했습니다(export_failed)Error
503내보낼 수 있는 상태가 아닙니다 — home 노드 주소가 없거나(no_home_node), CP에 노드 관리자 경로가 설정되어 있지 않습니다(no_node_admin).Error

GET /v1/orgs/{orgSlug}/projects/{projectName}/database/generations

복원은 있는 것 중에서만 고를 수 있습니다(docs/phase5.md B1). CP의 db_generations 테이블을 직접 읽습니다. 오프사이트 스토리지를 직접 조회하지는 않습니다: 복원이 수신한 바이트를 검증하려면 bytessha256이 CP에 있어야 합니다.

lastCheckedAt변경 없음 건너뛰기(no-change skip)의 하트비트입니다. 세대가 진행되지 않는 것과 백업이 죽은 것은 서로 다른 상황이며, 이 값이 그 둘을 구분합니다 — 비어 있다면 아직 확인이 이루어지지 않았다는 뜻입니다.

member 이상이 사용할 수 있습니다. 목록에는 오프사이트 키와 다이제스트가 포함됩니다.

데이터베이스가 활성화되어 있을 필요가 없습니다. pg delete 이후에도 마지막 안전 세대가 남아 있으므로, 삭제 후에도 이 목록에서 계속 볼 수 있습니다.

operationId listGenerations

상태 코드설명응답 본문
200세대 목록, 최신순DatabaseGenerations
403
404

POST /v1/orgs/{orgSlug}/projects/{projectName}/database/restore

세대를 복원하는 것은 기존 인스턴스를 종료한 뒤 다시 활성화하는 과정입니다(docs/phase5.md B2). pg.restore가 빈 store만 받아들인다는 사실이 이 형태를 결정합니다: draining → sealing(현재 데이터를 가진 복원 전 세대를 먼저 보존합니다 — 되돌아갈 길) → committing(선택한 세대를 final_gen에 씁니다) → reactivation(epoch+1).

그 사이에 이루어진 쓰기는 유실됩니다. 그래서 admin 이상의 권한이 필요하며, CLI는 프로젝트 이름을 다시 입력하도록 요구합니다.

서버는 latest를 절대 해석하지 않습니다. 목록에서 본 정확한 (epoch, seq)를 전달해야 합니다 — 서버가 스스로 "가장 최근"을 선택한다면, 그 사이에 생성된 예약 세대 때문에 사용자가 본 것과 다른 세대로 보내질 수 있습니다.

202를 반환합니다. 돌아오는 것은 결과가 아니라 operation id입니다; 진행 상황은 …/database/operations/{opId}에서 확인하세요.

operationId restoreDatabase

요청 본문: application/json · RestoreRequest

상태 코드설명응답 본문
202operation을 열었습니다OperationStarted
400
403
404프로젝트가 존재하지 않거나, 데이터베이스가 아직 생성되지 않았습니다Error
409다른 operation이 이미 진행 중이거나(operation_in_progress), 배포가 중단된 상태입니다(suspended).Error
503복원할 수 있는 상태가 아닙니다(예: 사용 가능한 batch 노드가 없음)Error

POST /v1/orgs/{orgSlug}/projects/{projectName}/database/delete

draining → sealing(마지막 안전 세대를 final로 남깁니다) → committing(project_databases 행을 삭제합니다; 다음 convergence에서 노드가 env.db가 없는 프로세스로 교체하고 데이터 디렉터리를 tombstone으로 옮깁니다, docs/phase5.md B3). admin 이상의 권한이 필요합니다.

confirm은 프로젝트 이름과 정확히 일치해야 합니다. 일치하지 않으면 400 confirm_mismatch를 반환하고 아무 것도 시작되지 않습니다. CLI 프롬프트만으로는 충분하지 않습니다 — 잘못된 디렉터리에서 --yes로 실행된 스크립트는 프롬프트를 아예 보여주지 않습니다.

DELETE 메서드를 쓰지 않는 이유: 이 요청은 행 하나를 삭제하는 것이 아니라 202로 시작해 몇 분에 걸쳐 끝나는 operation이며, 본문에 확인 문자열이 필요합니다 — 경로상의 프록시들이 DELETE 본문을 일관되게 처리하지 않습니다.

operationId deleteDatabase

요청 본문: application/json · DeleteRequest

상태 코드설명응답 본문
202operation을 열었습니다OperationStarted
400확인 문자열이 프로젝트 이름과 일치하지 않습니다(confirm_mismatch)Error
403
404프로젝트가 존재하지 않거나, 데이터베이스가 아직 생성되지 않았습니다Error
409다른 operation이 이미 진행 중입니다(operation_in_progress)Error

GET /v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}

복원 또는 삭제의 진행 상황을 지켜봅니다. CLI는 2초마다 폴링하며 phase가 바뀔 때마다 출력합니다.

operation이 프로젝트 아래에 위치하는 것은 id가 자격 증명이 아니기 때문입니다. cp-core의 /v1/operations/{opId}는 id를 아는 어떤 클라이언트에도 응답합니다(node, cp-public), 하지만 사용자 대면 표면이 같은 방식으로 동작한다면 id 하나가 다른 org의 operation 상태를 여는 키가 되어 버립니다. 이 경로는 응답하기 전에 operation의 projectId가 경로상의 프로젝트와 일치하는지 확인하며, 그렇지 않으면 존재하지 않는 것처럼 404를 반환합니다.

member 이상의 권한이 필요합니다.

operationId getDatabaseOperation

상태 코드설명응답 본문
200Operation 상태Operation
403
404프로젝트에 해당 operation이 없습니다(다른 프로젝트에 속한 operation도 여기로 떨어집니다)Error

POST /v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}/abort

복구 불가능한 단계(docs/phase5.md B4) 이전에만 가능합니다: evict, restore_generation, delete는 커밋 전까지 취소할 수 있지만 restore는 취소할 수 없습니다. 취소하면 배치가 active로 돌아가고 terminalCode=aborted로 남습니다.

admin 이상입니다. 서버는 먼저 읽고 나서 취소합니다 — 순서를 뒤집으면 404를 반환하기 전에 다른 프로젝트의 작업을 실제로 취소하게 됩니다.

operationId abortDatabaseOperation

상태 코드설명응답 본문
200일시 중단된 작업의 상태Operation
403
404프로젝트에 해당 작업이 없습니다Error
409되돌릴 수 없는 지점을 지났습니다(not_abortable) — 커밋 후이거나 restore 작업인 경우입니다.Error

이 페이지의 목차