ev/pkg/es/driver/mem-store/mem-store.go

176 lines
4.0 KiB
Go
Raw Normal View History

2022-08-04 21:07:10 -06:00
package memstore
import (
"context"
"fmt"
2022-08-13 18:59:15 -06:00
"github.com/sour-is/ev/internal/logz"
2022-08-04 21:07:10 -06:00
"github.com/sour-is/ev/pkg/es"
"github.com/sour-is/ev/pkg/es/driver"
"github.com/sour-is/ev/pkg/es/event"
"github.com/sour-is/ev/pkg/locker"
"github.com/sour-is/ev/pkg/math"
)
type state struct {
streams map[string]*locker.Locked[event.Events]
}
type eventLog struct {
streamID string
events *locker.Locked[event.Events]
2022-08-04 21:07:10 -06:00
}
type memstore struct {
state *locker.Locked[state]
}
const AppendOnly = es.AppendOnly
const AllEvents = es.AllEvents
2022-08-04 21:07:10 -06:00
func Init(ctx context.Context) {
2022-08-13 18:59:15 -06:00
ctx, span := logz.Span(ctx)
defer span.End()
2022-08-04 21:07:10 -06:00
es.Register(ctx, "mem", &memstore{})
}
var _ driver.Driver = (*memstore)(nil)
2022-08-13 18:59:15 -06:00
func (memstore) Open(ctx context.Context, name string) (driver.Driver, error) {
_, span := logz.Span(ctx)
defer span.End()
s := &state{streams: make(map[string]*locker.Locked[event.Events])}
2022-08-04 21:07:10 -06:00
return &memstore{locker.New(s)}, nil
}
func (m *memstore) EventLog(ctx context.Context, streamID string) (driver.EventLog, error) {
2022-08-13 18:59:15 -06:00
ctx, span := logz.Span(ctx)
defer span.End()
el := &eventLog{streamID: streamID}
err := m.state.Modify(ctx, func(state *state) error {
2022-08-13 18:59:15 -06:00
_, span := logz.Span(ctx)
defer span.End()
l, ok := state.streams[streamID]
if !ok {
l = locker.New(&event.Events{})
state.streams[streamID] = l
}
el.events = l
return nil
})
if err != nil {
return nil, err
}
return el, err
}
var _ driver.EventLog = (*eventLog)(nil)
2022-08-04 21:07:10 -06:00
// Append implements driver.EventStore
func (m *eventLog) Append(ctx context.Context, events event.Events, version uint64) (uint64, error) {
2022-08-13 18:59:15 -06:00
ctx, span := logz.Span(ctx)
defer span.End()
event.SetStreamID(m.streamID, events...)
return uint64(len(events)), m.events.Modify(ctx, func(stream *event.Events) error {
2022-08-13 18:59:15 -06:00
_, span := logz.Span(ctx)
defer span.End()
2022-08-14 10:04:15 -06:00
span.AddEvent(fmt.Sprintf(" %s %#v %d", m.streamID, stream, len(*stream)))
last := uint64(len(*stream))
if version != AppendOnly && version != last {
2022-08-16 16:06:25 -06:00
return fmt.Errorf("%w: current version wrong %d != %d", es.ErrWrongVersion, version, last)
}
2022-08-04 21:07:10 -06:00
for i := range events {
2022-08-13 18:59:15 -06:00
span.AddEvent(fmt.Sprintf("read event %d of %d", i, len(events)))
2022-08-04 21:07:10 -06:00
pos := last + uint64(i) + 1
event.SetPosition(events[i], pos)
*stream = append(*stream, events[i])
2022-08-04 21:07:10 -06:00
}
return nil
})
}
// Read implements driver.EventStore
2022-08-14 10:04:15 -06:00
func (m *eventLog) Read(ctx context.Context, pos int64, count int64) (event.Events, error) {
2022-08-13 18:59:15 -06:00
ctx, span := logz.Span(ctx)
defer span.End()
var events event.Events
2022-08-04 21:07:10 -06:00
2022-08-14 10:04:15 -06:00
err := m.events.Modify(ctx, func(stream *event.Events) error {
2022-08-13 18:59:15 -06:00
_, span := logz.Span(ctx)
defer span.End()
2022-08-14 10:04:15 -06:00
span.AddEvent(fmt.Sprintf(" %s %#v %d", m.streamID, stream, len(*stream)))
first := stream.First().EventMeta().Position
last := stream.Last().EventMeta().Position
// ---
2022-08-04 21:07:10 -06:00
if first == 0 || last == 0 {
return nil
}
2022-08-10 10:09:58 -06:00
start, count := math.PagerBox(first, last, pos, count)
if count == 0 {
return nil
2022-08-04 21:07:10 -06:00
}
2022-08-14 10:04:15 -06:00
span.AddEvent(fmt.Sprint("box", first, last, pos, count))
events = make([]event.Event, math.Abs(count))
2022-08-04 21:07:10 -06:00
for i := range events {
2022-08-13 18:59:15 -06:00
span.AddEvent(fmt.Sprintf("read event %d of %d", i, math.Abs(count)))
// ---
events[i] = (*stream)[start-1]
// ---
2022-08-04 21:07:10 -06:00
if count > 0 {
start += 1
} else {
start -= 1
}
if start < first || start > last {
events = events[:i+1]
break
}
}
return nil
})
if err != nil {
return nil, err
}
2022-08-14 10:04:15 -06:00
event.SetStreamID(m.streamID, events...)
2022-08-04 21:07:10 -06:00
return events, nil
2022-08-04 21:07:10 -06:00
}
2022-08-07 11:55:49 -06:00
// FirstIndex for the streamID
func (m *eventLog) FirstIndex(ctx context.Context) (uint64, error) {
2022-08-13 18:59:15 -06:00
_, span := logz.Span(ctx)
defer span.End()
events, err := m.events.Copy(ctx)
return events.First().EventMeta().Position, err
2022-08-07 11:55:49 -06:00
}
// LastIndex for the streamID
func (m *eventLog) LastIndex(ctx context.Context) (uint64, error) {
2022-08-13 18:59:15 -06:00
_, span := logz.Span(ctx)
defer span.End()
events, err := m.events.Copy(ctx)
return events.Last().EventMeta().Position, err
2022-08-07 11:55:49 -06:00
}
2022-08-14 10:04:15 -06:00
func (m *eventLog) LoadForUpdate(ctx context.Context, a event.Aggregate, fn func(context.Context, event.Aggregate) error) (uint64, error) {
panic("not implemented")
}