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

# GS2-Lock SDK for Game Engine API 레퍼런스

게임 엔진용 GS2-Lock SDK의 모델 사양과 API 레퍼런스



## 모델

### EzMutex

뮤텍스<br>

GS2가 제공하는 뮤텍스는 재진입 가능한 락의 일종입니다.<br>

잠금을 획득할 때 트랜잭션 ID를 지정하며, 동일한 트랜잭션 ID를 지정한 경우에만 다시 잠금을 획득할 수 있습니다.<br>
참조 카운터를 가지므로, 해제할 때에는 동일한 횟수만큼 잠금 해제 처리가 필요합니다.

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| mutexId | string |  | ※ |  |  ~ 1024자 | 뮤텍스 GRN<br>※ 서버가 자동으로 설정 |
| propertyId | string |  | ✓ |  |  ~ 1024자 | 프로퍼티 ID<br>잠금 대상 리소스를 식별하기 위한 ID로, 어떤 리소스에 대한 잠금인지를 결정합니다.<br>여러 처리가 동일한 리소스에 대한 배타적 접근을 필요로 하는 경우, 동일한 프로퍼티 ID를 지정해야 합니다. |
| transactionId | string |  | ✓ |  |  ~ 256자 | 트랜잭션 ID<br>잠금을 획득하는 트랜잭션의 식별자입니다. 이 ID는 재진입 가능한 잠금을 구현하는 데 사용됩니다.<br>잠금 요청이 현재 잠금을 보유한 것과 동일한 트랜잭션 ID를 지정한 경우, 잠금은 재획득에 성공하며 참조 카운터가 증가합니다.<br>다른 트랜잭션 ID로의 잠금 요청은 잠금이 유지되는 동안 거부됩니다. |
| ttlAt | long |  |  | 현재 시각으로부터 1시간 후의 절대 시각 |  | 유효기간 일시<br>UNIX 시간・밀리초 |

**관련 메서드:**
get - 뮤텍스 상태 조회
lock - 잠금 획득
unlock - 잠금 해제


---

## 메서드

### get

뮤텍스 상태 조회

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| propertyId | string |  | ✓|  |  ~ 1024자 | 프로퍼티 ID<br>잠금 대상 리소스를 식별하기 위한 ID로, 어떤 리소스에 대한 잠금인지를 결정합니다.<br>여러 처리가 동일한 리소스에 대한 배타적 접근을 필요로 하는 경우, 동일한 프로퍼티 ID를 지정해야 합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzMutex](#ezmutex) | 뮤텍스|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Lock.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Mutex(
        propertyId: "property-0001"
    );
    var item = await domain.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Lock.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Mutex(
        propertyId: "property-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Lock->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Mutex(
        "property-0001" // propertyId
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

```


##### 값 변경 이벤트 핸들링




**Unity (UniTask)**
```csharp
    var domain = gs2.Lock.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Mutex(
        propertyId: "property-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Lock.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Mutex(
        propertyId: "property-0001"
    );
    
    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Lock->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Mutex(
        "property-0001" // propertyId
    );
    
    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Lock::Model::FMutex> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);

```


**⚠️ Warning**

이 이벤트는 SDK가 가진 로컬 캐시의 값이 변경되었을 때 호출됩니다.

로컬 캐시는 SDK가 가진 API의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-Distributor를 통한 스탬프 시트의 실행, 또는 GS2-Gateway의 알림을 활성화한 GS2-JobQueue의 실행에 의해 변화한 것만이 대상이 됩니다.

따라서 이 방법 이외로 값이 변경된 경우 콜백은 호출되지 않습니다.

---

### lock

잠금 획득<br>

ttl로 지정한 초 동안 `프로퍼티 ID`의 리소스를 잠급니다.<br>
잠금 시에는 `트랜잭션 ID`를 지정해야 합니다.<br>
서로 다른 `트랜잭션 ID`로 동일한 `프로퍼티 ID`에 대한 잠금 획득을 시도하면 실패합니다.<br>
동일한 트랜잭션으로부터의 잠금 획득 요청인 경우에는 참조 카운터를 증가시킵니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| propertyId | string |  | ✓|  |  ~ 1024자 | 프로퍼티 ID<br>잠금 대상 리소스를 식별하기 위한 ID로, 어떤 리소스에 대한 잠금인지를 결정합니다.<br>여러 처리가 동일한 리소스에 대한 배타적 접근을 필요로 하는 경우, 동일한 프로퍼티 ID를 지정해야 합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| transactionId | string |  | ✓|  |  ~ 256자 | 트랜잭션 ID<br>잠금을 획득하는 트랜잭션의 식별자입니다. 이 ID는 재진입 가능한 잠금을 구현하는 데 사용됩니다.<br>잠금 요청이 현재 잠금을 보유한 것과 동일한 트랜잭션 ID를 지정한 경우, 잠금은 재획득에 성공하며 참조 카운터가 증가합니다.<br>다른 트랜잭션 ID로의 잠금 요청은 잠금이 유지되는 동안 거부됩니다. |
| ttl | long |  | ✓|  | 0 ~ 9223372036854775805 | 잠금 획득 기간(초) |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzMutex](#ezmutex) | 뮤텍스|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Lock.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Mutex(
        propertyId: "property-0001"
    );
    var result = await domain.LockAsync(
        transactionId: "transaction-0001",
        ttl: 100000L
    );
    var item = await result.ModelAsync();

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Lock.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Mutex(
        propertyId: "property-0001"
    );
    var future = domain.LockFuture(
        transactionId: "transaction-0001",
        ttl: 100000L
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Lock->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Mutex(
        "property-0001" // propertyId
    );
    const auto Future = Domain->Lock(
        "transaction-0001", // transactionId
        100000L // ttl
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

```


---

### unlock

잠금 해제<br>

잠금을 해제하려면 동일한 `트랜잭션 ID`로부터 해제해야 합니다.<br>
잠금 획득 시 재진입이 이루어진 경우에는 동일한 횟수만큼 잠금 해제를 수행해야 하며, 참조 카운터가 0이 되는 시점에 실제로 해제가 이루어집니다.

#### Request

|  | 타입 | 활성화 조건 | 필수 | 기본값 | 값 제한 | 설명 |
| --- | --- | --- | --- | --- | --- | --- |
| namespaceName | string |  | ✓|  |  ~ 128자 | 네임스페이스 이름<br>네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다. |
| propertyId | string |  | ✓|  |  ~ 1024자 | 프로퍼티 ID<br>잠금 대상 리소스를 식별하기 위한 ID로, 어떤 리소스에 대한 잠금인지를 결정합니다.<br>여러 처리가 동일한 리소스에 대한 배타적 접근을 필요로 하는 경우, 동일한 프로퍼티 ID를 지정해야 합니다. |
| gameSession | GameSession | | ✓|  |  | GameSession |
| transactionId | string |  | ✓|  |  ~ 256자 | 트랜잭션 ID<br>잠금을 획득하는 트랜잭션의 식별자입니다. 이 ID는 재진입 가능한 잠금을 구현하는 데 사용됩니다.<br>잠금 요청이 현재 잠금을 보유한 것과 동일한 트랜잭션 ID를 지정한 경우, 잠금은 재획득에 성공하며 참조 카운터가 증가합니다.<br>다른 트랜잭션 ID로의 잠금 요청은 잠금이 유지되는 동안 거부됩니다. |

#### Result

|  | 타입 | 설명 |
| --- | --- | --- |
| item | [EzMutex](#ezmutex) | 뮤텍스|

#### 구현 예제




**Unity (UniTask)**
```csharp
    var domain = gs2.Lock.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Mutex(
        propertyId: "property-0001"
    );
    var result = await domain.UnlockAsync(
        transactionId: "transaction-0001"
    );

```

**Unity (Vanilla)**
```cs
    var domain = gs2.Lock.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Mutex(
        propertyId: "property-0001"
    );
    var future = domain.UnlockFuture(
        transactionId: "transaction-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }

```

**Unreal Engine 5**
```cpp
    const auto Domain = Gs2->Lock->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Mutex(
        "property-0001" // propertyId
    );
    const auto Future = Domain->Unlock(
        "transaction-0001" // transactionId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

```


---



