public IEnumerator WritePartyStorage(string @namespace, string accessToken, PartyDataUpdateRequest data,
                                             string partyId, ResultCallback <PartyDataUpdateNotif> callback, Action callbackOnConflictedData = null)
        {
            Assert.IsNotNull(@namespace, nameof(@namespace) + " cannot be null");
            Assert.IsNotNull(accessToken, nameof(accessToken) + " cannot be null");
            Assert.IsNotNull(partyId, nameof(partyId) + " cannot be null");
            Assert.IsNotNull(data, nameof(data) + " cannot be null");

            var request = HttpRequestBuilder
                          .CreatePut(this.baseUrl + "/v1/admin/party/namespaces/{namespace}/parties/{partyId}/attributes")
                          .WithPathParam("namespace", @namespace)
                          .WithPathParam("partyId", partyId)
                          .WithBearerAuth(accessToken)
                          .WithBody(data.ToUtf8Json())
                          .WithContentType(MediaType.ApplicationJson)
                          .Accepts(MediaType.ApplicationJson)
                          .GetResult();

            IHttpResponse response = null;

            yield return(this.httpWorker.SendRequest(request, rsp => response = rsp));

            var result = response.TryParseJson <PartyDataUpdateNotif>();

            if (result.IsError && result.Error.Code == ErrorCode.PreconditionFailed)
            {
                callbackOnConflictedData?.Invoke();
            }
            else
            {
                callback.Try(result);
            }
        }
        private void WritePartyStorageRecursive(int remainingAttempt, string partyId, ResultCallback <PartyDataUpdateNotif> callback, Func <Dictionary <string, object>, Dictionary <string, object> > payloadModifier)
        {
            if (remainingAttempt <= 0)
            {
                callback.TryError(new Error(ErrorCode.PreconditionFailed, "Exhaust all retry attempt to modify party storage. Please try again."));
                return;
            }

            GetPartyStorage(partyId, getPartyStorageResult =>
            {
                if (getPartyStorageResult.IsError)
                {
                    callback.TryError(getPartyStorageResult.Error);
                }
                else
                {
                    getPartyStorageResult.Value.custom_attribute = payloadModifier(getPartyStorageResult.Value.custom_attribute);

                    var updateRequest = new PartyDataUpdateRequest();
                    updateRequest.custom_attribute = getPartyStorageResult.Value.custom_attribute;
                    updateRequest.updatedAt        = getPartyStorageResult.Value.updatedAt;

                    this.coroutineRunner.Run(
                        this.api.WritePartyStorage(
                            this.namespace_,
                            this.session.AuthorizationToken,
                            updateRequest,
                            partyId,
                            callback,
                            () =>
                    {
                        WritePartyStorageRecursive(remainingAttempt - 1, partyId, callback, payloadModifier);
                    }));
                }
            });
        }