question

sam-4 avatar image
sam-4 asked

ExecuteInventoryOperations - Missing Parameters

Hi there, I'm trying to use ExecuteInventoryOperations from an azure function but it's returning an error saying "Missing parameters".

This is how I'm calling the request:

                     ExecuteInventoryOperationsRequest ExecuteInventoryOperationsRequest = new();
                     ExecuteInventoryOperationsRequest.Entity = Context.CallerEntityProfile.Entity.ToEconomyEntityKey();
    
                     ExecuteInventoryOperationsRequest.Operations = new();
                     foreach (CatalogItem Item in ItemsToGrant)
                     {
                         AddInventoryItemsOperation Operation = new();
                         Operation.Item = new InventoryItemReference { Id = Item.Id };
                         Operation.Amount = 1;
                         Operation.NewStackValues = new();
                         ExecuteInventoryOperationsRequest.Operations.Add(new InventoryOperation{Add= Operation});
                     }
    
                     var Result = await PlayFabServerUtils.GetEconomyAPI(Context).ExecuteInventoryOperationsAsync(ExecuteInventoryOperationsRequest);

The API instance running the request has the title authentication and the developer secret key which works fine for other requests. I'm not sure how to find out what parameter I'm missing and I can't find any code examples for this. What am I doing wrong?

Much thanks for the help.

In-Game EconomyPlayer Inventory
3 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Gosen Gao avatar image Gosen Gao commented ·

Your code works fine in my tests. Please provide the detailed error message for research.

0 Likes 0 ·
sam-4 avatar image sam-4 Gosen Gao commented ·

Hi, here's the full error: - Error {PlayFab.PlayFabError} PlayFab.PlayFabError Error InvalidRequest PlayFab.PlayFabErrorCode ErrorDetails null System.Collections.Generic.Dictionary<string, string[]> ErrorMessage "Missing parameters." string HttpCode 400 int HttpStatus "BadRequest" string RequestId "1-63b42312-03b94f511b888599140abc49" string RetryAfterSeconds null uint?

0 Likes 0 ·
sam-4 avatar image sam-4 sam-4 commented ·
 -        Error    {PlayFab.PlayFabError}    PlayFab.PlayFabError
         Error    InvalidRequest    PlayFab.PlayFabErrorCode
         ErrorDetails    null    System.Collections.Generic.Dictionary&lt;string, string[]&gt;
         ErrorMessage    "Missing parameters."    string
         HttpCode    400    int
         HttpStatus    "BadRequest"    string
         RequestId    "1-63b42312-03b94f511b888599140abc49"    string
         RetryAfterSeconds    null    uint?

Trying to post it again because the formatting didn't work and there doesn't seem to be any edit functionality

0 Likes 0 ·
sam-4 avatar image
sam-4 answered

Thanks, I think the problem was that I was trying to add too many items and I didn't realise the limit was only 5. I would suggest that the error should be updated to reflect this because "missing parameters" is not very clear.

Can I ask, what would you recommend doing if I need to add a large amount of items, like around 250?

6 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

kylemc@microsoft.com avatar image kylemc@microsoft.com commented ·

250 is a lot to add in a single transaction. What's the scenario?

One thing you can do is grant a bundle instead of granting items directly. With the bundle size limit and the operations limit, you should be able to reduce this grant to just a handful of calls.

0 Likes 0 ·
sam-4 avatar image sam-4 kylemc@microsoft.com commented ·

Hi, this exact scenario is a developer tool used to add all items in the game to a player account, though it's possible we'd need to support large throughputs for certain events during gameplay as well (for example, "tournament" game events that grant large rewards to multiple players)

Right now there are a little over 250 items but there will likely be many many more in the future. Since the list is dynamic it needs to be controlled by function logic and not predefined (unless we can do something hacky like create a new bundle dynamically every time we need to do this and delete it afterward?)

Currently in order to achieve this within the limitations we need to perform 6 SearchItem requests as they return 50 items each. From profiling it, this seems to take about 1.9s for all the requests to complete which is already quite slow. Then to add the items, 42 ExecuteInventoryOperations requests of only 5 items each, which we have to run in sequence since we get "too many requests" trying to run them in parallel. Since each of these requests seems to take 300ms to 1.6s, this takes around 28.9s to complete in total which is long past causing the Azure function to timeout.

0 Likes 0 ·
sam-4 avatar image sam-4 kylemc@microsoft.com commented ·

I'm concerned these per-request limits might be a dealbreaker for our purposes. If ~250 items takes 30 seconds, then even operating on a fraction of that would still be problematically slow. Are we stepping out of PlayFab's capabilities here? Thanks.

0 Likes 0 ·
kylemc@microsoft.com avatar image kylemc@microsoft.com sam-4 commented ·

Are your items entitlements (like a skin), currencies, consumables (like a boost), or items you might just have one or two of (like a hat)?

Is your scenario to test what each item looks like in the game or are you going to run each item through a bunch of logic (adding, subtracting, updating, etc.)?

There's definitely a write throttle at our data layer, but it isn't the one you see publicly. There will always be a limit to how fast you can modify a single user, so I'm interested is seeing if there's a more elegant way to address this scenario.

0 Likes 0 ·
Show more comments
Gosen Gao avatar image
Gosen Gao answered

Here is the code that I used for tests, can you please give a try?

 FunctionExecutionContext&lt;dynamic&gt; context = JsonConvert.DeserializeObject&lt;FunctionExecutionContext&lt;dynamic&gt;&gt;(await req.ReadAsStringAsync());
    
 var authContext = new PlayFabAuthenticationContext();
 authContext.EntityToken = context.TitleAuthenticationContext.EntityToken;
    
 var apiSettings = new PlayFab.PlayFabApiSettings()
 {
     TitleId = Environment.GetEnvironmentVariable("PLAYFAB_TITLE_ID", EnvironmentVariableTarget.Process),
     DeveloperSecretKey = Environment.GetEnvironmentVariable("PLAYFAB_DEV_SECRET_KEY", EnvironmentVariableTarget.Process)
 };
 var economyApi = new PlayFabEconomyInstanceAPI(apiSettings, authContext);
    
 var ret = await economyApi.GetItemsAsync(new GetItemsRequest{
     Ids = new List&lt;string&gt;{
         "itemId",
         "itemId"
     }
 });
    
 ExecuteInventoryOperationsRequest ExecuteInventoryOperationsRequest = new();
 ExecuteInventoryOperationsRequest.Entity = new PlayFab.EconomyModels.EntityKey{
     Id = context.CallerEntityProfile.Entity.Id,
     Type = context.CallerEntityProfile.Entity.Type
 };
    
 ExecuteInventoryOperationsRequest.Operations = new();
    
    
 foreach (CatalogItem Item in ret.Result.Items)
     {
         AddInventoryItemsOperation Operation = new();
         Operation.Item = new InventoryItemReference { Id = Item.Id };
         Operation.Amount = 1;
         Operation.NewStackValues = new();
         ExecuteInventoryOperationsRequest.Operations.Add(new InventoryOperation{Add= Operation});
     }
    
 var result = await economyApi.ExecuteInventoryOperationsAsync(ExecuteInventoryOperationsRequest);
    
 return new OkObjectResult(result);
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.