트랜잭션 액션의 조합
각 서비스의 API 레퍼런스에는 「하나의 트랜잭션에 지정할 수 있는 조합」이라는 표가 있습니다. 이 페이지는 그 표를 읽기 위한 전제를 정리한 것입니다.
액션의 「종별」
각 서비스의 액션 표에 있는 「종별」은 그 액션을 트랜잭션의 검증·소비·획득 중 어느 목록에 둘 수 있는지를 나타냅니다.
액션의 이름이나 실제 효과와 일치하지 않는 경우가 있습니다. 이름이 Verify라도 소비 액션이거나, 아무것도 업데이트하지 않는데 획득 액션인 경우가 있습니다.
각 서비스의 표를 읽는 법
각 서비스의 페이지에는 그 서비스의 조작을 나열한 표가 있습니다.
| 열 | 의미 |
|---|---|
| 조작 | 묶이는 단위. 같은 행에 나열된 조작끼리는 1건으로 통합됩니다 |
| 같은 행을 겹쳤을 때 | 그 행의 조작을 하나의 트랜잭션에 여러 개 지정한 결과 |
| 중첩 너머 | 같은 대상에 대한 업데이트가 안쪽 트랜잭션에서도 도착한 경우의 결과 |
| 다른 대상이 되는 경계 | 여기가 다르면 다른 대상이므로, 몇 개를 나열해도 충돌하지 않습니다 |
같은 경계 안에서 서로 다른 행의 조작을 겹치면 트랜잭션이 실패합니다. 행이 나뉘어 있는 것은 값을 합성하는 방법을 정의할 수 없기 때문입니다. 이 실패가 일어나는 것은 액션을 병렬로 실행하는 경우이며, 기본값인 직렬 실행에서는 일어나지 않습니다. 자세한 내용은 직렬 실행과 병렬 실행을 참조하십시오.
결과 칸에는 다음 용어를 사용합니다.
| 용어 | 의미 |
|---|---|
| 통합된다 | 1건으로 묶여 값이 합산 또는 결합됩니다 |
| 같은 값이면 통합 | 같은 값을 지정했다면 1건이 됩니다. 값이 다르면 발행 시에 오류가 됩니다 |
| 먼저 지정한 쪽이 남음 | 오류가 되지 않고 두 번째 이후가 조용히 버려집니다 |
| 실패한다 | 트랜잭션이 실패합니다(400). 재시도해도 해결되지 않습니다 |
| 충돌하지 않는다 | 겹쳐도 됩니다 |
이 5개 용어로 부족한 경우에는, 셀에 그 서비스 고유의 결과가 그대로 쓰입니다. 「나중에 도착한 쪽의 값으로 덮어써진다」 「진행을 건드리지 않는다」와 같은 기술이 그것입니다.
검증 액션은 읽기만 하므로 어떤 업데이트와 함께 두어도 됩니다. 검증 행만은 위 규칙의 예외입니다.
검증 액션끼리 겹친 경우, 대상·검증 타입·임계값이 모두 같은 것만이 하나로 묶입니다. 어느 하나라도 다르면 각각 독립적으로 판정됩니다.
묶였을 때의 취급은 두 가지가 있으며, 액션에 따라 다릅니다.
| 취급 | 결과 |
|---|---|
| 임계값이 합산된다 | 완전히 같은 검증을 두 번 작성하면, 임계값이 2배인 검증 1건이 됩니다 |
| 두 번째가 버려진다 | 완전히 같은 검증이므로 결과는 달라지지 않습니다 |
어느 쪽이 되는지는 각 서비스의 페이지에 쓰여 있습니다. multiplyValueSpecifyingQuantity에 false를 명시한 액션은 그룹화 대상에서 제외되어 항상 각각 독립적으로 판정됩니다.
「같은 행을 겹쳤을 때」 칸에 있는 「발행 시에 오류」는 트랜잭션을 구성하는 시점에 거부됩니다. 중첩 너머의 경우에는 그 검사가 작동하지 않으므로, 같은 불일치가 실행 시의 실패가 됩니다. 둘 다 400이며 재시도해도 해결되지 않습니다.
해당하는 행을 찾을 수 없는 경우, 그 조합은 지정해도 됩니다. 「쓰여 있지 않으니 알 수 없다」가 아니라 「제한이 없다」라고 읽어 주십시오. 다른 서비스의 액션끼리도 충돌하지 않습니다.
실패의 종류와 재시도
| 표의 기술 | 언제 거부되는가 | 상태 |
|---|---|---|
| 트랜잭션이 실패합니다 | 실행 시 | 400 |
| 발행 시에 오류가 됩니다 | 실행보다 앞서, 트랜잭션을 구성하는 시점 | 400 |
둘 다 트랜잭션 구성 자체의 문제입니다. 재시도해도 해결되지 않습니다.
충돌(409)은 상태가 경합했을 뿐이므로 재시도해도 됩니다. 다만 서비스에 따라서는 재시도해도 해소되지 않는 충돌이 있습니다. 해당하는 경우에는 각 서비스의 페이지에 쓰여 있습니다.
중첩된 트랜잭션
액션 중에는 그 액션 자신이 다시 별도의 트랜잭션을 발행하는 것이 있습니다. 다음이 해당됩니다.
추첨(GS2-Lottery), 교환(GS2-Exchange), 강화와 해방(GS2-Enhance), 보상 수령(GS2-Mission / GS2-LoginReward / GS2-Idle / GS2-Ranking2), 메시지 개봉(GS2-Inbox), 시리얼 코드 사용(GS2-SerialKey), 진열대에서의 구매(GS2-Showcase), 노드의 해방(GS2-SkillTree), 배율 적용(GS2-Experience / GS2-Grade), 스크립트 실행(GS2-Script), 스테이트 머신의 시작(GS2-StateMachine)
각 서비스의 조합 표는 하나의 트랜잭션에 직접 지정한 액션끼리의 이야기입니다. 안쪽 트랜잭션이 발행하는 업데이트는 그것들과 통합되지 않습니다. 이것은 두 가지 형태로 일어납니다.
- 바깥쪽과 안쪽 — 트랜잭션에 직접 지정한 액션과, 안쪽 트랜잭션이 발행하는 업데이트가 같은 대상을 건드림
- 안쪽끼리 — 두 개 이상의 중첩 액션이 각각의 안쪽에서 같은 대상을 건드림
후자를 놓치기 쉽습니다. 10연 추첨, 여러 스텝의 로그인 보너스를 한꺼번에 수령, 진열대에서 2개 상품을 구매하는 구성은 모두 이 형태가 됩니다. 안쪽끼리도 통합되지 않으므로, 바깥쪽과 안쪽의 경우와 완전히 같은 취급입니다.
둘 다 병렬 실행에서 그 대상이 두 개의 기록을 허용하지 않는 경우에는 트랜잭션이 실패합니다. 이러한 충돌은 잘못된 트랜잭션으로 취급되므로, 재시도해도 해소되지 않습니다. 기본값인 직렬 실행에서는 일어나지 않습니다.
중첩된 액션의 내용을 조사하는 방법
중첩된 액션이 무엇을 배분(소비)하는지는 그 액션이 참조하는 마스터 데이터로 결정됩니다. 추첨이라면 경품 테이블, 미션이라면 보상, 시리얼 코드라면 캠페인, 로그인 보너스라면 보너스 모델입니다.
배분되는 것의 대부분은 GS2-Inventory의 아이템, GS2-Money2의 통화, GS2-Experience의 경험치입니다. 같은 대상을 바깥쪽에서도 건드리고 있지 않은지를 각 서비스의 페이지에서 확인해 주십시오.
직렬 실행과 병렬 실행
여기까지의 「실패합니다」――같은 경계 안에서 서로 다른 행의 조작이 겹친다, 중첩의 안쪽과 바깥쪽이 같은 대상을 다룬다――는, 액션을 한꺼번에 동시에 실행하는 것에서 비롯됩니다. 실행 방침은 그 트랜잭션을 발행하는 네임스페이스의 트랜잭션 설정으로 정해집니다.
- 직렬 실행(기본값・
enableParallelExecution이false)에서는 액션이 하나씩 실행되며 각각이 직전까지의 결과를 봅니다. 같은 행을 여러 액션에서 갱신할 수 있으므로 이러한 실패는 일어나지 않습니다. 중첩의 안쪽에서 도착하는 갱신과의 충돌도 마찬가지로, 바깥쪽 트랜잭션을 발행하는 네임스페이스가 직렬 실행이라면 충돌하지 않습니다. - 병렬 실행(
enableParallelExecution이true)에서는 액션이 동일한 데이터 스냅샷에 대해 동시에 실행됩니다. 두 액션이 같은 행을 갱신하면 트랜잭션은database:transaction:same.resource(400)로 실패합니다. 표의 「실패합니다」는 이 경우의 결과입니다.
병렬 실행을 선택하는 것은 응답 시간을 줄이고 싶은 경우나, 하나의 트랜잭션에 21건 이상의 액션을 포함해야 하는 경우입니다. 그 경우에는 표를 읽고 같은 경계를 다루는 액션이 겹치지 않도록 트랜잭션을 구성하십시오.
어느 쪽이든 네임스페이스의 설정이며, 그 네임스페이스가 발행하는 모든 트랜잭션에 영향을 줍니다. 유지하고 싶은 보장과 견주어 선택하십시오.
「발행 시점에 에러가 됩니다」라고 쓰여 있는 것은 어느 실행 방침에서도 해소되지 않습니다. 실행 방침보다 앞, 트랜잭션을 조립하는 시점의 판정이기 때문입니다.
실행 순서와, 각 액션이 보는 상태
검증 액션, 소비 액션, 획득 액션 순으로 실행됩니다. 이 순서는 어느 실행 방침에서도 변하지 않습니다.
직렬 실행에서는 각 액션이 같은 트랜잭션 안에서 먼저 실행된 액션의 쓰기를 봅니다. List나 Query의 결과에서도, 중첩된 트랜잭션 내부에서도 보입니다. 트랜잭션을 발행한 API가 같은 요청 안에서 먼저 수행한 갱신――사전 스크립트에 의한 변경을 포함합니다――도 보입니다. 각 페이즈 안에서의 실행 순서는 액션 이름, 그다음 대상 리소스로 결정되므로, 요청에 나열한 순서로 실행 순서를 지정할 수는 없습니다.
병렬 실행에서는 모든 액션이 트랜잭션 시작 시점의 상태를 기준으로 판정됩니다. 같은 트랜잭션의 다른 액션이 수행한 변경은 어느 액션에서도 보이지 않습니다. 그래서 「삭제한 결과를 생성 액션이 본다」 「업데이트한 결과를 검증 액션이 본다」와 같은 구성은 할 수 없습니다.
다만 검증 액션과 소비 액션이 획득 액션보다 나중에 실행되는 일은 없습니다. 「획득한 것을 같은 트랜잭션에서 소비한다」와 같은 구성은 어느 실행 방침에서도 할 수 없습니다. 순서가 필요한 경우에는 트랜잭션을 나누십시오.