You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google Retail API SetInventory操作PollUntilCompleted抛出无效操作异常

Google Retail API PollUntilCompleted() 报错 "Operation has not completed." 解决指南

问题概述

在使用Google Retail API设置产品库存时,调用PollUntilCompleted()同步方法抛出System.InvalidOperationException,错误提示为"Operation has not completed."。同时调用AddLocalInventoriesAsync方法时也出现相同异常,但产品创建操作可正常完成。

异常详情

  • 异常类型:System.InvalidOperationException
  • 错误消息:"Operation has not completed."
  • 调试观测:'operation.Result' threw an exception of type 'System.InvalidOperationException'

涉事核心代码

public static void SetProductInventory(string productName)
{
    var setInventoryRequest = GetSetInventoryRequest(productName);
    var client = ProductServiceClient.Create();
    var operation = client.SetInventory(setInventoryRequest);

    Console.WriteLine("Set inventory. Please, wait.");
    Console.WriteLine();

    operation.PollUntilCompleted();   // 触发异常的代码行
}

// 调用流程
public static void PerformSetInventoryOperation()
{
    string projectId = Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID");
    Product createdProduct = CreateProductSample.CreateRetailProductWithFulfillment(projectId);
    SetInventorySample.SetProductInventory(createdProduct.Name); // 调用库存设置方法
    Product product = GetProductSample.GetRetailProduct(createdProduct.Name);
    
    Console.WriteLine($"Product Price Info: {product.PriceInfo}");
    DeleteProductSample.DeleteRetailProduct(createdProduct.Name);
}

解决方案

1. 替换为异步轮询方法

同步轮询易因主线程阻塞或超时设置不合理导致异常,改用异步版本:

// 修改库存设置方法为异步
public static async Task SetProductInventoryAsync(string productName)
{
    var setInventoryRequest = GetSetInventoryRequest(productName);
    var client = ProductServiceClient.Create();
    var operation = client.SetInventory(setInventoryRequest);

    Console.WriteLine("Set inventory. Please, wait.");
    Console.WriteLine();

    await operation.PollUntilCompletedAsync();
}

// 调用处同步改为异步
public static async Task PerformSetInventoryOperationAsync()
{
    string projectId = Environment.GetEnvironmentVariable("GOOGLE_PROJECT_ID");
    Product createdProduct = CreateProductSample.CreateRetailProductWithFulfillment(projectId);
    await SetInventorySample.SetProductInventoryAsync(createdProduct.Name);
    
    Product product = GetProductSample.GetRetailProduct(createdProduct.Name);
    Console.WriteLine($"Product Price Info: {product.PriceInfo}");
    DeleteProductSample.DeleteRetailProduct(createdProduct.Name);
}

2. 自定义轮询超时与间隔

默认轮询配置可能超时过短,手动指定合理的超时时间和轮询间隔:

// 设置30秒超时,每2秒轮询一次
operation.PollUntilCompleted(TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(2));

3. 增加产品创建后的延迟

产品创建后存在短暂的后端同步延迟,添加延迟确保产品状态稳定后再执行库存操作:

Product createdProduct = CreateProductSample.CreateRetailProductWithFulfillment(projectId);
// 等待2秒确保产品同步完成
System.Threading.Thread.Sleep(2000); // 异步场景可使用await Task.Delay(2000)
SetInventorySample.SetProductInventory(createdProduct.Name);

4. 检查操作状态再执行轮询

在轮询前先判断操作状态,避免对已失败的操作执行轮询:

if (!operation.IsCompleted)
{
    try
    {
        operation.PollUntilCompleted();
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine($"轮询失败: {ex.Message}");
        // 可根据需求尝试重新发起操作
    }
}
else if (operation.IsFaulted)
{
    Console.WriteLine($"操作已失败: {operation.Exception?.InnerException?.Message}");
}

5. 验证API权限与配额

  • 确认当前服务账号拥有Retail Editor或对应库存操作的权限
  • 在Google Cloud控制台查看Retail API的配额使用情况,确认未触发调用限制
  • 查看API日志,排查是否存在后端服务返回的隐藏错误

内容的提问来源于stack exchange,提问作者Ivan Meyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:02:08