// internal/adapter/buffer.go package adapter import ( "sync" "time" ) type RingBuffer struct { mu sync.RWMutex data []byte writePtr int count int lastWrite time.Time } func NewRingBuffer(size int) *RingBuffer { return &RingBuffer{ data: make([]byte, size), lastWrite: time.Now(), } } func (rb *RingBuffer) Write(b byte) { rb.mu.Lock() defer rb.mu.Unlock() rb.data[rb.writePtr] = b rb.writePtr = (rb.writePtr + 1) % len(rb.data) if rb.count < len(rb.data) { rb.count++ } rb.lastWrite = time.Now() } func (rb *RingBuffer) LastWriteTime() time.Time { rb.mu.RLock() defer rb.mu.RUnlock() return rb.lastWrite } func (rb *RingBuffer) GetLatest() (byte, bool) { rb.mu.RLock() defer rb.mu.RUnlock() if rb.count == 0 { return 0, false } idx := rb.writePtr - 1 if idx < 0 { idx += len(rb.data) } return rb.data[idx], true } func (rb *RingBuffer) GetLast(n int) []byte { rb.mu.RLock() defer rb.mu.RUnlock() if n > rb.count { n = rb.count } res := make([]byte, n) start := rb.writePtr - n if start < 0 { start += len(rb.data) copy(res, rb.data[start:]) copy(res[len(rb.data)-start:], rb.data[:rb.writePtr]) } else { copy(res, rb.data[start:rb.writePtr]) } return res } func (rb *RingBuffer) Stats() map[string]interface{} { rb.mu.RLock() defer rb.mu.RUnlock() return map[string]interface{}{ "size": len(rb.data), "filled": rb.count, "last_write": rb.lastWrite, } } func (rb *RingBuffer) IsAlive(timeout time.Duration) bool { rb.mu.RLock() defer rb.mu.RUnlock() return time.Since(rb.lastWrite) < timeout }