기술 자료

지원

Cloud Code

Cloud Code

배치 요청

Batch your requests to execute UGS service calls in parallel for efficiency.
읽는 시간 1분최근 업데이트: 한 달 전

UGS 서비스를 호출할 때 요청을 배치 처리하여 병렬로 실행할 수 있습니다.
Task.WhenAll
메서드를 사용하여 병렬로 UGS 서비스를 호출할 수 있습니다. 이 메서드는 인수 목록의 모든 작업이 완료되면 마무리되는
Task
를 반환합니다.

결과 호출 및 반환

아래 샘플을 사용하여 서비스를 호출하고 요청의 결과를 반환할 수 있습니다. 이 샘플에서는 Leaderboards 서비스와 Economy 서비스를 호출합니다. 프로젝트에 리더보드나 재화가 구성되어 있지 않으면 호출이 실패합니다. 이렇게 하면 Cloud Code 모듈에서 오류 처리를 테스트할 수 있습니다. 메서드는 요청 결과가 포함된 딕셔너리를 반환하며, 요청을 만든 메서드의 서명을 키로 사용하고 요청의 결과를 값으로 사용합니다. 요청이 실패하면 어떤 요청이 실패했는지 알려 줍니다. 이러한 요청도 물론 로그됩니다.
using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using Unity.Services.CloudCode.Apis;using Unity.Services.CloudCode.Core;using Unity.Services.CloudSave.Model;using Unity.Services.Economy.Model;namespace BatchingRequests;public class BatchingRequests{ private const string ExperienceKey = "experience"; private const string ProgressXpKey = "progressXP"; private const string FailedMessage = "Failed. Check logs."; private readonly ILogger<BatchingRequests> _logger; public BatchingRequests(ILogger<BatchingRequests> logger) { _logger = logger; } [CloudCodeFunction("HandleMultipleRequests")] public async Task<Dictionary<string, object>> HandleMultipleRequests(IGameApiClient gameApiClient, IExecutionContext ctx) { async Task<object> GetCloudSaveData() { var res = await gameApiClient.CloudSaveData.GetItemsAsync(ctx, ctx.AccessToken, ctx.ProjectId, ctx.PlayerId, new List<string> { ExperienceKey, ProgressXpKey }); return res.Data; } async Task<object> SetCloudSaveData() { var res = await gameApiClient.CloudSaveData.SetItemAsync(ctx, ctx.AccessToken, ctx.ProjectId, ctx.PlayerId, new SetItemBody(ExperienceKey, 1)); return res.Data; } async Task<object> GetLeaderboardScore() { const string leaderboardId = "leaderboard"; var res = await gameApiClient.Leaderboards.GetLeaderboardPlayerScoreAsync(ctx, ctx.AccessToken, Guid.Parse(ctx.ProjectId), leaderboardId, ctx.PlayerId); return res.Data; } async Task<object> GetEconomyConfig() { var res = await gameApiClient.EconomyConfiguration.GetPlayerConfigurationAsync(ctx, ctx.AccessToken, ctx.ProjectId, ctx.PlayerId); return res.Data; } async Task<object> SetEconomyConfig() { const string currencyId = "NOT_REAL"; var res = await gameApiClient.EconomyCurrencies.IncrementPlayerCurrencyBalanceAsync(ctx, ctx.AccessToken, ctx.ProjectId, ctx.PlayerId, currencyId, new CurrencyModifyBalanceRequest(currencyId, 1)); return res.Data; } // Create a list of UGS tasks that return data var tasksWithObjects = new List<Func<Task<object>>>() { GetCloudSaveData, GetLeaderboardScore, SetCloudSaveData, GetEconomyConfig, SetEconomyConfig }; var results = await AwaitBatch(tasksFns); foreach (var item in results) { if (item is Exception) { _logger.LogError($"AwaitBatch failed status {item}"); } else if (item is CurrencyBalanceResponse) { _logger.LogInformation($"AwaitBatch CurrencyBalanceResponse status {item.GetType()} = {item}"); } else { _logger.LogInformation($"AwaitBatch success status {item.GetType()} = {item}"); } } // Alternatively to looping through all results, you may access function results directly // The order of function results follows the order of the function input e.g. // - GetCloudSaveData corresponds to results[0]: GetItemsResponse || Exception // - GetLeaderboardScore corresponds to results[1]: LeaderboardEntryWithUpdatedTime || Exception // ... etc // This can also help ascertain where the Exception originated from } private async Task<object[]> AwaitBatch(List<Func<Task<object>>> tasks) { var tasksToRun = tasks.Select(Run); var results = await Task.WhenAll(tasksToRun); return results; } async Task<object> Run(Func<Task<object>> fn) { try { return await fn(); } catch (Exception e) { return e; } }}public class ModuleConfig : ICloudCodeSetup{ public void Setup(ICloudCodeConfig config) { config.Dependencies.AddSingleton(GameApiClient.Create()); }}