b396638438
Motivation: 持仓与已处理信号的状态此前仅存于进程内存,服务重启或多实例部署后会丢失,导致加仓均价、仓位大小等计算失真,重复信号也无法跨实例幂等。通过将状态持久化到 Redis,保证持仓跟踪跨重启、跨实例连续一致,提升通知内容的准确性与可靠性。 Changes: * 新增持仓存储抽象,支持内存与 Redis 两种实现,持仓状态与已处理信号快照按 TTL 持久化 * 持仓变更通过 Redis 事务管道原子提交,保证状态更新与幂等记录一致写入 * 存储写入失败时消息进入重试而非直接确认,避免状态丢失导致通知失真 * 缓存层新增原始值读取与批量事务写入能力,并在订阅器初始化时注入 Redis 依赖 * 补充跨实例持久化、幂等去重与存储失败场景的测试覆盖
47 lines
808 B
Go
47 lines
808 B
Go
package cache
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/redis/go-redis/v9"
|
|
)
|
|
|
|
type KVWrite struct {
|
|
Key string
|
|
Val []byte
|
|
TTL time.Duration
|
|
Delete bool
|
|
}
|
|
|
|
func (c *Cache) GetRaw(ctx context.Context, key string) ([]byte, error) {
|
|
if c == nil || c.rdb == nil {
|
|
return nil, fmt.Errorf("redis unavailable")
|
|
}
|
|
b, err := c.rdb.Get(ctx, key).Bytes()
|
|
if err == redis.Nil {
|
|
return nil, nil
|
|
}
|
|
return b, err
|
|
}
|
|
|
|
func (c *Cache) TxWrite(ctx context.Context, writes []KVWrite) error {
|
|
if c == nil || c.rdb == nil {
|
|
return fmt.Errorf("redis unavailable")
|
|
}
|
|
if len(writes) == 0 {
|
|
return nil
|
|
}
|
|
pipe := c.rdb.TxPipeline()
|
|
for _, w := range writes {
|
|
if w.Delete {
|
|
pipe.Del(ctx, w.Key)
|
|
continue
|
|
}
|
|
pipe.Set(ctx, w.Key, w.Val, w.TTL)
|
|
}
|
|
_, err := pipe.Exec(ctx)
|
|
return err
|
|
}
|