Go全家桶规划之四: gomini迷你框架之协程并发框架, 工业级巨匠

99b09faab35f4093953d7fb62565fe71.png

GO全家桶测试驱动学习:

c9fa436486464730a9e1838627e3ca4d.png

计算步骤:

        分组=》并发计算=》合并结果

业务扩展点:

        业务数据与业务计算逻辑。

代码开源:

ichub/gomini

代码位置:

a64aedeb191e48ebad5f5ec0cc31c023.png

测试用例

package app

import (
    "fmt"
    "gitee.com/ichub/gomini/mini/general/framework/coroutines"
    "gitee.com/ichub/gomini/mini/model"
    "github.com/emirpasic/gods/lists/arraylist"
    "github.com/sirupsen/logrus"
    "testing"
    "time"
)

func Test001_runner(t *testing.T) {
    //Execute()
    var rulesRunner = NewRulesRunner()
    rulesRunner.GroupNumber = 2
    rulesRunner.Tasks = arraylist.New()

    rulesRunner.Tasks.Add(model.NewRules())
    rulesRunner.Tasks.Add(model.NewRules())
    rulesRunner.Tasks.Add(model.NewRules())

    var result = coroutines.FindBeanCoRoutines().Execute(rulesRunner)
    logrus.Error(result)

}

测试结果

[2024-04-427 12:07:47]D:/go-ichub/go/gomini/mini/general/framework/app/rule_runner_test.go:24 gitee.com/ichub/gomini/mini/general/framework/app.Test001_runner() {
     "code": 200,
     "msg": "成功",
     "data": [
          {
               "code": 200,
               "msg": "成功",
               "data": [
                    {
                         "rule_id": "0",
                         "rule_key": "",
                         "name": "NAME20000",
                         "domain": "",
                         "rule": "",
                         "param": "",
                         "result": "",
                         "remark": "",
                         "func_type": "",
                         "created_at": {},
                         "created_by": "0"
                    }
               ]
          },
          {
               "code": 200,
               "msg": "成功",
               "data": [
                    {
                         "rule_id": "0",
                         "rule_key": "",
                         "name": "NAME10000",
                         "domain": "",
                         "rule": "",
                         "param": "",
                         "result": "",
                         "remark": "",
                         "func_type": "",
                         "created_at": {},
                         "created_by": "0"
                    },
                    {
                         "rule_id": "0",
                         "rule_key": "",
                         "name": "NAME10001",
                         "domain": "",
                         "rule": "",
                         "param": "",
                         "result": "",
                         "remark": "",
                         "func_type": "",
                         "created_at": {},
                         "created_by": "0"
                    }
               ]
          }
     ]

--- PASS: Test001_runner (0.02s)
PASS

代码解析

接口

package iface

import (
    "gitee.com/ichub/goconfig/common/base/basedto"
    "gitee.com/ichub/gomini/mini/general/framework/coroutines/dto"
)

type CoRunnerIface interface {
    Execute(data *dto.CoData) *basedto.IchubResult

    GetData() *dto.CoData
}

计算基类
package coroutines

import (
    "gitee.com/ichub/goconfig/common/base/basedto"
    "gitee.com/ichub/gomini/mini/general/framework/coroutines/dto"
)

type CoRunner struct {
    *dto.CoData
}

func NewCoRunner() *CoRunner {
    return &CoRunner{
       CoData: dto.NewCoData(),
    }
}

func (g *CoRunner) Execute(data *dto.CoData) *basedto.IchubResult {

    return basedto.NewIchubResult().SuccessData(data.Tasks)
}

func (g *CoRunner) GetData() *dto.CoData {
    g.CoData.DivideGroup()
    return g.CoData
}
应用计算:
package app

import (
    "gitee.com/ichub/goconfig/common/base/basedto"
    "gitee.com/ichub/goconfig/common/base/baseutils"
    "gitee.com/ichub/gomini/mini/general/framework/coroutines"
    "gitee.com/ichub/gomini/mini/general/framework/coroutines/dto"
    "gitee.com/ichub/gomini/mini/model"
)

type RulesRunner struct {
    *coroutines.CoRunner
}

func NewRulesRunner() *RulesRunner {
    return &RulesRunner{
       CoRunner: coroutines.NewCoRunner(),
    }
}

func (g *RulesRunner) Execute(data *dto.CoData) *basedto.IchubResult {
    for i := 0; i < data.Tasks.Size(); i++ {
       var task, ok = data.Tasks.Get(i)
       if ok {
          task.(*model.Rules).Name = "NAME" + baseutils.Any2Str(i+10000*data.GroupOrder)
       } else {
          return basedto.ResultFailMessage("处理类型不是Rules!")
       }
    }

    return basedto.NewIchubResult().SuccessData(data.Tasks)
}
计算执行类
package coroutines

import (
    "gitee.com/ichub/goconfig/common/base/basedto"
    "gitee.com/ichub/gomini/mini/general/framework/coroutines/dto"
    "gitee.com/ichub/gomini/mini/general/framework/coroutines/iface"
    "github.com/emirpasic/gods/lists/arraylist"
    "sync"
)

type CoRoutines struct {
    basedto.BaseEntitySingle
}

func NewCoRoutines() *CoRoutines {
    return &CoRoutines{}
}

func (self *CoRoutines) Execute(iface iface.CoRunnerIface) *basedto.IchubResult {
    if iface.GetData() == nil {
       return basedto.ResultFailMsg("Data is nil")
    }
    var wg sync.WaitGroup
    done := make(chan *basedto.IchubResult, iface.GetData().GroupTasks.Size())
    for i := 0; i < iface.GetData().GroupNumber; i++ {

       var task, ok = iface.GetData().GroupTasks.Get(i)
       if !ok {
          continue
       }
       var data = dto.NewCoData()
       data.GroupOrder = i + 1
       data.Tasks = task.(*arraylist.List)
       wg.Add(1)
       go func() {
          defer wg.Done()
          result := iface.Execute(data)
          if result == nil {
             result = basedto.ResultFailMsg("Task execution resulted in nil result")
          }
          done <- result
       }()

    }
    resultList := arraylist.New()
    // 恢复并优化超时机制
    timeout := time.After(time.Duration(iface.GetData().TimeoutSeconds))
    for i := 0; i < iface.GetData().GroupNumber; i++ {
       select {
       case <-timeout:
          fmt.Println("操作超时,退出。")
          wg.Wait()
          close(done)
          return self.Merge(resultList)
       case result := <-done:
          resultList.Add(result)
       }
    }

    wg.Wait()
    close(done)
    return self.Merge(resultList)

}

func (this *CoRoutines) MergeResult(result *basedto.IchubResult) *basedto.IchubResult {
    var groups = result.Data.(*arraylist.List)
    for i := 0; i < groups.Size(); i++ {
       //var r, _ = groups.Get(i)
       //result.Data = r.(*basedto.IchubResult).Data
    }

    return result
}
func (this *CoRoutines) Merge(taskResult *arraylist.List) *basedto.IchubResult {

    if taskResult.Size() == 0 {
       return basedto.ResultFailMsg("result is empty!")
    }
    var result = basedto.NewIchubResult()
    result.Data = taskResult
    return result
}
func (this *CoRoutines) worker(done chan *basedto.IchubResult, iface iface.CoRunnerIface, data *dto.CoData, wg *sync.WaitGroup) {

    defer wg.Done()
    var result = iface.Execute(data)

    done <- result

}

计算数据
package dto

import (
    "github.com/emirpasic/gods/lists/arraylist"
    "github.com/sirupsen/logrus"
    "time"
)

const DATA_WAIT_TIMEOUT = 5 * 60 * time.Second
const DATA_THEAD_NUMBER = 2

type CoData struct {
    //协程数
    GroupNumber    int           `json:"group_number"`
    TimeoutSeconds time.Duration `json:"timeout_seconds"`

    GroupTasks *arraylist.List `json:"group_tasks"`
    Tasks      *arraylist.List `json:"tasks"`

    GroupOrder int `json:"group_order"`
}

func NewCoData() *CoData {
    return &CoData{
       GroupNumber:    DATA_THEAD_NUMBER,
       TimeoutSeconds: DATA_WAIT_TIMEOUT,
    }
}

func (this *CoData) DivideGroup() *CoData {
    if this.GroupTasks != nil {
       return this
    }

    this.GroupTasks = arraylist.New()
    if this.Tasks.Size() == 0 {
       return this
    } else if this.Tasks.Size() <= this.GroupNumber {
       this.GroupTasks.Add(this.Tasks)
    } else {
       this.Split2Group()
    }
    return this
}
func (this *CoData) GroupSize() int {

    var groupSize = this.Tasks.Size() / this.GroupNumber
    if this.Tasks.Size()%this.GroupNumber > 0 {
       groupSize += 1
    }
    logrus.Info(groupSize, this.Tasks)
    return groupSize
}

func (this *CoData) Split2Group() {

    var groupSize = this.GroupSize()
    var j = 0
    var group = arraylist.New()
    for i := 0; i < this.Tasks.Size(); i++ {
       j++
       var task, ok = this.Tasks.Get(i)
       if ok {
          group.Add(task)
       }
       if j%groupSize == 0 || i == this.Tasks.Size()-1 {
          this.GroupTasks.Add(group)
          j = 0
          group = arraylist.New()
       }

    }

}

 

 

 

 

  • 44
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leijmdas

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值