处理channel 100条数据写入一批数据,超过1s自动提交
package main
import (
"io"
"log"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
type LogBatch struct {
Logs []string
}
type LogSink struct {
logChan chan string
autoCommitChan chan *LogBatch
}
func main() {
logFile, err := os.OpenFile("test.log", os.O_CREATE | os.O_APPEND | os.O_RDWR, 0666)
if err != nil {
panic(err)
}
defer logFile.Close()
mw := io.MultiWriter(os.Stdout,logFile)
log.SetOutput(mw)
logSink := &LogSink{
logChan: make(chan string, 2000),
autoCommitChan: make(chan *LogBatch, 1000),
}
go logSink.writeLoop()
page := 1
for{
time.Sleep(time.Millisecond * time.Duration(rand.Intn(500) + 700))
for i := (page-1)*50; i< 50*page;i++ {
logSink.logChan <- strconv.Itoa(i)
}
page++
}
}
func (c *LogSink)writeLoop() {
var (
limit = 100
logStr string
logBatch *LogBatch
commitTimer *time.Timer
timeOutBatch *LogBatch
)
for {
select {
case logStr = <-c.logChan:
if logBatch == nil {
logBatch = &LogBatch{}
commitTimer = time.AfterFunc(
1*time.Second, func(logBatch *LogBatch) func() {
return func() {
c.autoCommitChan <- logBatch
}
}(logBatch),
)
}
logBatch.Logs = append(logBatch.Logs, logStr)
if len(logBatch.Logs) >= limit {
commitTimer.Stop()
log.Println(strings.Join(logBatch.Logs, "|"))
logBatch = nil
}
case timeOutBatch = <-c.autoCommitChan:
if timeOutBatch != logBatch {
continue
}
log.Println("超时:", strings.Join(timeOutBatch.Logs, "|"))
logBatch = nil
}
}
}