Skip to content

Commit 097343d

Browse files
[plugins] feat: redis caching plugin added
1 parent ed1376e commit 097343d

File tree

5 files changed

+1084
-0
lines changed

5 files changed

+1084
-0
lines changed

plugins/redis/README.md

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
# Redis Cache Plugin for Bifrost
2+
3+
This plugin provides Redis-based caching functionality for Bifrost requests. It caches responses based on request body hashes and returns cached responses for identical requests, significantly improving performance and reducing API costs.
4+
5+
## Features
6+
7+
- **High-Performance Hashing**: Uses xxhash for ultra-fast request body hashing
8+
- **Asynchronous Caching**: Non-blocking cache writes for optimal response times
9+
- **Response Caching**: Stores complete responses in Redis with configurable TTL
10+
- **Cache Hit Detection**: Returns cached responses for identical requests
11+
- **Simple Setup**: Only requires Redis address - sensible defaults for everything else
12+
- **Self-Contained**: Creates and manages its own Redis client
13+
14+
## Installation
15+
16+
```bash
17+
go get github.com/maximhq/bifrost/core
18+
go get github.com/maximhq/bifrost/plugins/redis
19+
```
20+
21+
## Quick Start
22+
23+
### Basic Setup
24+
25+
```go
26+
import (
27+
"github.com/maximhq/bifrost/plugins/redis"
28+
bifrost "github.com/maximhq/bifrost/core"
29+
)
30+
31+
// Simple configuration - only Redis address is required!
32+
config := redis.RedisPluginConfig{
33+
Addr: "localhost:6379", // Your Redis server address
34+
}
35+
36+
// Create the plugin
37+
plugin, err := redis.NewRedisPlugin(config, logger)
38+
if err != nil {
39+
log.Fatal("Failed to create Redis plugin:", err)
40+
}
41+
42+
// Use with Bifrost
43+
bifrostConfig := schemas.BifrostConfig{
44+
Account: yourAccount,
45+
Plugins: []schemas.Plugin{plugin},
46+
// ... other config
47+
}
48+
```
49+
50+
That's it! The plugin uses Redis client defaults for connection handling and these defaults for caching:
51+
52+
- **TTL**: 5 minutes
53+
- **CacheOnlySuccessful**: true (only cache successful responses)
54+
- **CacheByModel**: true (include model in cache key)
55+
- **CacheByProvider**: true (include provider in cache key)
56+
57+
### With Password Authentication
58+
59+
```go
60+
config := redis.RedisPluginConfig{
61+
Addr: "localhost:6379",
62+
Password: "your-redis-password",
63+
}
64+
```
65+
66+
### With Custom TTL and Prefix
67+
68+
```go
69+
config := redis.RedisPluginConfig{
70+
Addr: "localhost:6379",
71+
TTL: time.Hour, // Cache for 1 hour
72+
Prefix: "myapp:cache:", // Custom prefix
73+
}
74+
```
75+
76+
### With Different Database
77+
78+
```go
79+
config := redis.RedisPluginConfig{
80+
Addr: "localhost:6379",
81+
DB: 1, // Use Redis database 1
82+
}
83+
```
84+
85+
### Cache All Responses (Including Errors)
86+
87+
```go
88+
config := redis.RedisPluginConfig{
89+
Addr: "localhost:6379",
90+
CacheOnlySuccessful: bifrost.Ptr(false), // Cache both successful and error responses
91+
}
92+
```
93+
94+
### Custom Cache Key Configuration
95+
96+
```go
97+
config := redis.RedisPluginConfig{
98+
Addr: "localhost:6379",
99+
CacheByModel: bifrost.Ptr(false), // Don't include model in cache key
100+
CacheByProvider: bifrost.Ptr(true), // Include provider in cache key
101+
}
102+
```
103+
104+
### Custom Redis Client Configuration
105+
106+
```go
107+
config := redis.RedisPluginConfig{
108+
Addr: "localhost:6379",
109+
PoolSize: 20, // Custom connection pool size
110+
DialTimeout: 5 * time.Second, // Custom connection timeout
111+
ReadTimeout: 3 * time.Second, // Custom read timeout
112+
ConnMaxLifetime: time.Hour, // Custom connection lifetime
113+
}
114+
```
115+
116+
## Configuration Options
117+
118+
| Option | Type | Required | Default | Description |
119+
| --------------------- | --------------- | -------- | ----------------- | ---------------------------------- |
120+
| `Addr` | `string` || - | Redis server address (host:port) |
121+
| `Username` | `string` || `""` | Username for Redis AUTH (Redis 6+) |
122+
| `Password` | `string` || `""` | Password for Redis AUTH |
123+
| `DB` | `int` || `0` | Redis database number |
124+
| `TTL` | `time.Duration` || `5 * time.Minute` | Time-to-live for cached responses |
125+
| `Prefix` | `string` || `""` | Prefix for cache keys |
126+
| `CacheOnlySuccessful` | `*bool` || `true` | Only cache successful responses |
127+
| `CacheByModel` | `*bool` || `true` | Include model in cache key |
128+
| `CacheByProvider` | `*bool` || `true` | Include provider in cache key |
129+
130+
**Redis Connection Options** (all optional, Redis client uses its own defaults for zero values):
131+
132+
- `PoolSize`, `MinIdleConns`, `MaxIdleConns` - Connection pool settings
133+
- `ConnMaxLifetime`, `ConnMaxIdleTime` - Connection lifetime settings
134+
- `DialTimeout`, `ReadTimeout`, `WriteTimeout` - Timeout settings
135+
136+
All Redis configuration values are passed directly to the Redis client, which handles its own zero-value defaults. You only need to specify values you want to override from Redis client defaults.
137+
138+
## How It Works
139+
140+
The plugin generates an xxhash of the normalized request including:
141+
142+
- Provider (if CacheByProvider is true)
143+
- Model (if CacheByModel is true)
144+
- Input (chat completion or text completion)
145+
- Parameters (includes tool calls)
146+
147+
Identical requests will always produce the same hash, enabling effective caching.
148+
149+
### Caching Flow
150+
151+
1. **PreHook**: Checks Redis for cached response, returns immediately if found
152+
2. **PostHook**: Stores the response in Redis asynchronously (non-blocking)
153+
3. **Cleanup**: Clears all cached entries and closes connection on shutdown
154+
155+
**Asynchronous Caching**: Cache writes happen in background goroutines with a 30-second timeout, ensuring responses are never delayed by Redis operations. This provides optimal performance while maintaining cache functionality.
156+
157+
### Cache Keys
158+
159+
Cache keys follow the pattern: `{prefix}{xxhash}`
160+
161+
Example: `bifrost:cache:a1b2c3d4e5f6...`
162+
163+
## Testing
164+
165+
Run the tests with a Redis instance running:
166+
167+
```bash
168+
# Start Redis (using Docker)
169+
docker run -d -p 6379:6379 redis:latest
170+
171+
# Run tests
172+
go test ./...
173+
```
174+
175+
Tests will be skipped if Redis is not available.
176+
177+
## Performance Benefits
178+
179+
- **Reduced API Calls**: Identical requests are served from cache
180+
- **Ultra-Low Latency**: Cache hits return immediately, cache writes are non-blocking
181+
- **Cost Savings**: Fewer API calls to expensive LLM providers
182+
- **Improved Reliability**: Cached responses available even if provider is down
183+
- **High Throughput**: Asynchronous caching doesn't impact response times
184+
185+
## Error Handling
186+
187+
The plugin is designed to fail gracefully:
188+
189+
- If Redis is unavailable during startup, plugin creation fails with clear error
190+
- If Redis becomes unavailable during operation, requests continue without caching
191+
- If cache retrieval fails, requests proceed normally
192+
- If cache storage fails asynchronously, responses are unaffected (already returned)
193+
- Malformed cached data is ignored and requests proceed normally
194+
- Cache operations have timeouts to prevent resource leaks
195+
196+
## Best Practices
197+
198+
1. **Start Simple**: Use only `Addr` and let defaults handle the rest
199+
2. **Set appropriate TTL**: Balance between cache efficiency and data freshness
200+
3. **Use meaningful prefixes**: Helps organize cache keys in shared Redis instances
201+
4. **Monitor Redis memory**: Track cache usage in production environments
202+
5. **Use `bifrost.Ptr()`**: For boolean pointer configuration options
203+
204+
## Security Considerations
205+
206+
- **Sensitive Data**: Be cautious about caching responses containing sensitive information
207+
- **Redis Security**: Use authentication and network security for Redis
208+
- **Data Isolation**: Use different Redis databases or prefixes for different environments

plugins/redis/go.mod

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
module github.com/maximhq/bifrost/plugins/redis
2+
3+
go 1.24.1
4+
5+
require (
6+
github.com/cespare/xxhash/v2 v2.3.0
7+
github.com/maximhq/bifrost/core v1.1.15
8+
github.com/redis/go-redis/v9 v9.10.0
9+
)
10+
11+
replace github.com/maximhq/bifrost/core => ../../core
12+
13+
require (
14+
cloud.google.com/go/compute/metadata v0.3.0 // indirect
15+
github.com/andybalholm/brotli v1.1.1 // indirect
16+
github.com/aws/aws-sdk-go-v2 v1.36.3 // indirect
17+
github.com/aws/aws-sdk-go-v2/config v1.29.14 // indirect
18+
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 // indirect
19+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 // indirect
20+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
21+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
22+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
23+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
24+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
25+
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect
26+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
27+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 // indirect
28+
github.com/aws/smithy-go v1.22.3 // indirect
29+
github.com/bytedance/sonic v1.14.0 // indirect
30+
github.com/bytedance/sonic/loader v0.3.0 // indirect
31+
github.com/cloudwego/base64x v0.1.5 // indirect
32+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
33+
github.com/google/uuid v1.6.0 // indirect
34+
github.com/klauspost/compress v1.18.0 // indirect
35+
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
36+
github.com/mark3labs/mcp-go v0.32.0 // indirect
37+
github.com/spf13/cast v1.7.1 // indirect
38+
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
39+
github.com/valyala/bytebufferpool v1.0.0 // indirect
40+
github.com/valyala/fasthttp v1.60.0 // indirect
41+
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
42+
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
43+
golang.org/x/net v0.39.0 // indirect
44+
golang.org/x/oauth2 v0.30.0 // indirect
45+
golang.org/x/text v0.24.0 // indirect
46+
)

plugins/redis/go.sum

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
2+
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
3+
github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
4+
github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
5+
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
6+
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
7+
github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM=
8+
github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g=
9+
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM=
10+
github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ=
11+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw=
12+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M=
13+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
14+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
15+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
16+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
17+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
18+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
19+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
20+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
21+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM=
22+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
23+
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8=
24+
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI=
25+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako=
26+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs=
27+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY=
28+
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
29+
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
30+
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
31+
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
32+
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
33+
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
34+
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
35+
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
36+
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
37+
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
38+
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
39+
github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
40+
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
41+
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
42+
github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
43+
github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
44+
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
45+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
46+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
47+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
48+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
49+
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
50+
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
51+
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
52+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
53+
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
54+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
55+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
56+
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
57+
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
58+
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
59+
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
60+
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
61+
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
62+
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
63+
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
64+
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
65+
github.com/mark3labs/mcp-go v0.32.0 h1:fgwmbfL2gbd67obg57OfV2Dnrhs1HtSdlY/i5fn7MU8=
66+
github.com/mark3labs/mcp-go v0.32.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
67+
github.com/maximhq/bifrost/core v1.1.15 h1:LfpBweunwVFTXD2RFLrFfrl6XGhOPCPFJwgoFKuuvLs=
68+
github.com/maximhq/bifrost/core v1.1.15/go.mod h1:Wa/BtJoHZ0+RXYomGeAL+wyBu6iD1h6vMiUHF5RTlkA=
69+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
70+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
71+
github.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs=
72+
github.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
73+
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
74+
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
75+
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
76+
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
77+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
78+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
79+
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
80+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
81+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
82+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
83+
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
84+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
85+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
86+
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
87+
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
88+
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
89+
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
90+
github.com/valyala/fasthttp v1.60.0 h1:kBRYS0lOhVJ6V+bYN8PqAHELKHtXqwq9zNMLKx1MBsw=
91+
github.com/valyala/fasthttp v1.60.0/go.mod h1:iY4kDgV3Gc6EqhRZ8icqcmlG6bqhcDXfuHgTO4FXCvc=
92+
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
93+
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
94+
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
95+
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
96+
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
97+
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
98+
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
99+
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
100+
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
101+
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
102+
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
103+
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
104+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
105+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
106+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
107+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
108+
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=

0 commit comments

Comments
 (0)