diff --git a/README.md b/README.md index f794823874c32057b9f542ab2be9f10fd4a212da..4333b476d3c9a5425ae3d06919977db07127cea6 100644 --- a/README.md +++ b/README.md @@ -303,6 +303,14 @@ import ( "gitlab.schukai.com/oss/libraries/go/application/configuration" ) +type ChangeEventHandler struct { + callback func(event configuration.ChangeEvent) +} + +func (c *ChangeEventHandler) Handle(event configuration.ChangeEvent) { + c.callback(event) +} + func main() { config := struct { Host string @@ -314,12 +322,17 @@ func main() { closeChan := make(chan bool) - s.OnChange(func(event configuration.ChangeEvent) { + var h configuration.EventHook + h = &ChangeEventHandler{ + callback: func(event configuration.ChangeEvent) { log := event.Changlog - msg := fmt.Sprintf("Change from %s to %s", log[0].From, log[0].To) + msg = fmt.Sprintf("Change from %s to %s", log[0].From, log[0].To) fmt.Println(msg) closeChan <- true - }) + }, + } + + s.OnChange(h) c := s.Config() c.Host = "www.example.com" diff --git a/change.go b/change.go index 18c63d98f08831814a34d3262ed4c6995f9f0d65..f5136700208561ac5a8272f2ebe0a8230f100d12 100644 --- a/change.go +++ b/change.go @@ -11,16 +11,40 @@ type ChangeEvent struct { Changlog diff.Changelog } -type EventHook func(event ChangeEvent) +type EventHook interface { + Handle(event ChangeEvent) +} +// OnChange registers a hook that is called when the configuration changes. func (s *Settings[C]) OnChange(hook EventHook) *Settings[C] { s.hooks.change = append(s.hooks.change, hook) return s } +// HasOnChangeHook returns true if there are registered hooks. +func (s *Settings[C]) HasOnChangeHook(hook EventHook) *Settings[C] { + for _, h := range s.hooks.change { + if h == hook { + break + } + } + return s +} + +// RemoveOnChangeHook removes a change hook from the list of hooks. +func (s *Settings[C]) RemoveOnChangeHook(hook EventHook) *Settings[C] { + for i, h := range s.hooks.change { + if h == hook { + s.hooks.change = append(s.hooks.change[:i], s.hooks.change[i+1:]...) + break + } + } + return s +} + func (s *Settings[C]) notifyChangeHooks(changelog diff.Changelog) *Settings[C] { for _, h := range s.hooks.change { - h(ChangeEvent{Changlog: changelog}) + h.Handle(ChangeEvent{Changlog: changelog}) } return s } diff --git a/change_test.go b/change_test.go index 2b8d8adbc4e6d3a25916a96974d182c807830037..7414a81a4eafe08431acdb6702a0ff176fbdc3f3 100644 --- a/change_test.go +++ b/change_test.go @@ -11,6 +11,49 @@ import ( "time" ) +type mockTestEventHandler struct { + EventHook +} + +func (m *mockTestEventHandler) Handle(event ChangeEvent) { + // do nothing + +} + +func TestAddRemoveHook(t *testing.T) { + + config := struct { + Host string + }{ + Host: "localhost", + } + + s := New(config) + + var h EventHook + h = &mockTestEventHandler{} + s.OnChange(h) + + if len(s.hooks.change) != 1 { + t.Error("Expected 1 got ", len(s.hooks.change)) + } + + s.RemoveOnChangeHook(h) + + if len(s.hooks.change) != 0 { + t.Error("Expected 0 got ", len(s.hooks.change)) + } + +} + +type ChangeEventTester struct { + callback func(event ChangeEvent) +} + +func (c *ChangeEventTester) Handle(event ChangeEvent) { + c.callback(event) +} + func TestReadmeExample(t *testing.T) { config := struct { @@ -24,13 +67,19 @@ func TestReadmeExample(t *testing.T) { closeChan := make(chan bool) msg := "" - s.OnChange(func(event ChangeEvent) { - log := event.Changlog - msg = fmt.Sprintf("Change from %s to %s", log[0].From, log[0].To) - // for Readme - //fmt.Println(msg) - closeChan <- true - }) + + var h EventHook + h = &ChangeEventTester{ + callback: func(event ChangeEvent) { + log := event.Changlog + msg = fmt.Sprintf("Change from %s to %s", log[0].From, log[0].To) + // for Readme + //fmt.Println(msg) + closeChan <- true + }, + } + + s.OnChange(h) c := s.Config() c.Host = "www.example.com" @@ -84,10 +133,16 @@ func TestCangeOnChange(t *testing.T) { closeChan := make(chan bool) counter := 0 - s.OnChange(func(event ChangeEvent) { - counter++ - closeChan <- true - }) + + var h EventHook + h = &ChangeEventTester{ + callback: func(event ChangeEvent) { + counter++ + closeChan <- true + }, + } + + s.OnChange(h) c.A = "b" s.SetConfig(c) diff --git a/http-handler_test.go b/http-handler_test.go index 1955070486847a580256ff6a336b26b96ce1b52f..7f1cdb5af4cf1ae875c55617b0eaa49bba8a5d50 100644 --- a/http-handler_test.go +++ b/http-handler_test.go @@ -271,10 +271,16 @@ func TestConfigurationServePostJson(t *testing.T) { closeChan := make(chan bool) counter := 0 - s.OnChange(func(event ChangeEvent) { - counter++ - closeChan <- true - }) + + var h EventHook + h = &ChangeEventTester{ + callback: func(event ChangeEvent) { + counter++ + closeChan <- true + }, + } + + s.OnChange(h) // We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response. rr := httptest.NewRecorder() diff --git a/watch_test.go b/watch_test.go index b310b9ef143e5a00b217e1abc5e476193cebe5ce..aafb522ff0061d380b2cc01560c2f6be92b1f62d 100644 --- a/watch_test.go +++ b/watch_test.go @@ -35,11 +35,16 @@ func TestWatch(t *testing.T) { signal := make(chan bool) - c.OnChange(func(event ChangeEvent) { - assert.Equal(t, event.Changlog[0].From, "localhost") - assert.Equal(t, event.Changlog[0].To, "example.org") - signal <- true - }) + var h EventHook + h = &ChangeEventTester{ + callback: func(event ChangeEvent) { + assert.Equal(t, event.Changlog[0].From, "localhost") + assert.Equal(t, event.Changlog[0].To, "example.org") + signal <- true + }, + } + + c.OnChange(h) c.Watch()