feat: build vehicle data platform and production pipeline
This commit is contained in:
@@ -2,6 +2,8 @@ package loadsim
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
@@ -19,24 +21,32 @@ type Stats struct {
|
||||
ConnectionsFailed int64
|
||||
FramesWritten int64
|
||||
WriteErrors int64
|
||||
ResponseBytes int64
|
||||
ReadErrors int64
|
||||
}
|
||||
|
||||
func (r Runner) Run(ctx context.Context, cfg Config) (Stats, error) {
|
||||
phoneBase := cfg.JT808PhoneBase
|
||||
if phoneBase <= 0 {
|
||||
phoneBase = DefaultJT808PhoneBase
|
||||
}
|
||||
if _, err := (&FlagConfig{
|
||||
protocol: string(cfg.Protocol),
|
||||
addr: cfg.Addr,
|
||||
connections: cfg.Connections,
|
||||
connectRate: cfg.ConnectRatePerSecond,
|
||||
sendInterval: cfg.SendInterval,
|
||||
duration: cfg.Duration,
|
||||
template: cfg.Template,
|
||||
protocol: string(cfg.Protocol),
|
||||
addr: cfg.Addr,
|
||||
connections: cfg.Connections,
|
||||
connectRate: cfg.ConnectRatePerSecond,
|
||||
sendInterval: cfg.SendInterval,
|
||||
duration: cfg.Duration,
|
||||
template: cfg.Template,
|
||||
jt808PhoneBase: phoneBase,
|
||||
drainResponses: cfg.DrainResponses,
|
||||
}).Build(); err != nil {
|
||||
return Stats{}, err
|
||||
}
|
||||
var factory *FrameFactory
|
||||
if cfg.SendFrames {
|
||||
var err error
|
||||
factory, err = NewFrameFactory(cfg.Protocol, cfg.Template)
|
||||
factory, err = NewFrameFactoryWithJT808PhoneBase(cfg.Protocol, cfg.Template, phoneBase)
|
||||
if err != nil {
|
||||
return Stats{}, err
|
||||
}
|
||||
@@ -74,12 +84,24 @@ func (r Runner) Run(ctx context.Context, cfg Config) (Stats, error) {
|
||||
connectionIndex++
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
defer conn.Close()
|
||||
if cfg.SendFrames {
|
||||
var readDone chan struct{}
|
||||
if cfg.DrainResponses {
|
||||
readDone = make(chan struct{})
|
||||
go func() {
|
||||
drainResponses(runCtx, conn, &stats)
|
||||
close(readDone)
|
||||
}()
|
||||
}
|
||||
writeLoop(runCtx, conn, factory, connIndex, cfg.SendInterval, &stats)
|
||||
_ = conn.Close()
|
||||
if readDone != nil {
|
||||
<-readDone
|
||||
}
|
||||
return
|
||||
}
|
||||
<-runCtx.Done()
|
||||
_ = conn.Close()
|
||||
}()
|
||||
}
|
||||
}
|
||||
@@ -88,6 +110,28 @@ func (r Runner) Run(ctx context.Context, cfg Config) (Stats, error) {
|
||||
return stats, nil
|
||||
}
|
||||
|
||||
func drainResponses(ctx context.Context, conn net.Conn, stats *Stats) {
|
||||
buffer := make([]byte, 4096)
|
||||
for {
|
||||
_ = conn.SetReadDeadline(time.Now().Add(time.Second))
|
||||
read, err := conn.Read(buffer)
|
||||
if read > 0 {
|
||||
atomic.AddInt64(&stats.ResponseBytes, int64(read))
|
||||
}
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
if ctx.Err() != nil || errors.Is(err, net.ErrClosed) || errors.Is(err, io.EOF) {
|
||||
return
|
||||
}
|
||||
if timeout, ok := err.(net.Error); ok && timeout.Timeout() {
|
||||
continue
|
||||
}
|
||||
atomic.AddInt64(&stats.ReadErrors, 1)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func writeLoop(ctx context.Context, conn net.Conn, factory *FrameFactory, connectionIndex int, interval time.Duration, stats *Stats) {
|
||||
for frameIndex := int64(0); ; frameIndex++ {
|
||||
payload, err := factory.Frame(connectionIndex, frameIndex)
|
||||
|
||||
Reference in New Issue
Block a user