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

Strawberry Shake客户端CacheAndNetwork策略离线未读缓存问题求助

问题分析与解决方案

代码遗漏的关键配置

你的代码确实缺少两项核心配置,导致离线时无法回退到本地缓存:

  • 未配置本地缓存存储:Strawberry Shake需要显式指定缓存实现(内存或持久化),否则缓存策略无法生效。
  • 未处理网络请求异常:默认HttpClient会直接抛出HttpRequestException,不会自动回退到缓存,需要配置客户端允许网络失败时返回缓存数据。

你的预期是正确的:CacheAndNetwork策略的设计逻辑就是优先返回缓存数据,同时后台请求网络更新缓存;当网络不可用时,应直接返回现有缓存。

修正后的示例代码

第一步:安装必要的NuGet包

确保已安装以下包(以内存缓存为例):

Install-Package StrawberryShake.Transport.Http
Install-Package StrawberryShake.Caching.InMemory

第二步:完整客户端代码

namespace strawberry_shake_graphql_client
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            var serviceCollection = new ServiceCollection();
            
            serviceCollection
                // 注册内存缓存存储(如需持久化可替换为Sqlite缓存)
                .AddInMemoryCache()
                // 配置Strawberry Shake客户端及缓存策略
                .AddStrawberryShakeGraphQLClient(StrawberryShake.ExecutionStrategy.CacheAndNetwork)
                .ConfigureHttpClient(client => 
                {
                    client.BaseAddress = new Uri("https://localhost:7148/graphql/");
                    // 允许网络错误转为GraphQL错误,而非直接抛出异常
                    client.DefaultRequestPolicy = new HttpPolicy
                    {
                        AllowNetworkErrors = true
                    };
                })
                // 配置缓存过期规则
                .ConfigureCache(options =>
                {
                    options.DefaultExpiration = TimeSpan.FromHours(1);
                });

            var serviceProvider = serviceCollection.BuildServiceProvider();
            var client = serviceProvider.GetRequiredService<IStrawberryShakeGraphQLClient>();

            while (Console.ReadLine() != string.Empty)
            {
                await GetBooks(client);
            }
        }

        static async Task GetBooks(IStrawberryShakeGraphQLClient client)
        {
            try
            {
                var result = await client.Getbooks.ExecuteAsync();
                
                if (result.IsErrorResult())
                {
                    // 检查是否为网络错误,尝试读取缓存
                    var hasNetworkError = result.Errors.Any(e => 
                        e.Message.Contains("network") || e.Message.Contains("HttpRequestException"));
                    
                    if (hasNetworkError)
                    {
                        var cachedResult = await client.Getbooks.ReadFromCacheAsync();
                        if (cachedResult?.Data != null)
                        {
                            Console.WriteLine("使用本地缓存数据:");
                            foreach (var book in cachedResult.Data.BooksList)
                            {
                                Console.WriteLine(book.Title);
                            }
                            return;
                        }
                        Console.WriteLine("网络错误且无本地缓存数据");
                        return;
                    }
                    
                    Console.WriteLine("查询执行错误:" + string.Join(", ", result.Errors.Select(e => e.Message)));
                    return;
                }

                Console.WriteLine("使用最新网络数据:");
                foreach (var book in result.Data.BooksList)
                {
                    Console.WriteLine(book.Title);
                }
            }
            catch (HttpRequestException ex)
            {
                // 兜底捕获网络异常,尝试读取缓存
                var cachedResult = await client.Getbooks.ReadFromCacheAsync();
                if (cachedResult?.Data != null)
                {
                    Console.WriteLine("网络不可用,使用本地缓存数据:");
                    foreach (var book in cachedResult.Data.BooksList)
                    {
                        Console.WriteLine(book.Title);
                    }
                }
                else
                {
                    Console.WriteLine($"网络不可用且无缓存数据:{ex.Message}");
                }
            }
        }
    }
}

关键配置说明

  • AddInMemoryCache():注册内存缓存,若需进程重启后保留缓存,可替换为AddSqliteCache(options => options.ConnectionString = "Data Source=cache.db")。
  • HttpPolicy.AllowNetworkErrors = true:将网络错误转换为GraphQL错误,让Strawberry Shake可以处理并触发缓存回退逻辑。
  • ReadFromCacheAsync():网络请求失败时,主动从缓存读取历史查询结果。
  • CacheAndNetwork策略:在线时优先返回缓存,后台异步更新缓存;离线时直接返回已缓存的数据(若存在)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 08:10:25