feat(events): listener Docker events (F-002) — auto-refresh daftar + panel Aktivitas beranda hidup
CI / test (push) Successful in 25s
CI / test (push) Successful in 25s
This commit is contained in:
1 parent
177e27910b
commit
f555f27467
8 files changed
+316
-32
No files matched your search
@@ -0,0 +1,71 @@
|
||||
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
|
||||
}
|
||||
Reference in new issue
Block a user