feat(交易信号): 持仓状态持久化至 Redis 以保障重启与多实例下均价计算准确
Motivation: 持仓与已处理信号的状态此前仅存于进程内存,服务重启或多实例部署后会丢失,导致加仓均价、仓位大小等计算失真,重复信号也无法跨实例幂等。通过将状态持久化到 Redis,保证持仓跟踪跨重启、跨实例连续一致,提升通知内容的准确性与可靠性。 Changes: * 新增持仓存储抽象,支持内存与 Redis 两种实现,持仓状态与已处理信号快照按 TTL 持久化 * 持仓变更通过 Redis 事务管道原子提交,保证状态更新与幂等记录一致写入 * 存储写入失败时消息进入重试而非直接确认,避免状态丢失导致通知失真 * 缓存层新增原始值读取与批量事务写入能力,并在订阅器初始化时注入 Redis 依赖 * 补充跨实例持久化、幂等去重与存储失败场景的测试覆盖
This commit is contained in:
@@ -6,10 +6,12 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"aiaa-notification-service/internal/cache"
|
||||
"aiaa-notification-service/internal/config"
|
||||
)
|
||||
|
||||
var ErrInvalidSignal = errors.New("invalid signal")
|
||||
var ErrPositionStore = errors.New("position store")
|
||||
|
||||
type Converter struct {
|
||||
overrides map[string]config.StrategyOverride
|
||||
@@ -17,9 +19,13 @@ type Converter struct {
|
||||
}
|
||||
|
||||
func NewConverter(overrides map[string]config.StrategyOverride) *Converter {
|
||||
return NewConverterWithCache(overrides, nil)
|
||||
}
|
||||
|
||||
func NewConverterWithCache(overrides map[string]config.StrategyOverride, c *cache.Cache) *Converter {
|
||||
return &Converter{
|
||||
overrides: overrides,
|
||||
positions: NewTracker(),
|
||||
positions: NewTrackerWithStore(newRedisStore(c)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +45,10 @@ func (c *Converter) Convert(body []byte) (string, map[string]interface{}, error)
|
||||
return "trade.message", data, nil
|
||||
}
|
||||
out := Apply(&sig, c.overrideFor(sig.StrategyCode))
|
||||
snap := c.positions.Apply(out)
|
||||
snap, err := c.positions.Apply(out)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("%w: %v", ErrPositionStore, err)
|
||||
}
|
||||
var opts FormatOptions
|
||||
if snap.HasAvg {
|
||||
avg := snap.AvgPrice
|
||||
|
||||
Reference in New Issue
Block a user