Skip to content

Instantly share code, notes, and snippets.

@geoah
Created January 26, 2022 18:33
Show Gist options
  • Save geoah/f559bfbfd1feedb82cceba7bff6bd66a to your computer and use it in GitHub Desktop.
Save geoah/f559bfbfd1feedb82cceba7bff6bd66a to your computer and use it in GitHub Desktop.
go1.18-eventsource-poc-v0
package stream
import (
"fmt"
"nimona.io/pkg/object"
)
type (
Applicable[State any] interface {
Apply(*State) error
}
Controller[State any] interface {
NewStream() Stream[State]
}
Stream[State any] interface {
ApplyObject(*object.Object) error
ApplyEvent(Applicable[State]) error
GetState() State
}
controller[State any] struct{}
stream[State any] struct {
// lock sync.RWMutex // TODO add mutex
LatestState *State
}
)
func NewController[State any]() Controller[State] {
c := &controller[State]{}
return c
}
func (c *controller[State]) NewStream() Stream[State] {
s := &stream[State]{
LatestState: new(State),
}
return s
}
func (s *stream[State]) ApplyObject(o *object.Object) error {
return nil
}
func (s *stream[State]) ApplyEvent(e Applicable[State]) error {
err := e.Apply(s.LatestState)
if err != nil {
return fmt.Errorf("error applying state, %w", err)
}
return nil
}
func (s *stream[State]) GetState() State {
return *s.LatestState
}
package stream
import (
"testing"
"github.com/stretchr/testify/require"
"nimona.io/pkg/object"
)
type (
TestState struct {
Foo int
Bar int
Comments []string
}
TestEventAddFoo struct {
Metadata object.Metadata
}
TestEventAddBar struct {
Metadata object.Metadata
}
TestEventAddComment struct {
Metadata object.Metadata
Comment string
}
)
func (e *TestEventAddFoo) Apply(s *TestState) error {
s.Foo++
return nil
}
func (e *TestEventAddBar) Apply(s *TestState) error {
s.Bar++
return nil
}
func (e *TestEventAddComment) Apply(s *TestState) error {
s.Comments = append(s.Comments, e.Comment)
return nil
}
func Test_Controller_Example(t *testing.T) {
c := NewController[TestState]()
require.NotNil(t, c)
s := c.NewStream()
err := s.ApplyEvent(&TestEventAddFoo{})
require.NoError(t, err)
err = s.ApplyEvent(&TestEventAddFoo{})
require.NoError(t, err)
err = s.ApplyEvent(&TestEventAddBar{})
require.NoError(t, err)
err = s.ApplyEvent(&TestEventAddComment{Comment: "hello"})
require.NoError(t, err)
err = s.ApplyEvent(&TestEventAddComment{Comment: "world"})
require.NoError(t, err)
require.Equal(t, TestState{
Foo: 2,
Bar: 1,
Comments: []string{
"hello",
"world",
},
}, s.GetState())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment