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

# GS2-JobQueue 트랜잭션 액션

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




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

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

GS2-JobQueue의 트랜잭션 액션은 네임스페이스와 사용자의 조합으로 결정되는 한 사용자의 잡 큐를 대상으로 합니다. 등록은 항상 새로운 잡을 만들므로 등록마다 다른 대상이 되고, 삭제는 잡 이름으로 특정되는 기존 잡 하나를 대상으로 합니다.

조작 | 같은 행을 겹쳤을 때 | 중첩 너머 | 다른 대상이 되는 경계 | 직렬 실행 모드 활성화 시
--- | --- | --- | --- | ---
잡의 등록<br>`PushByUserId` | 1건의 등록으로 통합되어 잡의 리스트가 연결된다. 합계가 10건을 넘으면 발행 시에 오류가 된다 | 충돌하지 않는다. 등록할 때마다 자신의 잡을 만든다 | 등록할 때마다 다른 대상 | 변하지 않는다. 원래부터 충돌하지 않는다
잡의 삭제<br>`DeleteJobByUserId` | 1건으로 통합된다 | 실패한다 | 네임스페이스·사용자·잡 이름 | 계속 실패한다. 1건으로 묶이지 않게 되므로, 2건째는 이미 사라진 잡에 대해 실행되어 찾을 수 없음(404)으로 거부된다

트랜잭션에서 등록한 잡은 그 트랜잭션의 다른 액션에서는 아직 존재하지 않는 것으로 취급됩니다. 모든 액션이 트랜잭션 시작 시점의 상태를 기준으로 동작하기 때문입니다. 잡을 쌓은 뒤 조작하고 싶은 경우에는 트랜잭션을 나누어 주십시오.

여러 잡을 한꺼번에 쌓고 싶은 경우에는, 액션을 여러 번 지정하기보다 하나의 등록의 `jobs`에 나열하여 지정하는 편이 간결하고 처리도 가볍습니다.

### 잡은 트랜잭션 안이 아니라 나중에 실행됩니다

쌓인 잡은 트랜잭션의 일부로서 실행되지 않습니다. 나중에 꺼내어져 단독으로 실행되며, 그 내용은 이 트랜잭션이 아니라 잡이 건드리는 서비스 각각의 제한을 받습니다.

이것이 GS2-JobQueue를 다른 서비스의 제한 회피에 사용할 수 있는 이유입니다. 같은 것을 업데이트하기 위해 하나의 트랜잭션에 넣을 수 없는 두 개의 액션이 있는 경우, 한쪽을 잡으로 쌓으면 별개의 트랜잭션으로 나눌 수 있습니다. 그 대신 그 결과는 트랜잭션의 응답 시점에는 반영되어 있지 않고, 트랜잭션 전체와 일괄로 성공·실패하는 일도 없어집니다.

같은 발상은 액션으로 명시하는 것이 아니라 설정으로도 사용할 수 있습니다. 네임스페이스의 트랜잭션 설정에서 `acquireActionUseJobQueue`를 활성화하면, 그 네임스페이스의 트랜잭션에서 획득 액션이 2개 이상일 때 그것들이 GS2-JobQueue를 거쳐 하나씩 실행되게 됩니다.

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

안쪽에서 삭제된 잡과 바깥쪽에서 삭제된 같은 잡이 충돌합니다. 등록은 영향을 받지 않습니다. 등록할 때마다 자신의 잡을 만들기 때문입니다. **직렬 실행 모드(`enableSequentialExecution` 또는 `TransactionSettingV2`)를 활성화해도 이 실패는 사라지지 않습니다. 안쪽 트랜잭션이 바깥쪽과 같은 직렬 실행 구간에서 실행되어 두 개의 삭제가 1건으로 묶이지 않게 되고, 2건째는 이미 사라진 잡에 대해 실행되어 병합 충돌이 아니라 「찾을 수 없음」 오류로 실패합니다.**

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

잡의 등록은 획득 액션, 잡의 삭제는 소비 액션입니다. 삭제끼리의 충돌은 소비 액션끼리이므로 `acquireActionUseJobQueue`로는 분리할 수 없고, `enableAtomicCommit`을 비활성화해야 합니다. 등록의 연결이 상한을 넘어 발행 시에 오류가 되는 경우에는 어느 설정으로도 해소되지 않습니다. 등록을 나누어 주십시오.

### 동시 실행과 재시도

잡의 등록은 요청이 몇 개 겹쳐도 충돌하지 않습니다. 등록할 때마다 자신의 잡을 만들기 때문입니다.

잡의 삭제는 그 잡이 아직 존재하는지를 확인합니다. 그 때문에 같은 잡을 동시에 삭제하면 나중에 확정된 쪽이 오류가 됩니다. 삭제 도중에 잡이 실행을 마치고 제거된 경우도 마찬가지입니다.

---



## Consume Action

소비 액션

### Gs2JobQueue:DeleteJobByUserId

사용자 ID를 지정하여 잡 삭제<br>

지정한 사용자의 잡 큐에서 특정 잡을 삭제합니다.<br>
실행 상태와 관계없이 잡이 삭제됩니다.

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

**반전 가능한 액션: 아니오**

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| userId | string |  | ✓|  |  ~ 128자 | 사용자ID<br>`#{userId}`로 설정하면 로그인 중인 사용자ID로 치환됩니다. |
| jobName | string |  | ✓| UUID |  ~ 36자 | 잡 이름<br>잡의 고유한 이름을 보유합니다.<br>이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 각 잡을 식별하는 데 사용됩니다. |
| timeOffsetToken | string |  | |  |  ~ 1024자 | 타임 오프셋 토큰 |




**JSON**
```json
{
    "action": "Gs2JobQueue:DeleteJobByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "jobName": "[string]잡 이름",
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
```

**YAML**
```yaml

action: Gs2JobQueue:DeleteJobByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  jobName: "[string]잡 이름"
  timeOffsetToken: "[string]타임 오프셋 토큰"
```

**GS2-Script**
```lua

transaction.service("jobQueue").consume.delete_job_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    jobName="[string]잡 이름",
    timeOffsetToken="[string]타임 오프셋 토큰",
})
```


---

## Acquire Action

입수 액션

### Gs2JobQueue:PushByUserId

사용자 ID를 지정하여 잡 등록<br>

사용자의 잡 큐에 하나 이상의 잡을 등록합니다(최대 10건).<br>
각 잡에는 실행할 GS2-Script, 인수, 최대 재시도 횟수를 지정합니다.<br>
네임스페이스에서 enableAutoRun이 활성화된 경우, 잡은 등록 후 즉시 비동기로 실행되며, 응답의 autoRun 플래그가 true가 됩니다.<br>
enableAutoRun이 비활성화되어 있으면 잡은 큐에 추가되고 Run API를 통해 수동으로 실행해야 하며, autoRun 플래그는 false가 됩니다.

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

**반전 가능한 액션: 아니오**

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




**JSON**
```json
{
    "action": "Gs2JobQueue:PushByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "jobs": [
            {
                "scriptId": "[string]스크립트 GRN",
                "args": "[string]인수",
                "maxTryCount": "[int]최대 시도 횟수"
            }
        ],
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
```

**YAML**
```yaml

action: Gs2JobQueue:PushByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  jobs: 
    - scriptId: "[string]스크립트 GRN"
      args: "[string]인수"
      maxTryCount: "[int]최대 시도 횟수"
  timeOffsetToken: "[string]타임 오프셋 토큰"
```

**GS2-Script**
```lua

transaction.service("jobQueue").acquire.push_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    jobs={
        {
            scriptId="[string]스크립트 GRN",
            args="[string]인수",
            maxTryCount="[int]최대 시도 횟수"
        }
    },
    timeOffsetToken="[string]타임 오프셋 토큰",
})
```


---



