Documentation index for AI agents

GS2-Exchange 트랜잭션 액션

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

액션의 조합과 동시 실행

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

GS2-Exchange의 트랜잭션 액션은 교환 대기를 거치는 것과 한 번에 교환하는 것 두 가지로 나뉩니다. 교환 대기는 네임스페이스·사용자·교환 대기 이름의 조합으로 결정됩니다.

조작같은 행을 겹쳤을 때중첩 너머다른 대상이 되는 경계
교환 대기의 생성
CreateAwaitByUserId
같은 교환 레이트라면 통합되어 수가 합산된다실패한다네임스페이스·사용자·교환 레이트
교환 대기의 스킵
SkipByUserId
통합되어 단축 시간이 합산된다실패한다네임스페이스·사용자·교환 대기
교환 대기 결과의 수령
AcquireForceByUserId
1건으로 통합된다실패한다네임스페이스·사용자·교환 대기
교환 대기의 파기
DeleteAwaitByUserId
1건으로 통합된다실패한다네임스페이스·사용자·교환 대기
한 번에 교환
ExchangeByUserId IncrementalExchangeByUserId
같은 레이트라면 통합되어 수가 합산된다교환 대기를 건드리지 않는다네임스페이스·사용자·교환 레이트

결과의 수령과 파기는 둘 다 교환 대기를 지우고, 생성은 교환 대기를 늘리므로, 이 중 두 개를 하나의 트랜잭션에 넣으면 충돌합니다. 스킵한 뒤 결과를 수령하는 흐름도 하나의 트랜잭션으로는 할 수 없습니다. 결과의 수령은 트랜잭션 시작 시점의 상태를 기준으로 판정되므로 스킵이 아직 보이지 않기 때문입니다.

ExchangeByUserIdIncrementalExchangeByUserId는 교환 대기를 전혀 건드리지 않습니다. 무엇을 소비하고 무엇을 획득할지를 산출하여 그것들을 자신의 트랜잭션으로 발행하므로, 그것들이 속한 서비스의 제한이 그대로 해당되며 아래의 내용도 해당됩니다. 증분 교환은 교환할 때마다 레이트도 올리지만, 이것도 발행하는 것의 일부입니다.

중첩된 트랜잭션에 주의

안쪽에서 생성된 교환 대기와 바깥쪽에서 수령되거나 파기된 교환 대기가 충돌하여 트랜잭션이 실패합니다.

제한을 회피하고 싶은 경우

교환 대기의 생성·스킵·결과의 수령, 그리고 한 번에 교환은 획득 액션, 교환 대기의 파기는 소비 액션입니다. 획득 액션끼리의 충돌은 acquireActionUseJobQueue를 활성화하면 해소할 수 있습니다. 파기와의 공존은 enableAtomicCommit을 비활성화하면 해소되며, 이때 파기는 획득 액션보다 먼저 실행됩니다.

동시 실행과 재시도

같은 교환 대기를 여러 요청이 동시에 건드린 경우, 나중에 확정된 쪽이 충돌(409)이 됩니다. 재시도하면 최신 상태로 다시 판정되므로, 교환 대기가 아직 남아 있으면 성공하고 이미 수령되거나 파기되었으면 오류가 반환됩니다.

교환 대기 이름이 다르면 다른 대상이므로, 다른 교환 대기에 대한 요청끼리는 충돌하지 않습니다.


Consume Action

소비 액션

Gs2Exchange:DeleteAwaitByUserId

사용자 ID를 지정하여 교환 대기 삭제

지정된 사용자의 교환 대기 레코드를 삭제합니다.
보류 중인 교환이 취소되며, 아직 취득하지 않은 보상은 포기됩니다.

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

반전 가능한 액션: 아니오

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
userIdstring
~ 128자사용자ID
#{userId}로 설정하면 로그인 중인 사용자ID로 치환됩니다.
awaitNamestring
UUID~ 36자교환 대기의 이름
교환 대기의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 교환 대기를 식별하는 데 사용됩니다.
timeOffsetTokenstring~ 1024자타임 오프셋 토큰
{
    "action": "Gs2Exchange:DeleteAwaitByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "awaitName": "[string]교환 대기의 이름",
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
action: Gs2Exchange:DeleteAwaitByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  awaitName: "[string]교환 대기의 이름"
  timeOffsetToken: "[string]타임 오프셋 토큰"
transaction.service("exchange").consume.delete_await_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    awaitName="[string]교환 대기의 이름",
    timeOffsetToken="[string]타임 오프셋 토큰",
})

Acquire Action

입수 액션

Gs2Exchange:ExchangeByUserId

사용자 ID를 지정하여 교환을 실행

지정된 사용자에 대해, 지정된 교환 레이트 모델에 기반하여 리소스 교환을 실행합니다.
레이트 모델의 타이밍 타입을 검증합니다: ‘immediate’ 타이밍의 경우 네임스페이스에서 직접 교환이 유효해야 하며, ‘await’ 타이밍의 경우 대기 교환이 유효해야 합니다.
레이트 모델에서 정의된 소비·검증·획득 액션을 지정한 횟수만큼 실행하는 트랜잭션이 발행됩니다.

수량 지정 가능한 액션: 예

반전 가능한 액션: 아니오

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
rateNamestring
~ 128자교환 레이트 모델 이름
교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
userIdstring
~ 128자사용자ID
#{userId}로 설정하면 로그인 중인 사용자ID로 치환됩니다.
countint
1 ~ 1073741821교환 횟수
configList<Config>[]0 ~ 32 items트랜잭션 변수에 적용할 설정값
timeOffsetTokenstring~ 1024자타임 오프셋 토큰
{
    "action": "Gs2Exchange:ExchangeByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "rateName": "[string]교환 레이트 모델 이름",
        "userId": "[string]사용자ID",
        "count": "[int]교환 횟수",
        "config": [
            {
                "key": "[string]이름",
                "value": "[string]값"
            }
        ],
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
action: Gs2Exchange:ExchangeByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  rateName: "[string]교환 레이트 모델 이름"
  userId: "[string]사용자ID"
  count: "[int]교환 횟수"
  config: 
    - key: "[string]이름"
      value: "[string]값"
  timeOffsetToken: "[string]타임 오프셋 토큰"
transaction.service("exchange").acquire.exchange_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    rateName="[string]교환 레이트 모델 이름",
    userId="[string]사용자ID",
    count="[int]교환 횟수",
    config={
        {
            key="[string]이름",
            value="[string]값"
        }
    },
    timeOffsetToken="[string]타임 오프셋 토큰",
})

Gs2Exchange:IncrementalExchangeByUserId

사용자 ID를 지정하여 코스트 상승형 교환 실행

지정된 사용자에 대해, 지정된 코스트 상승형 교환 레이트 모델을 기반으로, 실행 횟수에 따라 코스트가 단계적으로 상승하는 리소스 교환을 실행합니다.
소비 코스트는 모델의 계산 타입(선형 계산식 또는 GS2-Script)과 현재 교환 횟수를 기반으로 계산됩니다.
소비·획득 액션을 실행하는 트랜잭션이 발행됩니다.

수량 지정 가능한 액션: 예

반전 가능한 액션: 아니오

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
rateNamestring
~ 128자코스트 상승형 교환 레이트 모델의 이름
코스트 상승형 교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
userIdstring
~ 128자사용자ID
#{userId}로 설정하면 로그인 중인 사용자ID로 치환됩니다.
countint
1 ~ 1073741821교환 횟수
configList<Config>[]0 ~ 32 items트랜잭션 변수에 적용할 설정값
timeOffsetTokenstring~ 1024자타임 오프셋 토큰
{
    "action": "Gs2Exchange:IncrementalExchangeByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "rateName": "[string]코스트 상승형 교환 레이트 모델의 이름",
        "userId": "[string]사용자ID",
        "count": "[int]교환 횟수",
        "config": [
            {
                "key": "[string]이름",
                "value": "[string]값"
            }
        ],
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
action: Gs2Exchange:IncrementalExchangeByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  rateName: "[string]코스트 상승형 교환 레이트 모델의 이름"
  userId: "[string]사용자ID"
  count: "[int]교환 횟수"
  config: 
    - key: "[string]이름"
      value: "[string]값"
  timeOffsetToken: "[string]타임 오프셋 토큰"
transaction.service("exchange").acquire.incremental_exchange_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    rateName="[string]코스트 상승형 교환 레이트 모델의 이름",
    userId="[string]사용자ID",
    count="[int]교환 횟수",
    config={
        {
            key="[string]이름",
            value="[string]값"
        }
    },
    timeOffsetToken="[string]타임 오프셋 토큰",
})

Gs2Exchange:CreateAwaitByUserId

사용자 ID를 지정하여 교환 대기를 작성

시간 대기형 교환의 새로운 교환 대기 레코드를 작성합니다.
지정된 레이트 모델의 타이밍 타입은 ‘await’이어야 하며, 그렇지 않은 경우 요청이 거부됩니다.
대기는 스킵 초수 0으로 시작되며, 레이트 모델에서 정의된 잠금 시간이 보상 획득까지의 사용자 대기 시간을 결정합니다.
작성 시 기본 설정값을 지정할 수 있으며, 획득 시 제공되는 설정값과 병합됩니다.

수량 지정 가능한 액션: 예

반전 가능한 액션: 아니오

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
userIdstring
~ 128자사용자ID
#{userId}로 설정하면 로그인 중인 사용자ID로 치환됩니다.
rateNamestring
~ 128자교환 레이트 모델 이름
교환 레이트 모델 종류 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
countint11 ~ 10000교환 수
이 교환을 실행하는 횟수입니다. 여러 번의 교환을 하나의 대기로 묶을 수 있으며, 소비되는 코스트와 받는 보상이 모두 곱해집니다.
configList<Config>[]0 ~ 32 items보상 획득 시 적용하는 기본 설정값
timeOffsetTokenstring~ 1024자타임 오프셋 토큰
{
    "action": "Gs2Exchange:CreateAwaitByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "rateName": "[string]교환 레이트 모델 이름",
        "count": "[int]교환 수",
        "config": [
            {
                "key": "[string]이름",
                "value": "[string]값"
            }
        ],
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
action: Gs2Exchange:CreateAwaitByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  rateName: "[string]교환 레이트 모델 이름"
  count: "[int]교환 수"
  config: 
    - key: "[string]이름"
      value: "[string]값"
  timeOffsetToken: "[string]타임 오프셋 토큰"
transaction.service("exchange").acquire.create_await_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    rateName="[string]교환 레이트 모델 이름",
    count="[int]교환 수",
    config={
        {
            key="[string]이름",
            value="[string]값"
        }
    },
    timeOffsetToken="[string]타임 오프셋 토큰",
})

Gs2Exchange:AcquireForceByUserId

교환 대기의 보상을 대기 시간 판정 없이 강제 취득

잠금 시간이 경과했는지 여부와 관계없이 교환 대기의 보상을 강제로 취득합니다.
일반적인 대기 시간 확인을 우회하여 즉시 보상을 취득할 수 있습니다.
제공된 설정값은 대기 작성 시 설정된 기본 설정값과 병합됩니다.
레이트 모델에서 정의된 획득 액션을 실행하는 트랜잭션이 발행됩니다.

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

반전 가능한 액션: 아니오

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
userIdstring
~ 128자사용자ID
#{userId}로 설정하면 로그인 중인 사용자ID로 치환됩니다.
awaitNamestring
UUID~ 36자교환 대기의 이름
교환 대기의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 교환 대기를 식별하는 데 사용됩니다.
configList<Config>[]0 ~ 32 items트랜잭션 변수에 적용할 설정값
timeOffsetTokenstring~ 1024자타임 오프셋 토큰
{
    "action": "Gs2Exchange:AcquireForceByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "awaitName": "[string]교환 대기의 이름",
        "config": [
            {
                "key": "[string]이름",
                "value": "[string]값"
            }
        ],
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
action: Gs2Exchange:AcquireForceByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  awaitName: "[string]교환 대기의 이름"
  config: 
    - key: "[string]이름"
      value: "[string]값"
  timeOffsetToken: "[string]타임 오프셋 토큰"
transaction.service("exchange").acquire.acquire_force_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    awaitName="[string]교환 대기의 이름",
    config={
        {
            key="[string]이름",
            value="[string]값"
        }
    },
    timeOffsetToken="[string]타임 오프셋 토큰",
})

Gs2Exchange:SkipByUserId

사용자 ID를 지정하여 교환 대기를 스킵

교환 대기의 대기 시간을 가속하거나 스킵합니다.
4가지 스킵 타입을 지원합니다: ‘complete’는 남은 대기 시간을 전부 스킵하고, ‘minutes’는 지정한 분수를 스킵 초수에 더하며, ’totalRate’는 전체 잠금 시간의 비율만큼 스킵하고, ‘remainRate’는 남은 대기 시간의 비율만큼 스킵합니다.
스킵 초수는 합계 잠금 시간이 상한이 되며, 이를 초과할 수 없습니다.

수량 지정 가능한 액션: 예

반전 가능한 액션: 아니오

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
userIdstring
~ 128자사용자ID
#{userId}로 설정하면 로그인 중인 사용자ID로 치환됩니다.
awaitNamestring
UUID~ 36자교환 대기의 이름
교환 대기의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 교환 대기를 식별하는 데 사용됩니다.
skipType문자열 열거형
enum {
  “complete”,
  “minutes”,
  “totalRate”,
  “remainRate”
}
“complete”스킵 방법
정의설명
complete완전히 스킵
minutes시간을 지정하여 스킵(분)
totalRate전체 대기 시간의 비율을 지정하여 스킵
remainRate남은 대기 시간의 비율을 지정하여 스킵
minutesint{skipType} == “minutes”0 ~ 2147483646스킵할 분수
※ skipType이(가) “minutes” 이면 활성화
ratefloat{skipType} == “totalRate” or {skipType} == “remainRate”0 ~ 1스킵할 대기 시간의 비율
timeOffsetTokenstring~ 1024자타임 오프셋 토큰
{
    "action": "Gs2Exchange:SkipByUserId",
    "request": {
        "namespaceName": "[string]네임스페이스 이름",
        "userId": "[string]사용자ID",
        "awaitName": "[string]교환 대기의 이름",
        "skipType": "[string]스킵 방법",
        "minutes": "[int]스킵할 분수",
        "rate": "[float]스킵할 대기 시간의 비율",
        "timeOffsetToken": "[string]타임 오프셋 토큰"
    }
}
action: Gs2Exchange:SkipByUserId
request:
  namespaceName: "[string]네임스페이스 이름"
  userId: "[string]사용자ID"
  awaitName: "[string]교환 대기의 이름"
  skipType: "[string]스킵 방법"
  minutes: "[int]스킵할 분수"
  rate: "[float]스킵할 대기 시간의 비율"
  timeOffsetToken: "[string]타임 오프셋 토큰"
transaction.service("exchange").acquire.skip_by_user_id({
    namespaceName="[string]네임스페이스 이름",
    userId="[string]사용자ID",
    awaitName="[string]교환 대기의 이름",
    skipType="[string]스킵 방법",
    minutes="[int]스킵할 분수",
    rate="[float]스킵할 대기 시간의 비율",
    timeOffsetToken="[string]타임 오프셋 토큰",
})