diff --git a/chat2.md b/chat2.md new file mode 100644 index 0000000..ea87ed6 --- /dev/null +++ b/chat2.md @@ -0,0 +1,305 @@ +> 这里,我引入 github.com/phyer/core/service 为的是让 Candle struct里的 属性 core 得到正确的类型, 结果出现了 循环以来, 那么我该如何用刚才提到的依赖注入和接口隔离的方式来规避 +> + +🤔 Thought content: + + +首先,我得理解问题所在。循环依赖通常发生在两个或多个包相互引用的时候。比如,如果model包引用了service包,而service包又引用了model包,就会形成循环。用户的结构体Candle有一个core字段,类型是service.Core,这可能导致model包依赖service包,而如果service包也依赖model包,就会循环。 + +接下来,用户想通过依赖注入和接口隔离来解决。依赖注入的意思是,不直接持有具体类型的实例,而是通过接口来抽象,从而解耦。接口隔离则是定义小接口,只暴露必要的方法,减少依赖。 + +我需要先检查用户的代码。在提供的代码中,Candle结构体的core字段类型是*service.Core。但用户提到引入了"github.com/phyer/core/service",这可能是指service包中的Core结构体。如果model包(即当前文件所在的包)引用了service包,而service包又引用了model包,就会形成循环。 + +解决方案应该是将core字段的类型从具体的service.Core改为一个接口类型,该接口包含Candle所需的方法。这样,model包就不再直接依赖service包,而是依赖一个本地定义的接口。service包中的Core结构体可以实现这个接口,从而解除循环依赖。 + +具体步骤可能如下: + +1. 在model包中定义一个接口,比如CoreService,包含Candle结构体需要使用的方法。例如,如果Candle的core字段需要调用Cfg、RedisLocalCli等方法,就在接口中声明这些方法。 + +2. 将Candle结构体中的core字段类型改为这个接口类型,比如core CoreService。 + +3. 在service包中,确保Core结构体实现了model.CoreService接口的所有方法。这样,当service包导入model包时,不会有循环,因为model包现在只依赖接口,而接口在model包内部定义。 + +4. 调整代码中所有使用core字段的地方,确保通过接口方法访问,而不是直接访问结构体字段。 + +例如,用户代码中Candle结构体的core字段是*service.Core类型,改为CoreService接口类型后,循环依赖就被打破了。因为model包现在只依赖自己定义的接口,而service包实现该接口,不需要反过来引用model包中的具体类型。 + +需要检查用户提供的代码中core字段被使用的地方。例如,在SaveCandle方法中,core.Cfg.Config.Get这样的调用,说明Core结构体需要有Cfg字段。因此在CoreService接口中,可能需要一个GetCfg()方法,返回配置对象。 + +这样,model包中的代码通过接口方法访问core的功能,而不直接依赖service包的具体实现。service包中的Core结构体实现这个接口,从而解除了循环依赖。 + +最后,用户需要修改Candle结构体的core字段类型,定义接口,并调整所有使用core的地方,改为调用接口方法。这样就能避免循环依赖的问题。我们可以通过以下步骤用接口隔离和依赖注入解决循环依赖问题: + +1. 首先在model包中定义核心服务需要的接口 +2. 修改Candle结构体使用接口类型 +3. 保持service包实现这个接口 + +具体修改如下: + +Filepath: model/candle.go +Replace lines: 23-26 +```go +// 定义核心服务接口 +type CoreService interface { + GetCfg() *simple.Json + GetRedisLocalCli() *redis.Client + AddToGeneralCandleChnl(candle *Candle, channels []string) + PeriodToMinutes(period string) (int64, error) + // 其他需要的方法... +} + +type Candle struct { + Id string `json:"_id"` + core CoreService // 改为接口类型 + InstID string `json:"instID"` +``` + +需要确保在service包中让Core结构体实现这个接口: + +```go +// 在service包中 +func (c *Core) GetCfg() *simple.Json { + return c.Cfg +} + +func (c *Core) GetRedisLocalCli() *redis.Client { + return c.RedisLocalCli +} + +func (c *Core) AddToGeneralCandleChnl(candle *model.Candle, channels []string) { + // 原有实现... +} + +func (c *Core) PeriodToMinutes(period string) (int64, error) { + // 原有实现... +} +``` + +这种修改的好处: +1. 解除了model和service包的循环依赖 +2. model包只依赖自己定义的接口 +3. service包实现model定义的接口 +4. 更容易进行单元测试(可以mock核心服务) +5. 明确声明了依赖关系和方法契约 + +需要同步修改所有使用core字段的地方,例如: +Filepath: model/candle.go +Replace lines: 0-0 +```go +core.GetCfg().Get(...) +``` + +这样的接口隔离配合依赖注入(在创建Candle时传入实现了CoreService的对象),可以有效解决循环依赖问题。 + +--- + +- Datetime: 2025-02-21 13:48:10 + +- Model: alidsr1/deepseek-r1 + +- Selected files: + - model/candle.go + +- Selected code: + +```go + + simple "github.com/bitly/go-simplejson" + "github.com/go-redis/redis" + "github.com/phyer/core/service" + "github.com/phyer/texus/utils" + logrus "github.com/sirupsen/logrus" +) +``` + +> 这个model包自己定义的接口能放到util包下吗, util包不依赖任何其他包, + +🤔 Thought content: + + > 首先,用户提供的代码中,model包定义了几个接口,比如CoreService、Sample、SampleList,以及结构体如Candle、CandleList等。这些接口可能被其他包或model内部的结构体和方法所依赖。 + + +用户的问题是将这些接口移到util包下是否可行,同时确保util包不依赖其他包。这意味着,我需要检查这些接口是否引用了model包或其他包的类型。如果接口中的方法参数或返回值使用了model或其他包的类型,那么将这些接口移到util包会导致util包依赖这些类型所在的包,从而违反util包不依赖其他包的条件。 + +查看代码中的CoreService接口,它的方法如GetCfg()返回了*simple.Json,而simple来自"github.com/bitly/go-simplejson",这属于外部依赖。同样,GetRedisLocalCli()返回*redis.Client,来自"github.com/go-redis/redis"。还有AddToGeneralCandleChnl方法参数中有*Candle,这是model包内的类型。因此,CoreService接口依赖了外部包和model包本身,无法移到util包,因为util不能有这些依赖。 + +接下来是Sample接口,SetToKey方法参数是*CoreService,同样CoreService在model中定义,并且CoreService本身依赖了外部包。所以Sample接口也不能移到util。 + +SampleList接口中的方法返回[]*Sample,而Sample是当前包的接口,同样涉及model包的依赖。 + +因此,结论是这些接口不能移到util包,因为它们引用了model包内或外部的类型,导致util包会产生依赖。需要保持接口在model包中,或者重新设计接口以避免依赖,但这可能影响现有功能。 + +最后,向用户解释这些分析,说明原因,并建议保持接口在model包中,或者考虑其他重构方式。通过分析代码,model包中定义的接口存在以下依赖问题,无法直接移动到独立的util包: + +1. CoreService接口依赖了其他包的组件: +```go +type CoreService interface { + GetCfg() *simple.Json // 依赖github.com/bitly/go-simplejson + GetRedisLocalCli() *redis.Client // 依赖github.com/go-redis/redis + AddToGeneralCandleChnl(candle *Candle, channels []string) // 依赖本包Candle类型 + //... +} +``` + +2. Sample接口也依赖了本包类型: +```go +type Sample interface { + SetToKey(cr *CoreService) ([]interface{}, error) // 参数依赖本包CoreService +} +``` + +3. SampleList接口依赖本包类型: +```go +type SampleList interface { + GetSectionOf(start int, end int) ([]*Sample, error) // 返回本包Sample类型 +} +``` + +建议方案: +1. 保持接口定义在model包中(当前最佳方案) +2. 如果确实需要独立util包,需要解耦依赖: +```go +// 需要先定义基础接口(在util包) +type BasicService interface { + // 只包含最基础的方法,不依赖具体实现 +} + +// 原model包中扩展接口 +type CoreService interface { + util.BasicService // 组合基础接口 + // 保留原项目特定方法 +} +``` + +需要我继续提供解耦方案的具体实现代码吗?这需要对现有代码结构进行较大调整。 + +--- + +- Datetime: 2025-02-21 14:06:06 + +- Model: alidsr1/deepseek-r1 + +- Selected files: + - core/interfaces.go + - config/config.go + - config/const.go + - data/coaster.go + - data/pixel.go + - data/plate.go + - data/rsi.go + - data/segmentItem.go + - data/series.go + - data/shearForceGrp.go + - data/sorted.go + - data/tray.go + - model/candle.go + - model/maX.go + - model/ticker.go + - service/service_context.go + - util/util.go + - util/writeLog.go + +- Selected code: + +```go +// 领域服务接口 +type CandleManager interface { + GetCandles(instID string, period string) ([]*Candle, error) + SaveCandle(candle *Candle) error +} + +// 基础设施接口 +type RedisService interface { + GetClient(options *redis.Options) (*redis.Client, error) + Ping(client *redis.Client) error +} +``` + +> 那既然model模块中定义接口, 让 service模块里的 core的struct去实现这个接口, 那么 core/interfaces.go里的接口是做什么的 +> + +🤔 Thought content: + 让 service模块里的 core的struct去实现这个接口, 那么 core/interfaces.go里的接口是做什么的”。首先,我需要理解用户的问题背景和他们可能存在的困惑。 + +用户提到在model模块中定义了接口,并让service模块的core结构体实现这些接口,然后问core/interfaces.go中的接口的作用。我需要先看看提供的代码内容,特别是interfaces.go文件中的内容。 + +查看用户提供的core/interfaces.go文件,里面定义了多个接口,如CandleManager、RedisService、HTTPRequester、EventPublisher等。这些接口似乎是领域服务和基础设施接口的抽象。例如,CandleManager定义了获取和保存蜡烛图数据的方法,而RedisService涉及Redis客户端的获取和健康检查。 + +用户可能混淆了不同层次接口的用途。model模块中的接口可能是领域模型相关的,而core/interfaces.go中的接口可能是更上层的应用服务或基础设施接口。需要明确两者在架构中的不同角色。 + +接下来,我应该解释接口的分层设计。在六边形架构或清洁架构中,通常会有领域层、应用层和基础设施层。领域层接口定义核心业务逻辑,应用层接口定义用例,基础设施层实现具体技术细节。core/interfaces.go中的接口可能属于应用层或基础设施层,而model中的接口属于领域层。 + +需要指出core/interfaces.go中的接口作用,例如CandleManager作为领域服务接口,由service层的Core结构体实现,这样可以将业务逻辑与技术实现分离,提高可测试性和可维护性。RedisService则是基础设施接口,由具体的Redis客户端实现,遵循依赖倒置原则,允许更换底层技术而不影响上层逻辑。 + +总结时,应强调core/interfaces.go中的接口定义了服务层和基础设施的契约,而model中的接口可能更偏向领域模型,两者各司其职,共同支持系统的松耦合设计。通过分析代码结构和架构设计,可以明确不同接口的职责定位: + +1. `core/interfaces.go` 中的接口是领域层与基础设施层的契约 +```go +// 领域服务接口(面向业务能力) +type CandleManager interface { + GetCandles(instID string, period string) ([]*Candle, error) + SaveCandle(candle *Candle) error +} + +// 基础设施接口(面向技术实现) +type RedisService interface { + GetClient(options *redis.Options) (*redis.Client, error) + Ping(client *redis.Client) error +} +``` + +2. 具体实现关系示意图 +``` +┌───────────────┐ ┌───────────────┐ +│ Domain │ │ Infrastructure│ +│ (model包) │<─依赖注入─┤ (service包) │ +└──────┬────────┘ └──────┬────────┘ + │ │ + │ core/interfaces.go │ + │ ┌───────────────────┐ │ + └─>│ CandleManager │ │ + │ HTTPRequester │<──┘ + └───────────────────┘ +``` + +3. 关键区别说明: + +| 维度 | model包接口 | core/interfaces.go接口 | +|--------------------|-------------------------------------|-----------------------------------| +| **定位** | 领域模型内部契约 | 跨层协作的抽象边界 | +| **使用者** | 领域对象之间相互调用 | 业务服务与基础设施实现的对接点 | +| **变化频率** | 随业务需求变化 | 随系统架构演进变化 | +| **实现位置** | 领域层内部实现 | 基础设施层(如redis/http实现) | +| **示例** | 如Candle实体行为 | 如RedisService定义存储访问规范 | + +4. 设计意图解析: +- 控制反转(IoC):通过`core/interfaces.go`定义抽象,允许service层实现具体逻辑 +- 解耦分层:领域层不直接依赖具体redis/http实现,而是通过接口抽象 +- 可测试性:Mock这些接口可以方便进行单元测试 +- 可扩展性:更换存储方案只需实现相同接口,不影响业务逻辑 + +5. 典型工作流程示例: +```go +// 基础设施层实现接口 +type Core struct { + redisService RedisService // 依赖接口 +} + +func (c *Core) GetClient(opts *redis.Options) (*redis.Client, error) { + // 具体实现redis连接逻辑 +} + +// 领域层通过接口使用 +func ProcessCandle(cm CandleManager) { + cm.SaveCandle(&Candle{...}) // 实际调用Core的实现 +} +``` + +这种设计模式遵循了SOLID原则中的: +- 依赖倒置原则(DIP) +- 接口隔离原则(ISP) +- 开闭原则(OCP) + +通过这种分层,当需要替换存储方案(如从Redis改为MySQL)时,只需实现相同的RedisService接口,而无需修改业务逻辑代码。 + + diff --git a/core/interfaces.go b/core/interfaces.go index 1195262..09fcd96 100644 --- a/core/interfaces.go +++ b/core/interfaces.go @@ -2,13 +2,14 @@ package core import ( "github.com/go-redis/redis" + "github.com/phyer/core/model" "time" ) // 领域服务接口 type CandleManager interface { - GetCandles(instID string, period string) ([]*Candle, error) - SaveCandle(candle *Candle) error + GetCandles(instID string, period string) ([]*model.Candle, error) + SaveCandle(candle *model.Candle) error } // 基础设施接口 @@ -22,6 +23,12 @@ type HTTPRequester interface { Post(url string, body []byte) ([]byte, error) } +// 时间段相关服务接口 +type SegmentService interface { + GetCurrentSegment(period string) *model.CandleSegment + ParseSegmentTime(timeStr string) (time.Time, error) +} + // 领域事件接口 type EventPublisher interface { Publish(topic string, message interface{}) error diff --git a/model/candle.go b/model/candle.go index 61e27f3..ac8d9a3 100644 --- a/model/candle.go +++ b/model/candle.go @@ -86,184 +86,6 @@ func (mc *MatchCheck) SetMatched(value bool) { mc.Matched = value } -func (core *Core) GetCandlesWithRest(instId string, kidx int, dura time.Duration, maxCandles int) error { - ary := []string{} - - wsary := core.Cfg.CandleDimentions - for k, v := range wsary { - matched := false - // 这个算法的目的是:越靠后的candles维度,被命中的概率越低,第一个百分之百命中,后面开始越来越低, 每分钟都会发生这样的计算, - // 因为维度多了的话,照顾不过来 - rand.New(rand.NewSource(time.Now().UnixNano())) - rand.Seed(time.Now().UnixNano()) - n := (k*2 + 2) * 3 - if n < 1 { - n = 1 - } - b := rand.Intn(n) - if b < 8 { - matched = true - } - if matched { - ary = append(ary, v) - } - } - - mdura := dura/(time.Duration(len(ary)+1)) - 50*time.Millisecond - // fmt.Println("loop4 Ticker Start instId, dura: ", instId, dura, dura/10, mdura, len(ary), " idx: ", kidx) - // time.Duration(len(ary)+1) - ticker := time.NewTicker(mdura) - done := make(chan bool) - idx := 0 - go func(i int) { - for { - select { - case <-ticker.C: - if i >= (len(ary)) { - done <- true - break - } - rand.Seed(time.Now().UnixNano()) - b := rand.Intn(2) - maxCandles = maxCandles * (i + b) * 2 - - if maxCandles < 3 { - maxCandles = 3 - } - if maxCandles > 30 { - maxCandles = 30 - } - mx := strconv.Itoa(maxCandles) - // fmt.Println("loop4 getCandlesWithRest, instId, period,limit,dura, t: ", instId, ary[i], mx, mdura) - go func(ii int) { - restQ := RestQueue{ - InstId: instId, - Bar: ary[ii], - Limit: mx, - Duration: mdura, - WithWs: true, - } - js, _ := json.Marshal(restQ) - core.RedisLocalCli.LPush("restQueue", js) - }(i) - i++ - } - } - }(idx) - time.Sleep(dura - 10*time.Millisecond) - ticker.Stop() - // fmt.Println("loop4 Ticker stopped instId, dura: ", instId, dura, mdura) - done <- true - return nil -} - -// 当前的时间毫秒数 对于某个时间段,比如3分钟,10分钟,是否可以被整除, -func IsModOf(curInt int64, duration time.Duration) bool { - vol := int64(0) - if duration < 24*time.Hour { - // 小于1天 - vol = (curInt + 28800000) - } else if duration >= 24*time.Hour && duration < 48*time.Hour { - // 1天 - vol = curInt - 1633881600000 - } else if duration >= 48*time.Hour && duration < 72*time.Hour { - // 2天 - vol = curInt - 1633795200000 - } else if duration >= 72*time.Hour && duration < 120*time.Hour { - // 3天 - vol = curInt - 1633708800000 - } else if duration >= 120*time.Hour { - // 5天 - vol = curInt - 1633795200000 - } else { - // fmt.Println("noMatched:", curInt) - } - - mody := vol % duration.Milliseconds() - if mody == 0 { - return true - } - return false -} - -func (core *Core) SaveCandle(instId string, period string, rsp *CandleData, dura time.Duration, withWs bool) { - leng := len(rsp.Data) - // fmt.Println("saveCandle leng: ", leng, " instId: ", instId, " period: ", period) - logrus.Info("saveCandles leng: ", leng, " instId: ", instId, " period: ", period, " length of rsp.Data: ", len(rsp.Data)) - // softCandleSegmentList - segments := core.Cfg.Config.Get("softCandleSegmentList").MustArray() - logrus.Warn("lensof segments:", len(segments)) - curSegStartTime := "" - for k, v := range segments { - logrus.Warn("fetch segments:", k, v) - cs := CandleSegment{} - sv, _ := json.Marshal(v) - json.Unmarshal(sv, &cs) - if !cs.Enabled { - continue - } - logrus.Warn("fetch segments2: cs.Seg: ", cs.Seg, ", period:", period, ", cs.Seg == period: ", (cs.Seg == period)) - - if cs.Seg == period { - curSegStartTime = cs.StartTime - break - } - } - logrus.Warn("curSegStartTime:", curSegStartTime) - curTm, _ := time.ParseInLocation("2006-01-02 15:04.000", curSegStartTime, time.Local) - curTmi := curTm.UnixMilli() - - for k, v := range rsp.Data { - tmi := ToInt64(v[0]) - last := ToFloat64(v[4]) - // ty := reflect.TypeOf(v[4]).Name() - // v4It, err := strconv.ParseInt(v[4].(string), 10, 64) - // if err != nil { - // logrus.Info("saveCandles last is 0 is err: ", err, "v4It: ", v4It, "v[4]: ", v[4], "v[4] type: ", ty, "leng: ", leng, " instId: ", instId, " period: ", period, " length of rsp.Data: ", len(rsp.Data), " data:", rsp.Data) - // } - if last == 0 { - // logrus.Info("saveCandles last is 0: ", "v[4]: ", v[4], "v[4] type: ", ty, " v4It: ", v4It, "leng: ", leng, " instId: ", instId, " period: ", period, " length of rsp.Data: ", len(rsp.Data), " data:", rsp.Data) - continue - } - minutes, _ := core.PeriodToMinutes(period) - logrus.Warn("tmi: ", tmi, " curTim:", curTmi, " minutes: ", minutes) - if (tmi-curTmi)%(minutes*60000) != 0 { - logrus.Warn("saveCandles error: 当前记录中的时间戳:", curSegStartTime, ",并非周期节点:", period, " 忽略") - continue - } - - ts, _ := Int64ToTime(tmi) - candle := Candle{ - InstID: instId, - Period: period, - Data: v, - From: "rest", - Timestamp: ts, - LastUpdate: time.Now(), - } - - //存到elasticSearch - candle.PushToWriteLogChan(core) - //保存rest得到的candle - // 发布到allCandles|publish, 给外部订阅者用于setToKey - arys := []string{ALLCANDLES_PUBLISH} - if withWs { - arys = append(arys, ALLCANDLES_INNER_PUBLISH) - time.Sleep(time.Duration(k*40) * time.Millisecond) - } - // 如果candle都不需要存到redis,那么AddToGeneralCandleChnl也没有意义 - saveCandle := os.Getenv("TEXUS_SAVECANDLE") - logrus.Info("saveCandles datas: k,v: ", k, v) - if saveCandle == "true" { - go func(k int) { - time.Sleep(time.Duration(k*100) * time.Millisecond) - candle.SetToKey(core) - core.AddToGeneralCandleChnl(&candle, arys) - }(k) - } - } -} - func (candle *Candle) PushToWriteLogChan(cr *Core) error { did := candle.InstID + candle.Period + candle.Data[0].(string) candle.Id = HashString(did) diff --git a/service/segment_service.go b/service/segment_service.go new file mode 100644 index 0000000..2353aa6 --- /dev/null +++ b/service/segment_service.go @@ -0,0 +1,32 @@ +package service + +import ( + "encoding/json" + "time" + + "github.com/bitly/go-simplejson" + logrus "github.com/sirupsen/logrus" +) + +type DefaultSegmentService struct { + Config *simplejson.Json +} + +func (s *DefaultSegmentService) GetCurrentSegment(period string) *CandleSegment { + segments := s.Config.Get("softCandleSegmentList").MustArray() + + for _, v := range segments { + cs := CandleSegment{} + sv, _ := json.Marshal(v) + json.Unmarshal(sv, &cs) + + if cs.Enabled && cs.Seg == period { + return &cs + } + } + return nil +} + +func (s *DefaultSegmentService) ParseSegmentTime(timeStr string) (time.Time, error) { + return time.ParseInLocation("2006-01-02 15:04.000", timeStr, time.Local) +} diff --git a/service/service_context.go b/service/service_context.go index 143293d..9c47b39 100644 --- a/service/service_context.go +++ b/service/service_context.go @@ -18,6 +18,7 @@ import ( // simple "github.com/bitly/go-simplejson" // "v5sdk_go/ws/wImpl" "github.com/go-redis/redis" + "github.com/phyer/core/core" "github.com/phyer/core/model" "github.com/phyer/texus/private" "github.com/phyer/v5sdkgo/rest" @@ -25,11 +26,12 @@ import ( ) type Core struct { - Env string - Config ConfigProvider // 改为接口类型 - Redis RedisConnector // 改为接口类型 - HTTPClient HTTPClient // 改为接口类型 - Logger Logger // 改为接口类型 + Env string + Config ConfigProvider // 改为接口类型 + Redis RedisConnector // 改为接口类型 + HTTPClient HTTPClient // 改为接口类型 + Logger Logger // 改为接口类型 + SegmentServer core.SegmentService // 新增接口依赖 // 保留原有的运行时字段 FluentBitUrl string @@ -188,6 +190,77 @@ func NewCore( return core } +func (core *Core) GetCandlesWithRest(instId string, kidx int, dura time.Duration, maxCandles int) error { + ary := []string{} + + wsary := core.Cfg.CandleDimentions + for k, v := range wsary { + matched := false + // 这个算法的目的是:越靠后的candles维度,被命中的概率越低,第一个百分之百命中,后面开始越来越低, 每分钟都会发生这样的计算, + // 因为维度多了的话,照顾不过来 + rand.New(rand.NewSource(time.Now().UnixNano())) + rand.Seed(time.Now().UnixNano()) + n := (k*2 + 2) * 3 + if n < 1 { + n = 1 + } + b := rand.Intn(n) + if b < 8 { + matched = true + } + if matched { + ary = append(ary, v) + } + } + + mdura := dura/(time.Duration(len(ary)+1)) - 50*time.Millisecond + // fmt.Println("loop4 Ticker Start instId, dura: ", instId, dura, dura/10, mdura, len(ary), " idx: ", kidx) + // time.Duration(len(ary)+1) + ticker := time.NewTicker(mdura) + done := make(chan bool) + idx := 0 + go func(i int) { + for { + select { + case <-ticker.C: + if i >= (len(ary)) { + done <- true + break + } + rand.Seed(time.Now().UnixNano()) + b := rand.Intn(2) + maxCandles = maxCandles * (i + b) * 2 + + if maxCandles < 3 { + maxCandles = 3 + } + if maxCandles > 30 { + maxCandles = 30 + } + mx := strconv.Itoa(maxCandles) + // fmt.Println("loop4 getCandlesWithRest, instId, period,limit,dura, t: ", instId, ary[i], mx, mdura) + go func(ii int) { + restQ := RestQueue{ + InstId: instId, + Bar: ary[ii], + Limit: mx, + Duration: mdura, + WithWs: true, + } + js, _ := json.Marshal(restQ) + core.RedisLocalCli.LPush("restQueue", js) + }(i) + i++ + } + } + }(idx) + time.Sleep(dura - 10*time.Millisecond) + ticker.Stop() + // fmt.Println("loop4 Ticker stopped instId, dura: ", instId, dura, mdura) + done <- true + return nil +} + func (core *Core) GetRedisCliFromConf(conf RedisConfig) (*redis.Client, error) { client := redis.NewClient(&redis.Options{ Addr: conf.Url, diff --git a/util/util.go b/util/util.go index 41b02d9..e0773c0 100644 --- a/util/util.go +++ b/util/util.go @@ -207,3 +207,32 @@ func Md5V(str string) string { h.Write([]byte(str)) return hex.EncodeToString(h.Sum(nil)) } + +// 当前的时间毫秒数 对于某个时间段,比如3分钟,10分钟,是否可以被整除, +func IsModOf(curInt int64, duration time.Duration) bool { + vol := int64(0) + if duration < 24*time.Hour { + // 小于1天 + vol = (curInt + 28800000) + } else if duration >= 24*time.Hour && duration < 48*time.Hour { + // 1天 + vol = curInt - 1633881600000 + } else if duration >= 48*time.Hour && duration < 72*time.Hour { + // 2天 + vol = curInt - 1633795200000 + } else if duration >= 72*time.Hour && duration < 120*time.Hour { + // 3天 + vol = curInt - 1633708800000 + } else if duration >= 120*time.Hour { + // 5天 + vol = curInt - 1633795200000 + } else { + // fmt.Println("noMatched:", curInt) + } + + mody := vol % duration.Milliseconds() + if mody == 0 { + return true + } + return false +}