> For the complete documentation index, see [llms.txt](/llms.txt)

# GS2-Distributor 트랜잭션 액션

검증/소비/입수 각 트랜잭션 액션의 사양




## 액션의 조합과 동시 실행

모든 서비스에 공통되는 전제는 [트랜잭션 액션의 조합]()에 정리되어 있습니다. 먼저 그쪽을 읽어 주십시오. 이 절의 나머지는 GS2-Distributor 고유의 내용입니다.

GS2-Distributor의 트랜잭션 액션은 데이터가 아니라 로직을 다룹니다. 다른 액션을 안쪽에 가지고, 그것들을 실행할지 여부를 결정합니다. GS2-Distributor는 자신의 데이터를 갖지 않으므로, 이러한 액션이 GS2-Distributor를 이유로 충돌하는 일은 없습니다.

조작 | 같은 행을 겹쳤을 때 | 중첩 너머 | 다른 대상이 되는 경계 | 직렬 실행 모드 활성화 시
--- | --- | --- | --- | ---
`and` 식의 평가<br>`AndExpressionByUserId` | 각각 독립적으로 평가된다 | 읽기만 하므로 충돌하지 않는다 | 식마다 다른 대상 | 변하지 않는다. 읽기만 하므로 원래 충돌하지 않는다
`or` 식의 평가<br>`OrExpressionByUserId` | 각각 독립적으로 평가된다 | 읽기만 하므로 충돌하지 않는다 | 식마다 다른 대상 | 변하지 않는다. 읽기만 하므로 원래 충돌하지 않는다
`if` 식의 평가<br>`IfExpressionByUserId` | 각각 독립적으로 평가된다 | 성립한 분기가 무엇을 기록하는지에 따른다 | 식마다 다른 대상 | 계속해서 성립한 분기가 무엇을 기록하는지에 따르지만, 그 기록은 같은 직렬 실행 구간을 거치게 된다(아래 설명 참고)

`and`와 `or` 식이 안쪽에 가지는 것은 검증 액션으로, 읽기만 수행합니다. `if` 식은 두 개의 분기에 소비 액션을 가지며, 이쪽은 기록합니다.

하나의 식 안쪽에 있는 액션끼리는 통상대로 통합됩니다. 하나의 `and` 식 안에 같은 대상에 대한 같은 액션이 두 개 있으면 하나가 됩니다. 다만 바깥쪽 트랜잭션의 액션과도, 다른 식의 안쪽 액션과도 통합되는 일은 없습니다.

주의해야 할 것은 여기입니다. `if`의 분기가 트랜잭션에 직접 작성된 액션과 같은 통화를 소비하거나 같은 도감을 다시 쓰는 경우, 두 개의 기록이 별개로 도착하므로 그 서비스에 쓰여 있는 제한에 그대로 부딪힙니다.

### 모두 트랜잭션 시작 시점의 상태에 대해 평가됩니다

식은 다른 검증 액션과 마찬가지로 트랜잭션 시작 시점의 상태를 읽습니다. 같은 트랜잭션이 변경한 것은 보이지 않습니다. 같은 트랜잭션의 다른 식이 변경한 것도 마찬가지입니다. 그 때문에 조건이 서로 의존하는 두 개의 `if` 식을 연쇄시킬 수는 없습니다. 둘 다 같은 시작 시점의 상태에 대해 평가됩니다.

### 중첩된 트랜잭션에 주의

안쪽 트랜잭션에서 도착하는 기록은 바깥쪽에 직접 지정한 액션의 대상이 아닙니다. 그 때문에 분기가 배분하는 아이템을 바깥쪽 트랜잭션도 배분하는 경우, 그 아이템이 두 개의 기록을 허용하지 않는다면 트랜잭션이 실패합니다. 직렬 실행 모드(`enableSequentialExecution` 또는 `TransactionSettingV2`)를 활성화하면 이는 달라집니다. 분기의 기록도 직접 지정한 액션과 마찬가지로, 중첩을 넘어서도 같은 직렬 실행 구간을 거치게 됩니다. 이 조합이 성립하는지는 직접 지정한 두 액션의 경우와 완전히 동일하게, 기록되는 아이템이나 리소스의 성질에 따라 결정됩니다. 그 리소스의 액션 조합이 직렬 실행 모드로 해소되는 종류인지는 해당 리소스 자체의 트랜잭션 관련 페이지를 확인해 주십시오.

식의 분기도 트랜잭션의 일부로서 읽어 주십시오.

### 제한을 회피하고 싶은 경우

`enableAtomicCommit`을 비활성화하면 분기와 바깥쪽 액션이 한 번의 기록에 모이지 않게 됩니다. `acquireActionUseJobQueue`로 분리할 수 있는 것은 식 주변에 있는 획득 액션뿐입니다. `if`의 분기가 가지는 것은 소비 액션이므로, 분기 자체가 분리되는 것은 아닙니다.

### 동시 실행과 재시도

GS2-Distributor 자체가 충돌을 반환하는 일은 없습니다. 식이 동시 실행 요청과 충돌하는지는 안쪽 액션이 무엇을 기록하는지에 따라 결정되며, 재시도 지침도 그 서비스의 것이 해당됩니다.

식은 단순히 조건이 충족되지 않아서 실패하는 경우도 있습니다. 이것은 결과이지 재시도해야 할 오류가 아닙니다.

---


## Verify Action

검증 액션

### Gs2Distributor:IfExpressionByUserId

조건을 검증하고 소비 액션의 내용을 전환<br>

검증 액션을 조건으로 평가하고, 결과에 따라 trueActions 또는 falseActions의 소비 액션 목록을 실행합니다.<br>
이를 통해 트랜잭션 내에서 조건 분기가 가능해지며, 검증 결과에 따라 서로 다른 소비 액션을 실행할 수 있습니다.<br>
multiplyValueSpecifyingQuantity가 활성화된 경우, 검증에 사용되는 값도 지정된 수량만큼 곱해집니다.

**수량 지정 가능한 액션: 아니오**

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| userId | string |  | ✓|  |  ~ 128자 | 사용자ID<br>`#{userId}`로 설정하면 로그인 중인 사용자ID로 치환됩니다. |
| condition | [VerifyAction](../sdk/#verifyaction) |  | ✓|  |  | 조건 |
| trueActions | [List&lt;ConsumeAction&gt;](../sdk/#consumeaction) |  | |  | 0 ~ 10 items | 조건이 참일 때 실행되는 소비 액션 목록 |
| falseActions | [List&lt;ConsumeAction&gt;](../sdk/#consumeaction) |  | |  | 0 ~ 10 items | 조건이 거짓일 때 실행되는 소비 액션 목록 |
| multiplyValueSpecifyingQuantity | bool |  | | true |  | 수량을 지정했을 때, 검증에 사용하는 값도 곱할지 여부 |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |




**JSON**
```json
{
    "action": "Gs2Distributor:IfExpressionByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "condition": {
            "action": "[string]검증 액션에서 실행할 액션의 종류",
            "request": "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
        },
        "trueActions": [
            {
                "action": "[string]소비 액션에서 실행할 액션의 종류",
                "request": "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
            }
        ],
        "falseActions": [
            {
                "action": "[string]소비 액션에서 실행할 액션의 종류",
                "request": "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
            }
        ],
        "multiplyValueSpecifyingQuantity": "[bool]수량을 지정했을 때, 검증에 사용하는 값도 곱할지 여부",
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
```

**YAML**
```yaml

action: Gs2Distributor:IfExpressionByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  condition: 
    action: "[string]검증 액션에서 실행할 액션의 종류"
    request: "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
  trueActions: 
    - action: "[string]소비 액션에서 실행할 액션의 종류"
      request: "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
  falseActions: 
    - action: "[string]소비 액션에서 실행할 액션의 종류"
      request: "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
  multiplyValueSpecifyingQuantity: "[bool]수량을 지정했을 때, 검증에 사용하는 값도 곱할지 여부"
  timeOffsetToken: "[string]타임 오프셋 토큰"
```

**GS2-Script**
```lua

transaction.service("distributor").verify.if_expression_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    condition={
        action="[string]검증 액션에서 실행할 액션의 종류",
        request="[string]액션 실행 시 사용되는 요청의 JSON 문자열"
    },
    trueActions={
        {
            action="[string]소비 액션에서 실행할 액션의 종류",
            request="[string]액션 실행 시 사용되는 요청의 JSON 문자열"
        }
    },
    falseActions={
        {
            action="[string]소비 액션에서 실행할 액션의 종류",
            request="[string]액션 실행 시 사용되는 요청의 JSON 문자열"
        }
    },
    multiplyValueSpecifyingQuantity="[bool]수량을 지정했을 때, 검증에 사용하는 값도 곱할지 여부",
    timeOffsetToken="[string]타임 오프셋 토큰",
})
```


---

### Gs2Distributor:AndExpressionByUserId

여러 검증 액션을 실행하여 모두 참인지 판정<br>

여러 검증 액션을 실행하고, 모두 참으로 평가된 경우에만 성공합니다(AND 논리).<br>
검증 액션 중 하나라도 실패하면 전체 표현식이 실패합니다.<br>
트랜잭션 실행 전에 모두 충족해야 하는 여러 전제 조건을 조합할 때 유용합니다.

**수량 지정 가능한 액션: 아니오**

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| userId | string |  | ✓|  |  ~ 128자 | 사용자ID<br>`#{userId}`로 설정하면 로그인 중인 사용자ID로 치환됩니다. |
| actions | [List&lt;VerifyAction&gt;](../sdk/#verifyaction) |  | |  | 0 ~ 10 items | 검증 액션 목록 |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |




**JSON**
```json
{
    "action": "Gs2Distributor:AndExpressionByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "actions": [
            {
                "action": "[string]검증 액션에서 실행할 액션의 종류",
                "request": "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
            }
        ],
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
```

**YAML**
```yaml

action: Gs2Distributor:AndExpressionByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  actions: 
    - action: "[string]검증 액션에서 실행할 액션의 종류"
      request: "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
  timeOffsetToken: "[string]타임 오프셋 토큰"
```

**GS2-Script**
```lua

transaction.service("distributor").verify.and_expression_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    actions={
        {
            action="[string]검증 액션에서 실행할 액션의 종류",
            request="[string]액션 실행 시 사용되는 요청의 JSON 문자열"
        }
    },
    timeOffsetToken="[string]타임 오프셋 토큰",
})
```


---

### Gs2Distributor:OrExpressionByUserId

여러 검증 액션을 실행하여 하나라도 참인지 판정<br>

여러 검증 액션을 실행하고, 그중 하나라도 참으로 평가되면 성공합니다(OR 논리).<br>
모든 검증 액션이 실패한 경우에만 표현식이 실패합니다.<br>
그중 하나만 충족해도 되는 대체 조건을 정의할 때 유용합니다.

**수량 지정 가능한 액션: 아니오**

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| userId | string |  | ✓|  |  ~ 128자 | 사용자ID<br>`#{userId}`로 설정하면 로그인 중인 사용자ID로 치환됩니다. |
| actions | [List&lt;VerifyAction&gt;](../sdk/#verifyaction) |  | |  | 0 ~ 10 items | 검증 액션 목록 |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |




**JSON**
```json
{
    "action": "Gs2Distributor:OrExpressionByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "actions": [
            {
                "action": "[string]검증 액션에서 실행할 액션의 종류",
                "request": "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
            }
        ],
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
```

**YAML**
```yaml

action: Gs2Distributor:OrExpressionByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  actions: 
    - action: "[string]검증 액션에서 실행할 액션의 종류"
      request: "[string]액션 실행 시 사용되는 요청의 JSON 문자열"
  timeOffsetToken: "[string]타임 오프셋 토큰"
```

**GS2-Script**
```lua

transaction.service("distributor").verify.or_expression_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    actions={
        {
            action="[string]검증 액션에서 실행할 액션의 종류",
            request="[string]액션 실행 시 사용되는 요청의 JSON 문자열"
        }
    },
    timeOffsetToken="[string]타임 오프셋 토큰",
})
```


---





