99 lines
12 KiB
Markdown
99 lines
12 KiB
Markdown
---
|
||
title: official-doc / Redis Lua API Reference — call vs pcall, typed errors, effects replication, sandbox
|
||
source_type: official-doc
|
||
url: https://redis.io/docs/latest/develop/programmability/lua-api/
|
||
archive_url:
|
||
related_branches: [feature-redis-atomic-program-catalog-contract]
|
||
related_projects: [ca-skeleton]
|
||
tags: [official-doc, ca-skeleton, runtime, redis]
|
||
created: 2026-07-28
|
||
---
|
||
|
||
# official-doc / Redis Lua API Reference — call vs pcall, typed errors, effects replication, sandbox
|
||
|
||
> Layer: `raw/` — 외부 자료(공식 문서)의 **원문 발췌·출처 기록**.
|
||
> 검증된 요약은 `/ingest` 후 `wiki/concepts/`에 별도 작성. 원본은 raw에 영구 보관.
|
||
|
||
## Parent / 활용 branch
|
||
|
||
| Branch | 이 자료가 정당화하는 결정 |
|
||
|---|---|
|
||
| [[raw/branch-notes/feature-redis-atomic-program-catalog-contract]] | atomic program 은 bounded·결정론적이어야 하며, 오류는 typed 로 반환하고, 복제 의미(effects replication)를 이해한 상태에서 작성해야 한다 — 그 제약을 카탈로그 규칙으로 고정한다. |
|
||
|
||
## 출처
|
||
|
||
- 원본 URL: https://redis.io/docs/latest/develop/programmability/lua-api/
|
||
- 참고: dispatch 에서 지정한 `https://redis.io/docs/latest/develop/interact/programmability/lua-api/` 는 WebFetch 시 `404 Not Found` — 위 대체 URL 로 fetch 성공(본 문서의 `url:` 은 실제 fetch 성공한 URL).
|
||
- 아카이브 URL: (미제공)
|
||
- 저자 / 조직: Redis, Inc. (공식 레퍼런스 문서 — "Redis Lua API reference")
|
||
- 발행일: 문서 자체에 발행일 명시 없음 (버전 미고정 "latest" reference 페이지, 각 API 항목에 `Since version:` / `Until version:` 개별 명시)
|
||
- 마지막 확인일: 2026-07-28
|
||
|
||
## 왜 저장했는지
|
||
|
||
`feature-redis-atomic-program-catalog-contract` 는 EVALSHA 기반 atomic program 이 (1) bounded/deterministic 하고 (2) 오류를 typed 로 반환하며 (3) replication 의미(verbatim vs effects)를 이해한 상태로 작성되어야 한다는 카탈로그 규칙을 정의하려 한다. 이 문서는 그 세 축(오류 처리, typed reply, replication 모드)의 1차 공식 근거다.
|
||
|
||
## 핵심 인용
|
||
|
||
> [§redis.call] "If and when `redis.call()` triggers a runtime exception, the raw exception is raised back to the user as an error, automatically." (line 127)
|
||
|
||
> [§redis.pcall] "The `redis.pcall()` function behaves exactly like [`redis.call()`](#redis.call), except that it: * Always returns a reply. * Never throws a runtime exception, and returns in its stead a [`redis.error_reply`](#redis.error_reply) in case that a runtime exception is thrown by the server." (line 149)
|
||
|
||
> [§redis.error_reply] "The helper accepts a single string argument and returns a Lua table with the _err_ field set to that string." (line 177)
|
||
|
||
> [§redis.status_reply] "The Lua API represents status replies as tables with a single field, _ok_, set with a simple status string." (line 211)
|
||
|
||
> [§redis.set_repl] "As of Redis version 7.0, script replication is no longer supported, and the only replication mode available is script effects replication." (line 278)
|
||
|
||
> [§redis.replicate_commands] "* Until version: 7.0.0" ... "The default, and only script replication mode supported, is script effects' replication." (lines 318, 327)
|
||
|
||
> [§The KEYS global variable] "The script **should only** access keys whose names are given as input arguments. Scripts **should never** access keys with programmatically-generated names or based on the contents of data structures stored in the database." (lines 87–88)
|
||
|
||
> [§Sandbox context > Global variables and functions] "The sandboxed Lua execution context blocks the declaration of global variables and functions." (line 17)
|
||
|
||
> [§Sandbox context > Imported Lua modules] "The sandboxed execution context prevents the loading modules by disabling Lua's [`require` function](https://www.lua.org/pil/8.1.html)." (line 65)
|
||
|
||
> [§redis.setresp] "The default protocol version is _2_, but it can be switched to version _3_." (line 257)
|
||
|
||
## Claims Extracted
|
||
|
||
| Claim ID | Claim (이 자료가 직접 말하는 것) | Evidence quote | Strength | Applies to | Does not prove |
|
||
|---|---|---|---|---|---|
|
||
| REDIS-LUAAPI-C1 | `redis.call()` propagates a runtime exception as a raw error automatically (script aborts); `redis.pcall()` never throws — it always returns a reply, converting the exception into a `redis.error_reply` table instead | [§redis.call] "the raw exception is raised back to the user as an error, automatically." / [§redis.pcall] "Never throws a runtime exception, and returns in its stead a `redis.error_reply`..." | official-reference | EVAL/EVALSHA 기반 ephemeral script 및 Redis Functions 모두 (문서에 "Available in functions: yes" 명시) | 상위 클라이언트 라이브러리(예: Spring Data Redis `RedisScript`)가 이 예외를 어떻게 재래핑하는지는 증명 안 함 |
|
||
| REDIS-LUAAPI-C2 | `redis.error_reply(x)` / `redis.status_reply(x)` 는 각각 `{err=...}` / `{ok=...}` Lua table 을 반환하는 공식 helper — 스크립트가 typed error/status 를 반환하는 공식 수단 | [§redis.error_reply] "returns a Lua table with the _err_ field set to that string." / [§redis.status_reply] "tables with a single field, _ok_, set with a simple status string." | official-reference | 모든 EVAL/EVALSHA 스크립트 및 함수의 반환값 설계 | 어떤 error code(첫 단어 convention)를 카탈로그가 강제해야 하는지는 규정 안 함 — 문서는 "convention"일 뿐 "not mandatory"라고 명시 |
|
||
| REDIS-LUAAPI-C3 | Redis 7.0 부터 verbatim script replication 이 완전히 제거되고, 오직 effects replication(쓰기 명령의 결과만 복제) 만 지원됨 | [§redis.set_repl] "As of Redis version 7.0, script replication is no longer supported, and the only replication mode available is script effects replication." | official-reference | Redis 7.0+ 배포 환경의 replication 동작 이해 | 6.x 이하에서의 verbatim replication 동작 세부(스크립트 소스 자체가 replica로 전송되는 방식)까지는 이 인용만으로 재구성 불가 — 별도 §redis.set_repl 상단 문단 확인 필요 |
|
||
| REDIS-LUAAPI-C4 | `redis.replicate_commands()` 는 `3.2.0`~`7.0.0` 구간에만 존재한 API(verbatim→effects 전환 함수)였고, 7.0 이후에는 effects replication 이 기본값이자 유일한 모드가 되어 이 함수 호출이 불필요해짐 | [§redis.replicate_commands] "* Until version: 7.0.0" / "The default, and only script replication mode supported, is script effects' replication." | official-reference | Redis 버전별(7.0 이전 vs 이후) 카탈로그 program 작성 시 `redis.replicate_commands()` 호출 필요 여부 판단 | 비결정적 명령(RANDOMKEY, TIME, SPOP 등)을 program 에서 사용해도 되는지에 대한 명시적 규칙은 **이 페이지에 없음** — 별도 확인 필요 (아래 Usage Boundaries 참고) |
|
||
| REDIS-LUAAPI-C5 | atomic program 이 접근하는 key 이름은 반드시 입력 인자(KEYS)로 명시되어야 하며, 프로그램적으로 생성되거나 데이터 내용에 기반한 key 이름 접근은 금지된다 | [§The KEYS global variable] "The script **should only** access keys whose names are given as input arguments. Scripts **should never** access keys with programmatically-generated names..." | official-reference | ScriptDescriptor 의 필수 필드 설계(KEYS 선언 강제) 근거 | 이 규칙은 key 접근 방식에 대한 것이며, program 의 시간/공간 복잡도(O(1)/bounded)를 직접 규정하지 않음 — bounded execution 규칙 자체는 별도 근거 필요 |
|
||
| REDIS-LUAAPI-C6 | Lua 샌드박스는 전역 변수/함수 선언과 미정의 전역 변수 접근을 차단한다 — 모든 선언은 `local` 이어야 한다 | [§Sandbox context > Global variables and functions] "The sandboxed Lua execution context blocks the declaration of global variables and functions." | official-reference | 카탈로그 program 작성 코딩 규칙(전역 변수 금지) | 문서 자체가 "sandbox 우회는 실수로는 어렵지만 불가능하지 않다"고 명시 — 우회 시도에 대한 강제력의 절대성까지는 증명 안 함 |
|
||
| REDIS-LUAAPI-C7 | Lua 샌드박스는 `require` 를 비활성화해 임의 외부 모듈 로드를 금지하며, 문서가 나열한 runtime 라이브러리(string/table/math/os 일부/struct/cjson/cmsgpack/bit)만 사용 가능하다 | [§Sandbox context > Imported Lua modules] "prevents the loading modules by disabling Lua's `require` function." | official-reference | 카탈로그 program 이 의존할 수 있는 라이브러리 화이트리스트 근거 | Redis Functions 배포 모드에서 라이브러리 제약이 ephemeral script 와 동일한지는 이 인용만으로 확정 안 됨(문서는 이 제약이 sandbox 공통 서술이라고만 함) |
|
||
| REDIS-LUAAPI-C8 | `redis.setresp(x)` 로 `redis.call()`/`redis.pcall()` 응답의 RESP 버전을 전환할 수 있으며 기본값은 RESP2, 옵트인으로 RESP3 전환 가능 | [§redis.setresp] "The default protocol version is _2_, but it can be switched to version _3_." | official-reference | typed facade 가 `redis.call`/`redis.pcall` 반환값을 파싱할 때 어떤 RESP 버전을 가정해야 하는지 근거 | RESP3 개별 타입(map/set/double/big_number/verbatim_string) 각각의 Lua 변환 세부 규칙까지는 이 인용에 포함하지 않음 — 필요 시 원문 "RESP3 to Lua type conversion" 섹션 추가 확인 |
|
||
|
||
## Usage Boundaries
|
||
|
||
- 이 자료가 직접 증명하는 것:
|
||
- `REDIS-LUAAPI-C1`, `C2`: call/pcall 오류 전파 차이 + typed error/status reply 공식 API
|
||
- `REDIS-LUAAPI-C3`, `C4`: Redis 7.0 기준 effects replication 이 유일한 모드이고 `redis.replicate_commands()` 는 과거(3.2.0~7.0.0) 호환 함수였다는 사실
|
||
- `REDIS-LUAAPI-C5`: KEYS 는 반드시 입력 인자로 선언되어야 한다는 규칙
|
||
- `REDIS-LUAAPI-C6`, `C7`: 전역 변수 금지 + `require` 비활성화(라이브러리 화이트리스트)
|
||
- `REDIS-LUAAPI-C8`: `redis.setresp()` 기본값/전환 가능 여부
|
||
- 이 자료가 증명하지 않는 것:
|
||
- **비결정적 명령(RANDOMKEY, TIME, SPOP 등) 사용 시의 규칙** — 이 페이지(`lua-api`)에는 명시적 서술이 없다. `eval-intro` 페이지(`redis.io/docs/latest/develop/programmability/eval-intro`)에서 다룰 가능성이 높으나 본 fetch 범위 밖이다. 카탈로그 문서에서 "비결정적 명령을 program 에서 금지/제한한다"는 규칙을 세우려면 **`UNSUPPORTED_DECISION`** 으로 표시하거나 `eval-intro` 를 별도 raw-source 로 추가 수집해야 한다.
|
||
- Redis Functions(`FUNCTION LOAD`) 전용 API(`redis.register_function`, script flags `no-writes`/`allow-oom`/`no-cluster` 등)의 세부 동작 — 본 문서에 존재하나 이번 인용 셋에 포함하지 않았다. Functions 배포 모드를 카탈로그 규칙에 넣으려면 별도 claim 추출 필요.
|
||
- RESP3 개별 타입 변환 세부 규칙(map/set/double/big_number/verbatim_string) — 원문에 존재하나 인용 미포함.
|
||
- Redis 6.x 이하에서 `redis.replicate_commands()` 를 호출하지 않았을 때의 구체적 오류/폴백 동작.
|
||
- 내 프로젝트(ca-skeleton)에 적용하려면 추가 확인이 필요한 것:
|
||
- 사용 중인 Redis 서버/클라이언트 버전이 7.0 이상인지 확인 — 이상이면 `redis.replicate_commands()` 호출은 불필요(no-op)하고 effects replication 이 기본.
|
||
- typed facade 구현 시 `redis.setresp()` 미호출 상태(RESP2 기본)를 가정해도 되는지 실제 배포 Redis 버전과 클라이언트 설정으로 검증.
|
||
|
||
## 메모
|
||
|
||
> 검증되지 않은 추론은 여기까지만. 인용 섹션에는 넣지 않았다.
|
||
|
||
- 비결정적 명령 규칙 공백(RANDOMKEY/TIME/SPOP)은 `eval-intro` 페이지를 별도 `wiki-source-summarizer` dispatch 로 수집해야 branch-note의 "bounded/deterministic" 결정이 완전히 근거를 갖춘다 — 현재는 부분 근거만 확보된 상태.
|
||
- 이 문서 하나로 branch 의 "복제 의미를 이해한 상태에서 작성" 요구는 effects-replication 전환(C3/C4) 근거는 있으나, "왜 그 요구가 필요한가"(replica/AOF 불일치 위험)는 `redis.set_repl` 섹션 상단의 warning 문단(이번 인용에 미포함)에 더 있다 — 필요 시 추가 인용 가능.
|
||
|
||
## Related
|
||
|
||
- 같은 branch 의 sibling 근거 (아직 미등록): eval-intro (bounded execution, blocking, 비결정적 명령) — `/branch-spec feature-redis-atomic-program-catalog-contract` 진행 시 추가 수집 권고.
|
||
- 이 자료를 인용한 wiki 요약: 아직 없음 (raw 단계).
|