feat: big ahh commit

- agent+proto+backend: transfer service status
- agent: fix returning empty message on nonzero exit status
- backend: refactor collector+commander and handlers dependent on them: implement agent accounting via grpc stats handler
This commit is contained in:
2026-04-04 22:55:39 +03:00
parent b516a54c17
commit 7be99f8e91
12 changed files with 541 additions and 190 deletions
+12 -41
View File
@@ -4,7 +4,6 @@ import (
"fmt"
"io"
"log"
"sync"
"time"
"gitea.d3m0k1d.ru/d3m0k1d/HellreigN/backend/internal/repository"
@@ -13,26 +12,19 @@ import (
"google.golang.org/grpc/metadata"
)
// Collector handles log streaming from connected agents.
type Collector struct {
proto.UnimplementedCollectorServer
logRepo *repository.LogRepository
agents map[string]*Agent
mu sync.RWMutex
tracker *ConnTracker
batchSize int
flushInterval time.Duration
}
type Agent struct {
ID string
Label string
Services []string
ConnectedAt time.Time
}
func New(logRepo *repository.LogRepository) *Collector {
func New(logRepo *repository.LogRepository, tracker *ConnTracker) *Collector {
return &Collector{
logRepo: logRepo,
agents: make(map[string]*Agent),
tracker: tracker,
batchSize: 100,
flushInterval: 2 * time.Second,
}
@@ -56,27 +48,15 @@ func (c *Collector) Stream(stream proto.Collector_StreamServer) error {
}
service := serviceVals[0]
servicesVals := md["services"]
var services []string
if len(servicesVals) > 0 {
services = servicesVals
}
// Register agent
c.mu.Lock()
c.agents[agentName] = &Agent{
agent := &Agent{
ID: agentName,
Label: agentName,
Services: services,
Services: make([]Service, 0),
ConnectedAt: time.Now(),
}
c.mu.Unlock()
defer func() {
c.mu.Lock()
delete(c.agents, agentName)
c.mu.Unlock()
}()
c.tracker.Register(agent)
defer c.tracker.Unregister(agent.ID)
log.Printf("Agent %s connected, streaming logs for service: %s", agentName, service)
@@ -139,7 +119,6 @@ func (c *Collector) Stream(stream proto.Collector_StreamServer) error {
for {
select {
case <-stream.Context().Done():
// Context cancelled, flush remaining
_ = flush()
return stream.Context().Err()
case <-ticker.C:
@@ -162,7 +141,6 @@ func (c *Collector) Stream(stream proto.Collector_StreamServer) error {
}
case err := <-errCh:
if err == io.EOF {
// Client closed stream
return flush()
}
return fmt.Errorf("failed to receive: %w", err)
@@ -170,19 +148,12 @@ func (c *Collector) Stream(stream proto.Collector_StreamServer) error {
}
}
// GetAgent delegates to the tracker.
func (c *Collector) GetAgent(name string) (*Agent, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
a, ok := c.agents[name]
return a, ok
return c.tracker.GetAgent(name)
}
// Agents delegates to the tracker.
func (c *Collector) Agents() []*Agent {
c.mu.RLock()
defer c.mu.RUnlock()
result := make([]*Agent, 0, len(c.agents))
for _, a := range c.agents {
result = append(result, a)
}
return result
return c.tracker.Agents()
}