diff --git a/business/jxstore/event/event_tcp.go b/business/jxstore/event/event_tcp.go index a0a829e6f..fb64829d8 100644 --- a/business/jxstore/event/event_tcp.go +++ b/business/jxstore/event/event_tcp.go @@ -16,6 +16,14 @@ import ( "unicode/utf8" ) +var Poll *Pool + +func init() { + Poll = NewPool(100) + Poll.Start() + +} + //入口 func ListenTcp() { l, err := net.Listen("tcp", ":8000") @@ -31,7 +39,7 @@ func ListenTcp() { break } - go func() { + fn := func() { defer func() { // 捕获异常 防止waitGroup阻塞 if err := recover(); err != nil { @@ -45,7 +53,23 @@ func ListenTcp() { t = nil return } - }() + } + Poll.AddJob(fn) + //go func() { + // defer func() { + // // 捕获异常 防止waitGroup阻塞 + // if err := recover(); err != nil { + // fmt.Println("recover err = ", err) + // return + // } + // }() + // + // t := NewTcpClient() + // if err := handleConn(c, t); err != nil { + // t = nil + // return + // } + //}() } } @@ -185,28 +209,56 @@ func (t *TcpClient) HandleTcpMessages(printNo string) { return } - go func() { + fn := func() { for { if t.TimeoutMap[printNo] == true { - timeNow := time.Now() - timeStart := time.Date(timeNow.Year(), timeNow.Month(), timeNow.Day(), 0, 0, 0, 0, timeNow.Location()) - timeEnd := time.Date(timeNow.Year(), timeNow.Month(), timeNow.Day(), 23, 59, 59, 0, timeNow.Location()) - prints, _ := dao.GetPrintMsgs(db, printNo, []int{printMsgWait}, timeStart.AddDate(0, 0, -1), timeEnd, offset, pageSize) - for _, printMsg := range prints { - printMsg.Status = printMsgAlreadyLoad - //先避免重复读再插到channel? - if _, err := dao.UpdateEntity(db, printMsg, "Status"); err == nil { - if err = t.addMsgChan(printMsg); err != nil { - globals.SugarLogger.Debugf("HandleTcpMessages addMsgChan Err: %v", err) + if time.Now().Unix()%3 == 0 { + timeNow := time.Now() + timeStart := time.Date(timeNow.Year(), timeNow.Month(), timeNow.Day(), 0, 0, 0, 0, timeNow.Location()) + timeEnd := time.Date(timeNow.Year(), timeNow.Month(), timeNow.Day(), 23, 59, 59, 0, timeNow.Location()) + prints, _ := dao.GetPrintMsgs(db, printNo, []int{printMsgWait}, timeStart.AddDate(0, 0, -1), timeEnd, offset, pageSize) + for _, printMsg := range prints { + printMsg.Status = printMsgAlreadyLoad + //先避免重复读再插到channel? + if _, err := dao.UpdateEntity(db, printMsg, "Status"); err == nil { + if err = t.addMsgChan(printMsg); err != nil { + globals.SugarLogger.Debugf("HandleTcpMessages addMsgChan Err: %v", err) + } } } + } else { + continue } } else { globals.SugarLogger.Debugf("HandleTcpMessages timeout") return } } - }() + } + Poll.AddJob(fn) + + //go func() { + // for { + // if t.TimeoutMap[printNo] == true { + // timeNow := time.Now() + // timeStart := time.Date(timeNow.Year(), timeNow.Month(), timeNow.Day(), 0, 0, 0, 0, timeNow.Location()) + // timeEnd := time.Date(timeNow.Year(), timeNow.Month(), timeNow.Day(), 23, 59, 59, 0, timeNow.Location()) + // prints, _ := dao.GetPrintMsgs(db, printNo, []int{printMsgWait}, timeStart.AddDate(0, 0, -1), timeEnd, offset, pageSize) + // for _, printMsg := range prints { + // printMsg.Status = printMsgAlreadyLoad + // //先避免重复读再插到channel? + // if _, err := dao.UpdateEntity(db, printMsg, "Status"); err == nil { + // if err = t.addMsgChan(printMsg); err != nil { + // globals.SugarLogger.Debugf("HandleTcpMessages addMsgChan Err: %v", err) + // } + // } + // } + // } else { + // globals.SugarLogger.Debugf("HandleTcpMessages timeout") + // return + // } + // } + //}() } func (t *TcpClient) readTimeoutMap(key string) bool { @@ -223,99 +275,192 @@ func (t *TcpClient) doPrint(key string) (err error) { if !t.isExistMsg(key) { return err } - go func() { - for { - if t.TimeoutMap[key] == true { - select { - case printMsg, ok := <-t.MsgMap[key]: - if !ok { - globals.SugarLogger.Debugf("doPrint err !ok ...") - return - } - var ( - data []byte - c net.Conn - ) - if printMsg != nil { - if err = checkPrintMsg(db, printMsg); err == nil { - status := t.getPrintStatus(printMsg.PrintNo) - switch status { - //只有在线才打印内容 - case printerStatusOnline: - if c = t.getPrintConn(printMsg.PrintNo); c != nil { - data, err = buildMsg(printMsg) - } - case printerStatusOffline: - err = fmt.Errorf("打印机离线!") - case printerStatusOnlineWithoutPaper: - err = fmt.Errorf("打印机缺纸!") - default: - err = fmt.Errorf("打印机状态未知!") + + fn := func() { + if t.TimeoutMap[key] == true { + select { + case printMsg, ok := <-t.MsgMap[key]: + if !ok { + globals.SugarLogger.Debugf("doPrint err !ok ...") + return + } + var ( + data []byte + c net.Conn + ) + if printMsg != nil { + if err = checkPrintMsg(db, printMsg); err == nil { + status := t.getPrintStatus(printMsg.PrintNo) + switch status { + //只有在线才打印内容 + case printerStatusOnline: + if c = t.getPrintConn(printMsg.PrintNo); c != nil { + data, err = buildMsg(printMsg) } + case printerStatusOffline: + err = fmt.Errorf("打印机离线!") + case printerStatusOnlineWithoutPaper: + err = fmt.Errorf("打印机缺纸!") + default: + err = fmt.Errorf("打印机状态未知!") } - if err != nil { - printMsg.Status = printMsgErr - printMsg.Comment = err.Error() - dao.UpdateEntity(db, printMsg, "Status", "Comment") - delete(t.TimeoutMap, key) - } else { - if c != nil { - if _, err = c.Write(data); err != nil { - globals.SugarLogger.Debugf("handleTcpMessages err [%v]", err) - //close(t.TimeoutMap[key]) - delete(t.TimeoutMap, key) - } else { - //等待回调 - dataStr := <-t.CallBackMap[key] - if dataStr != "" { - a, b := getCallbackMsgInfo(dataStr) - t.changePrintMsg(dataStr, a, b) - // 查询打印机是否扣费,未扣费就扣费,已经扣费不做处理 - have, err := dao.QueryOrderDeductionRecord(db, b, utils.Int64ToStr(a)) - if err != nil && !have { - // 扣除打印机账号金额 - if err = dao.DeductionPrintBalance(db, b); err != nil { - globals.SugarLogger.Debugf("扣除用户打印机金额错误 %s", err) - } else { - // 添加打印记录(支出记录) - if err = dao.AddPrintRecord(db, &model.PrintBillRecord{ - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - PrintNo: b, - PayType: 2, - PayMoney: 1, // 固定支出一分钱 - OrderId: utils.Int64ToStr(a), - UserId: "", - }); err != nil { - globals.SugarLogger.Debugf("添加打印机订单支付记录错误 %s", err) - } - } + } + if err != nil { + printMsg.Status = printMsgErr + printMsg.Comment = err.Error() + dao.UpdateEntity(db, printMsg, "Status", "Comment") + delete(t.TimeoutMap, key) + } else { + if c != nil { + if _, err = c.Write(data); err != nil { + globals.SugarLogger.Debugf("handleTcpMessages err [%v]", err) + //close(t.TimeoutMap[key]) + delete(t.TimeoutMap, key) + } else { + //等待回调 + dataStr := <-t.CallBackMap[key] + if dataStr != "" { + a, b := getCallbackMsgInfo(dataStr) + t.changePrintMsg(dataStr, a, b) + // 查询打印机是否扣费,未扣费就扣费,已经扣费不做处理 + have, err := dao.QueryOrderDeductionRecord(db, b, utils.Int64ToStr(a)) + if err != nil && !have { + // 扣除打印机账号金额 + if err = dao.DeductionPrintBalance(db, b); err != nil { + globals.SugarLogger.Debugf("扣除用户打印机金额错误 %s", err) } else { - globals.SugarLogger.Debugf("查询打印机扣费记录错误 %s", err) - } - //判断音频暂停? - //收到打印成功回调后,如果消息中有音频,需要等待一下,等上一个音频播完 - //暂停时间就暂时取的sound标签内内容长度/2 - if sounds := regexpSoundSpan.FindStringSubmatch(printMsg.Content); len(sounds) > 0 { - sound := sounds[1] - lenTime := time.Duration(utf8.RuneCountInString(sound)) * time.Second - time.Sleep(lenTime / 2) + // 添加打印记录(支出记录) + if err = dao.AddPrintRecord(db, &model.PrintBillRecord{ + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + PrintNo: b, + PayType: 2, + PayMoney: 1, // 固定支出一分钱 + OrderId: utils.Int64ToStr(a), + UserId: "", + }); err != nil { + globals.SugarLogger.Debugf("添加打印机订单支付记录错误 %s", err) + } } + } else { + globals.SugarLogger.Debugf("查询打印机扣费记录错误 %s", err) + } + //判断音频暂停? + //收到打印成功回调后,如果消息中有音频,需要等待一下,等上一个音频播完 + //暂停时间就暂时取的sound标签内内容长度/2 + if sounds := regexpSoundSpan.FindStringSubmatch(printMsg.Content); len(sounds) > 0 { + sound := sounds[1] + lenTime := time.Duration(utf8.RuneCountInString(sound)) * time.Second + time.Sleep(lenTime / 2) } } } } - } else { - globals.SugarLogger.Debugf("msgMap is nil") } + } else { + globals.SugarLogger.Debugf("msgMap is nil") } - } else { - globals.SugarLogger.Debugf("doPrint timeout") - return } - + } else { + globals.SugarLogger.Debugf("doPrint timeout") + return } - }() + } + + Poll.AddJob(fn) + //go func() { + // for { + // if t.TimeoutMap[key] == true { + // select { + // case printMsg, ok := <-t.MsgMap[key]: + // if !ok { + // globals.SugarLogger.Debugf("doPrint err !ok ...") + // return + // } + // var ( + // data []byte + // c net.Conn + // ) + // if printMsg != nil { + // if err = checkPrintMsg(db, printMsg); err == nil { + // status := t.getPrintStatus(printMsg.PrintNo) + // switch status { + // //只有在线才打印内容 + // case printerStatusOnline: + // if c = t.getPrintConn(printMsg.PrintNo); c != nil { + // data, err = buildMsg(printMsg) + // } + // case printerStatusOffline: + // err = fmt.Errorf("打印机离线!") + // case printerStatusOnlineWithoutPaper: + // err = fmt.Errorf("打印机缺纸!") + // default: + // err = fmt.Errorf("打印机状态未知!") + // } + // } + // if err != nil { + // printMsg.Status = printMsgErr + // printMsg.Comment = err.Error() + // dao.UpdateEntity(db, printMsg, "Status", "Comment") + // delete(t.TimeoutMap, key) + // } else { + // if c != nil { + // if _, err = c.Write(data); err != nil { + // globals.SugarLogger.Debugf("handleTcpMessages err [%v]", err) + // //close(t.TimeoutMap[key]) + // delete(t.TimeoutMap, key) + // } else { + // //等待回调 + // dataStr := <-t.CallBackMap[key] + // if dataStr != "" { + // a, b := getCallbackMsgInfo(dataStr) + // t.changePrintMsg(dataStr, a, b) + // // 查询打印机是否扣费,未扣费就扣费,已经扣费不做处理 + // have, err := dao.QueryOrderDeductionRecord(db, b, utils.Int64ToStr(a)) + // if err != nil && !have { + // // 扣除打印机账号金额 + // if err = dao.DeductionPrintBalance(db, b); err != nil { + // globals.SugarLogger.Debugf("扣除用户打印机金额错误 %s", err) + // } else { + // // 添加打印记录(支出记录) + // if err = dao.AddPrintRecord(db, &model.PrintBillRecord{ + // CreatedAt: time.Now(), + // UpdatedAt: time.Now(), + // PrintNo: b, + // PayType: 2, + // PayMoney: 1, // 固定支出一分钱 + // OrderId: utils.Int64ToStr(a), + // UserId: "", + // }); err != nil { + // globals.SugarLogger.Debugf("添加打印机订单支付记录错误 %s", err) + // } + // } + // } else { + // globals.SugarLogger.Debugf("查询打印机扣费记录错误 %s", err) + // } + // //判断音频暂停? + // //收到打印成功回调后,如果消息中有音频,需要等待一下,等上一个音频播完 + // //暂停时间就暂时取的sound标签内内容长度/2 + // if sounds := regexpSoundSpan.FindStringSubmatch(printMsg.Content); len(sounds) > 0 { + // sound := sounds[1] + // lenTime := time.Duration(utf8.RuneCountInString(sound)) * time.Second + // time.Sleep(lenTime / 2) + // } + // } + // } + // } + // } + // } else { + // globals.SugarLogger.Debugf("msgMap is nil") + // } + // } + // } else { + // globals.SugarLogger.Debugf("doPrint timeout") + // return + // } + // + // } + //}() return err } diff --git a/business/jxstore/event/print_test.go b/business/jxstore/event/print_test.go index 542f93afb..a53f20be6 100644 --- a/business/jxstore/event/print_test.go +++ b/business/jxstore/event/print_test.go @@ -8,6 +8,7 @@ import ( "strconv" "strings" "testing" + "time" "unicode/utf8" ) @@ -82,3 +83,24 @@ func TestTen216(t *testing.T) { fmt.Println(gg) fmt.Println(kk) } + +func TestNewPool(t *testing.T) { + var pool = NewPool(100) + pool.Start() + for i := 0; i < 10; i++ { + num := i + pool.AddJob(func() { + fmt.Printf("Worker %d: %d is odd? %v\n", num%5, num, num%2 == 1) + }) + } + + time.Sleep(5 * time.Second) + for i := 0; i < 10; i++ { + pool.AddJob(func() { + fmt.Println("刘磊") + }) + } + pool.Wait() + pool.Stop() + +} diff --git a/business/jxstore/event/timing_task.go b/business/jxstore/event/timing_task.go index 121c06918..c41152450 100644 --- a/business/jxstore/event/timing_task.go +++ b/business/jxstore/event/timing_task.go @@ -1,49 +1,85 @@ package event -// -//import ( -// "fmt" -// "sync" -//) -// -//type SimplePool struct { -// wg sync.WaitGroup -// work chan func() //任务队列 -//} -// -//func NewSimplePoll(workers int) *SimplePool { -// p := &SimplePool{ -// wg: sync.WaitGroup{}, -// work: make(chan func()), -// } -// p.wg.Add(workers) -// //根据指定的并发量去读取管道并执行 -// for i := 0; i < workers; i++ { -// go func() { -// defer func() { -// // 捕获异常 防止waitGroup阻塞 -// if err := recover(); err != nil { -// fmt.Println(err) -// p.wg.Done() -// } -// }() -// // 从workChannel中取出任务执行 -// for fn := range p.work { -// fn() -// } -// p.wg.Done() -// }() -// } -// return p -//} -// -//// 添加任务 -//func (p *SimplePool) Add(fn func()) { -// p.work <- fn -//} -// -//// 执行 -//func (p *SimplePool) Run() { -// close(p.work) -// p.wg.Wait() -//} +import ( + "sync" +) + +type Job func() + +type Worker struct { + id int + jobChannel chan Job + quit chan bool +} + +type Pool struct { + workers []*Worker + jobChannel chan Job + wg sync.WaitGroup +} + +func NewWorker(id int, jobChannel chan Job) *Worker { + return &Worker{ + id: id, + jobChannel: jobChannel, + quit: make(chan bool), + } +} + +func (w *Worker) Start() { + go func() { + for { + select { + case job := <-w.jobChannel: + job() + case <-w.quit: + return + } + } + }() +} + +func (w *Worker) Stop() { + go func() { + w.quit <- true + }() +} + +func NewPool(numWorkers int) *Pool { + jobChannel := make(chan Job) + pool := &Pool{ + workers: make([]*Worker, numWorkers), + jobChannel: jobChannel, + } + + for i := 0; i < numWorkers; i++ { + worker := NewWorker(i, jobChannel) + pool.workers[i] = worker + } + + return pool +} + +func (p *Pool) Start() { + for _, worker := range p.workers { + worker.Start() + } +} + +func (p *Pool) Stop() { + for _, worker := range p.workers { + worker.Stop() + } +} + +func (p *Pool) AddJob(job Job) { + p.wg.Add(1) + p.jobChannel <- func() { + job() + p.wg.Done() + } +} + +func (p *Pool) Wait() { + p.wg.Wait() +}