feat: add dynamic config reload, unique device identity (UUID), and MQTT support
- New StreamManager for dynamic RTSP/FLV stream lifecycle - Dynamic worker scaling for inference - Device UUID generation and persistence - Telegraf config and NPU monitoring scripts - .gitignore for build artifacts
This commit is contained in:
@@ -46,31 +46,75 @@ type dedupState struct {
|
||||
}
|
||||
|
||||
type Client struct {
|
||||
cfg *config.Config
|
||||
frames <-chan stream.Frame
|
||||
events chan<- event.SuspectedEvent
|
||||
dedup *dedupState
|
||||
cfg *config.Config
|
||||
frames <-chan stream.Frame
|
||||
events chan<- event.SuspectedEvent
|
||||
dedup *dedupState
|
||||
updates <-chan *config.Config
|
||||
}
|
||||
|
||||
func NewClient(cfg *config.Config, frames <-chan stream.Frame, events chan<- event.SuspectedEvent) *Client {
|
||||
func NewClient(cfg *config.Config, frames <-chan stream.Frame, events chan<- event.SuspectedEvent, updates <-chan *config.Config) *Client {
|
||||
return &Client{
|
||||
cfg: cfg,
|
||||
frames: frames,
|
||||
events: events,
|
||||
dedup: &dedupState{seen: make(map[string]float64)},
|
||||
cfg: cfg,
|
||||
frames: frames,
|
||||
events: events,
|
||||
dedup: &dedupState{seen: make(map[string]float64)},
|
||||
updates: updates,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Run(ctx context.Context) {
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < c.cfg.InferWorkers; i++ {
|
||||
|
||||
// Worker management loop
|
||||
numWorkers := c.cfg.InferWorkers
|
||||
activeWorkers := make([]context.CancelFunc, numWorkers)
|
||||
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
workerCtx, cancel := context.WithCancel(ctx)
|
||||
activeWorkers[i] = cancel
|
||||
wg.Add(1)
|
||||
go func(workerID int) {
|
||||
go func(id int, wCtx context.Context) {
|
||||
defer wg.Done()
|
||||
c.workerLoop(ctx, workerID)
|
||||
}(i)
|
||||
c.workerLoop(wCtx, id)
|
||||
}(i, workerCtx)
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
for _, cancel := range activeWorkers {
|
||||
cancel()
|
||||
}
|
||||
wg.Wait()
|
||||
return
|
||||
case newCfg := <-c.updates:
|
||||
c.cfg = newCfg
|
||||
target := c.cfg.InferWorkers
|
||||
if target < 0 {
|
||||
target = 0
|
||||
}
|
||||
|
||||
// Scale up
|
||||
for i := len(activeWorkers); i < target; i++ {
|
||||
workerCtx, cancel := context.WithCancel(ctx)
|
||||
activeWorkers = append(activeWorkers, cancel)
|
||||
wg.Add(1)
|
||||
go func(id int, wCtx context.Context) {
|
||||
defer wg.Done()
|
||||
c.workerLoop(wCtx, id)
|
||||
}(i, workerCtx)
|
||||
}
|
||||
// Scale down
|
||||
if target < len(activeWorkers) {
|
||||
for i := target; i < len(activeWorkers); i++ {
|
||||
activeWorkers[i]()
|
||||
}
|
||||
activeWorkers = activeWorkers[:target]
|
||||
}
|
||||
log.Printf("infer: workers scaled to %d", target)
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (c *Client) workerLoop(ctx context.Context, workerID int) {
|
||||
@@ -89,10 +133,9 @@ func (c *Client) workerLoop(ctx context.Context, workerID int) {
|
||||
log.Printf("infer[w%d]: socket connected", workerID)
|
||||
if !c.loop(ctx, conn, workerID) {
|
||||
conn.Close()
|
||||
return
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
conn.Close()
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,12 +146,10 @@ func (c *Client) loop(ctx context.Context, conn net.Conn, workerID int) bool {
|
||||
return false
|
||||
case f := <-c.frames:
|
||||
if err := c.send(conn, f); err != nil {
|
||||
log.Printf("infer[w%d]: send error: %v", workerID, err)
|
||||
return true
|
||||
}
|
||||
res, err := c.recv(conn)
|
||||
if err != nil {
|
||||
log.Printf("infer[w%d]: recv error: %v", workerID, err)
|
||||
return true
|
||||
}
|
||||
c.emitEvents(f, res)
|
||||
|
||||
Reference in New Issue
Block a user