Files
tia-love/internal/docker/events.go
T

72 lines
1.9 KiB
Go

package docker
import (
"context"
"time"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/api/types/filters"
)
// Event — ringkasan event Docker untuk daftar auto-refresh & feed aktivitas.
type Event struct {
At time.Time
Type string // container | image | volume | network
Action string // start | stop | die | destroy | pull | …
Actor string // nama (atau ID pendek bila nama tidak ada)
}
// activityTypes — jenis event yang relevan untuk tia (buang noise daemon/plugin).
var activityTypes = []string{"container", "image", "volume", "network"}
// StreamEvents membuka stream event (follow) dari daemon; channel ditutup
// saat ctx dibatalkan atau koneksi putus. Buffer 64: saat konsumen lambat,
// event di-drop (UI tetap responsif; daftar disinkronkan ulang oleh refresh).
func (c *Client) StreamEvents(ctx context.Context) <-chan Event {
args := filters.NewArgs()
for _, t := range activityTypes {
args.Add("type", t)
}
msgCh, errCh := c.cli.Events(ctx, events.ListOptions{Filters: args})
out := make(chan Event, 64)
go func() {
defer close(out)
for {
select {
case <-ctx.Done():
return
case m, ok := <-msgCh:
if !ok {
return
}
actor := m.Actor.Attributes["name"]
if actor == "" {
// Volume: Actor.ID = nama volume penuh — jangan dipotong.
// Image: Actor.ID = sha256 (64 hex) → tampilkan 12 char.
actor = m.Actor.ID
if len(actor) == 64 {
actor = trimID(actor)
} else if len(actor) > 40 {
actor = actor[:40]
}
}
at := time.Unix(0, m.TimeNano)
if m.TimeNano == 0 {
at = time.Unix(m.Time, 0)
}
select {
case out <- Event{At: at, Type: string(m.Type), Action: string(m.Action), Actor: actor}:
default:
}
case <-errCh:
if ctx.Err() != nil {
return
}
return // koneksi putus → channel ditutup; app akan mencoba lagi
}
}
}()
return out
}