GraphQL Which item failed when bulk updating inventory?

Solved
Conner
Explorer
49 1 9

Is there any way to tell specifically which InventoryItem failed when bulk updating inventory quantities via GraphQL?

I am working with stores that have a high amount of Products/Variants (think 25,000+ Products & 200,000+ Variants) and multiple Locations. Using the REST API to update inventory has proven to be pretty inefficient. However, bulk updating inventory quantities via the method below doesn't seem to be the greatest solution either, as I have run into scenarios where a Variant has been deleted just before an Inventory Item update was pushed out or there was an Internal Server Error.

Even if I include userErrors, I don't receive a message about which InventoryItem caused the failure-- just that the update failed. In the example below, my experience has been that there is no way to determine if the first InventoryItemID failed vs. the last. Is this true?

 

mutation {  inventoryBulkAdjustQuantityAtLocation(locationId: "gid://shopify/Location/{LocationID}",    inventoryItemAdjustments: [
    {inventoryItemId: "gid://shopify/InventoryItem/{InventoryItemID}", availableDelta: 1},
    {inventoryItemId: "gid://shopify/InventoryItem/{InventoryItemID}", availableDelta: 1},
    {inventoryItemId: "gid://shopify/InventoryItem/{InventoryItemID}", availableDelta: 1},
    {inventoryItemId: "gid://shopify/InventoryItem/{InventoryItemID}", availableDelta: 1}
]) {
    inventoryLevels {      
available } } }
Busfox
Shopify Staff
Shopify Staff
619 48 95

This is an accepted solution.

Hi @Conner,

 

Which error(s) are you referring to? I just tested on my end, and received the index in the inventoryItemAdjustments array that the error occurred. I purposefully included an InventoryItem id that does not exist. Here's my call and the response:

 

Request

mutation {  inventoryBulkAdjustQuantityAtLocation(locationId: "gid://shopify/Location/13994",    inventoryItemAdjustments: [
    {inventoryItemId: "gid://shopify/InventoryItem/5622530", availableDelta: 1},
    {inventoryItemId: "gid://shopify/InventoryItem/5621954", availableDelta: 1},
    {inventoryItemId: "gid://shopify/InventoryItem/379086082", availableDelta: 1},
    {inventoryItemId: "gid://shopify/InventoryItem/1", availableDelta: 1}
]) {
    inventoryLevels {      
        available
    }
  	userErrors{
      field
      message
    }
}}

 

Response

{
  "data": {
    "inventoryBulkAdjustQuantityAtLocation": {
      "inventoryLevels": null,
      "userErrors": [
        {
          "field": [
            "inventoryItemAdjustments",
            "3",
            "inventoryItemId"
          ],
          "message": "Quantity couldn't be adjusted because this product isn't stocked at Cali."
        }
      ]
    }
  },
  "extensions": {
    "cost": {
      "requestedQueryCost": 10,
      "actualQueryCost": 10,
      "throttleStatus": {
        "maximumAvailable": 1000.0,
        "currentlyAvailable": 990,
        "restoreRate": 50.0
      }
    }
  }
}

In this example, the index where the error was is indicated with the "3" under userError field object.

0 Likes
Conner
Explorer
49 1 9

Hi @Busfox,

 

Ah, I see-- So the index of the failed item is returned. I 100% did not catch that. Thanks for clearing that up for me, as this method of updating inventory will be extremely nice now that I've gotten over that hump!!

Thanks so much!

0 Likes
CartSpan
Tourist
8 0 0

Hi Conner,

 

As a benchmark, would you mind sharing how quickly your updates complete and how many items were processed?

 

Thanks,

Scott

0 Likes
Conner
Explorer
49 1 9

@CartSpan , I'll share as soon as I get it up and running. Probably will be a day or two, but I'll definitely report back on my experience with switching over.

Conner
Explorer
49 1 9

@CartSpan,

 

Here's my experience so far:

 

REST - /inventory_levels/set.json

174,000 Inventory Quantities Updated

25 Hours to complete

vs.

GraphQL - inventoryBulkAdjustQuantityAtLocation

174,000 Inventory Quantities Updated

25 Minutes to complete

Notes:

The GraphQL completion time could definitely be sped up even more. I just set up a quick & dirty API call, and I never even got close to having a need for throttling. I imagine you could significantly reduce the time by making use of parallelism & finding a sweet spot in how many updates you're sending up (I sent 100 updates per API call).

Also, the GraphQL completion time does not include time spent making the inventory connections required for multi-location stores.

___END___
Tourist
11 0 3

Thank you for the information. More questions from me:

1. In the 25 minute period you are not rate-limited?

2. Using REST 25 hours is a long time. Is this time largely due to REST rate limits? If you handle rate limits do you use external library?

3. How many times a day do you do this?

 

Also, the GraphQL completion time does not include time spent making the inventory connections required for multi-location stores.

This is guaranteeing that the 174,000 are updates and not no ops? What is the time that this takes, given your comparisons seems that it is not factor but curious? 

 

 

0 Likes
Conner
Explorer
49 1 9

1. In the 25 minute period you are not rate-limited?

Rate-limiting was still a factor. However, using GraphQL you can benefit from using small queries (as seen in extensions.cost.requestedQueryCost and extensions.cost.actualQueryCost). You can then check extensions.cost.throttleStatus to see where you stand.

2. Using REST 25 hours is a long time. Is this time largely due to REST rate limits? If you handle rate limits do you use external library?

Correct. Standard Shopify allows 2 API requests per second. No external library used.

3. How many times a day do you do this?

This was just a one-time audit to set inventory up initially, which ties into your final questions. If this is for new inventory and you have multiple locations, you need to connect the inventory to each location (it is only connected to the default location initially). I believe that using the REST API call to set inventory quantity connects the inventory to a location in one step. With GraphQL, you need an additional step to connect it. It's been a while so I can't remember exactly how long it took, but it likely took longer than the inventory quantity updates due to connecting all inventory to all locations. I don't recall it taking a long time still (perhaps an hour or two?).

0 Likes