From f937ead99a228b030a103e91ded8947a7ac6a02b Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Tue, 26 Sep 2023 20:14:56 +0200 Subject: [PATCH 1/3] feat: expose GetSourceID for sinks --- internal/adapter/sink_adapter.go | 4 ++++ internal/sync/mocks/Sink.go | 32 ++++++++++++++++++++++++-------- internal/sync/mocks/Source.go | 18 ++++++++++-------- internal/sync/synchronisation.go | 1 + 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/internal/adapter/sink_adapter.go b/internal/adapter/sink_adapter.go index 82ae750..dd19bda 100644 --- a/internal/adapter/sink_adapter.go +++ b/internal/adapter/sink_adapter.go @@ -102,3 +102,7 @@ func (a SinkAdapter) DeleteEvent(ctx context.Context, e models.Event) error { func (a SinkAdapter) EventsInTimeframe(ctx context.Context, start time.Time, end time.Time) ([]models.Event, error) { return a.client.EventsInTimeframe(ctx, start, end) } + +func (a SinkAdapter) GetSourceID() string { + return a.client.GetSourceID() +} diff --git a/internal/sync/mocks/Sink.go b/internal/sync/mocks/Sink.go index 0823a76..615e692 100644 --- a/internal/sync/mocks/Sink.go +++ b/internal/sync/mocks/Sink.go @@ -1,12 +1,12 @@ -// Code generated by mockery v2.15.0. DO NOT EDIT. +// Code generated by mockery v2.34.1. DO NOT EDIT. package mocks import ( context "context" - mock "github.com/stretchr/testify/mock" models "github.com/inovex/CalendarSync/internal/models" + mock "github.com/stretchr/testify/mock" time "time" ) @@ -49,6 +49,10 @@ func (_m *Sink) EventsInTimeframe(ctx context.Context, start time.Time, end time ret := _m.Called(ctx, start, end) var r0 []models.Event + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, time.Time, time.Time) ([]models.Event, error)); ok { + return rf(ctx, start, end) + } if rf, ok := ret.Get(0).(func(context.Context, time.Time, time.Time) []models.Event); ok { r0 = rf(ctx, start, end) } else { @@ -57,7 +61,6 @@ func (_m *Sink) EventsInTimeframe(ctx context.Context, start time.Time, end time } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, time.Time, time.Time) error); ok { r1 = rf(ctx, start, end) } else { @@ -67,6 +70,20 @@ func (_m *Sink) EventsInTimeframe(ctx context.Context, start time.Time, end time return r0, r1 } +// GetSourceID provides a mock function with given fields: +func (_m *Sink) GetSourceID() string { + ret := _m.Called() + + var r0 string + if rf, ok := ret.Get(0).(func() string); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(string) + } + + return r0 +} + // Name provides a mock function with given fields: func (_m *Sink) Name() string { ret := _m.Called() @@ -95,13 +112,12 @@ func (_m *Sink) UpdateEvent(ctx context.Context, e models.Event) error { return r0 } -type mockConstructorTestingTNewSink interface { +// NewSink creates a new instance of Sink. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSink(t interface { mock.TestingT Cleanup(func()) -} - -// NewSink creates a new instance of Sink. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewSink(t mockConstructorTestingTNewSink) *Sink { +}) *Sink { mock := &Sink{} mock.Mock.Test(t) diff --git a/internal/sync/mocks/Source.go b/internal/sync/mocks/Source.go index 62d6629..2bc4309 100644 --- a/internal/sync/mocks/Source.go +++ b/internal/sync/mocks/Source.go @@ -1,12 +1,12 @@ -// Code generated by mockery v2.15.0. DO NOT EDIT. +// Code generated by mockery v2.34.1. DO NOT EDIT. package mocks import ( context "context" - mock "github.com/stretchr/testify/mock" models "github.com/inovex/CalendarSync/internal/models" + mock "github.com/stretchr/testify/mock" time "time" ) @@ -21,6 +21,10 @@ func (_m *Source) EventsInTimeframe(ctx context.Context, start time.Time, end ti ret := _m.Called(ctx, start, end) var r0 []models.Event + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, time.Time, time.Time) ([]models.Event, error)); ok { + return rf(ctx, start, end) + } if rf, ok := ret.Get(0).(func(context.Context, time.Time, time.Time) []models.Event); ok { r0 = rf(ctx, start, end) } else { @@ -29,7 +33,6 @@ func (_m *Source) EventsInTimeframe(ctx context.Context, start time.Time, end ti } } - var r1 error if rf, ok := ret.Get(1).(func(context.Context, time.Time, time.Time) error); ok { r1 = rf(ctx, start, end) } else { @@ -67,13 +70,12 @@ func (_m *Source) Name() string { return r0 } -type mockConstructorTestingTNewSource interface { +// NewSource creates a new instance of Source. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewSource(t interface { mock.TestingT Cleanup(func()) -} - -// NewSource creates a new instance of Source. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -func NewSource(t mockConstructorTestingTNewSource) *Source { +}) *Source { mock := &Source{} mock.Mock.Test(t) diff --git a/internal/sync/synchronisation.go b/internal/sync/synchronisation.go index 181bfd8..c2e68fb 100644 --- a/internal/sync/synchronisation.go +++ b/internal/sync/synchronisation.go @@ -36,4 +36,5 @@ type Sink interface { UpdateEvent(ctx context.Context, e models.Event) error // DeleteEvent deletes the given Event in the external calendar DeleteEvent(ctx context.Context, e models.Event) error + GetSourceID() string } From 9079fe5c407b5e207213c6e5bfacf236491cb5bb Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Tue, 26 Sep 2023 20:37:45 +0200 Subject: [PATCH 2/3] feat: do not resurrect event when syncing in both directions --- internal/sync/controller.go | 12 +++++++ internal/sync/controller_test.go | 61 +++++++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/internal/sync/controller.go b/internal/sync/controller.go index f9a87bc..f463eb6 100644 --- a/internal/sync/controller.go +++ b/internal/sync/controller.go @@ -177,6 +177,18 @@ func (p Controller) diffEvents(sourceEvents []models.Event, sinkEvents []models. switch { case !exists: + // Don't sync synced events back to their original calendar to prevent resurrecting + // deleted events. + // Problem: + // - Sync event (from calendar A) to create eventCopy (calendar B, SourceID = calendar A). + // - Delete event (in calendar A) + // - Run sync from calendar B to calendar A. This will copy (and thereby resurrect) the event. + // + // Solution: Ignore events the originate from the sink, but no longer exist there. + if event.Metadata.SourceID == p.sink.GetSourceID() { + p.logger.Info("skipping event as it originates from the sink, but no longer exists there", logFields(event)...) + continue + } p.logger.Info("new event, needs sync", logFields(event)...) createEvents = append(createEvents, event) diff --git a/internal/sync/controller_test.go b/internal/sync/controller_test.go index cade14c..cc2a85a 100644 --- a/internal/sync/controller_test.go +++ b/internal/sync/controller_test.go @@ -94,6 +94,7 @@ func (suite *ControllerTestSuite) TestDryRun() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(sourceEvents, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(sinkEvents, nil) suite.sink.On("DeleteEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) + suite.sink.On("GetSourceID").Return("sinkID") suite.source.On("GetSourceID").Return("sourceID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, true) @@ -170,6 +171,7 @@ func (suite *ControllerTestSuite) TestCleanUp() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(sourceEvents, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(sinkEvents, nil) suite.sink.On("DeleteEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) + suite.sink.On("GetSourceID").Return("sinkID") suite.source.On("GetSourceID").Return("sourceID") err := suite.controller.CleanUp(ctx, startTime, endTime) @@ -213,6 +215,7 @@ func (suite *ControllerTestSuite) TestCreateEventsEmptySink() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(eventsToCreate, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(nil, nil) suite.sink.On("CreateEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) + suite.sink.On("GetSourceID").Return("sinkID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, false) assert.NoError(suite.T(), err) @@ -224,7 +227,7 @@ func (suite *ControllerTestSuite) TestCreateEventsEmptySink() { suite.sink.AssertNotCalled(suite.T(), "DeleteEvent", ctx, mock.AnythingOfType("models.Event")) } -// TestDeleteEventsNotInSink verifies that if events are present in the source-adapter, but not in the sink, these +// TestDeleteEventsNotInSink verifies that if events are present in the sink-adapter, but not in the source, these // events are deleted in the sink. func (suite *ControllerTestSuite) TestDeleteEventsNotInSink() { ctx := context.Background() @@ -296,6 +299,7 @@ func (suite *ControllerTestSuite) TestDeleteEventsNotInSink() { suite.sink.On("DeleteEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) // UpdateEvent gets called because the remaining event in the sink will get updated because there are no transformers configured suite.sink.On("UpdateEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) + suite.sink.On("GetSourceID").Return("sinkID") suite.source.On("GetSourceID").Return("sourceID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, false) @@ -306,6 +310,43 @@ func (suite *ControllerTestSuite) TestDeleteEventsNotInSink() { suite.sink.AssertNumberOfCalls(suite.T(), "DeleteEvent", expectedDelete) } +// TestDoNotResurrectEvents verifies that if events are present in the source-adapter that originated +// from the sink, but have been deleted there, these events are not copied to the sink. +// This ensures that for two calendars A and B, with sync A->B and B->A, that an event +// will not be restored if the original event was deleted. +func (suite *ControllerTestSuite) TestDoNotResurrectEvents() { + ctx := context.Background() + startTime := time.Now() + endTime := startTime.Add(2 * time.Hour) + sourceEvents := []models.Event{ + { + ICalUID: "testID", + ID: "testUID", + Title: "Title 1", + Description: "Description", + StartTime: startTime, + EndTime: endTime, + AllDay: false, + // originates from sink + Metadata: models.NewEventMetadata("seed1", "uri", "sinkID"), + Reminders: []models.Reminder{{Actions: models.ReminderActionDisplay, Trigger: models.ReminderTrigger{PointInTime: startTime.Add(-10 * time.Minute)}}}, + }, + } + sinkEvents := []models.Event{} + + suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(sourceEvents, nil) + suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(sinkEvents, nil) + suite.sink.On("GetSourceID").Return("sinkID") + suite.source.On("GetSourceID").Return("sourceID") + + err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, false) + assert.NoError(suite.T(), err) + + suite.sink.AssertNotCalled(suite.T(), "CreateEvent", ctx, mock.AnythingOfType("models.Event")) + suite.sink.AssertNotCalled(suite.T(), "UpdateEvent", ctx, mock.AnythingOfType("models.Event")) + suite.sink.AssertNotCalled(suite.T(), "DeleteEvent", ctx, mock.AnythingOfType("models.Event")) +} + // TestUpdateEventsPrefilledSink asserts that, given that the sink does contain any events, // the controller properly updates the events in the sink. // and leaves unmanaged events as they are @@ -425,6 +466,7 @@ func (suite *ControllerTestSuite) TestUpdateEventsPrefilledSink() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(sourceEvents, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(sinkEvents, nil) suite.sink.On("UpdateEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) + suite.sink.On("GetSourceID").Return("sinkID") suite.source.On("GetSourceID").Return("sourceID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, false) @@ -651,6 +693,19 @@ func TestController_diffEvents(t *testing.T) { expectedUpdateEvents: []models.Event{}, expectedDeleteEvents: []models.Event{}, }, + { + name: "should not resurrect events already deleted from source when syncing back from sink", + source: []models.Event{{ + Metadata: &models.Metadata{ + SyncID: "unicorn", + SourceID: "sinkID", + }, + Title: "Foo", + }}, + expectedCreateEvents: []models.Event{}, + expectedUpdateEvents: []models.Event{}, + expectedDeleteEvents: []models.Event{}, + }, } for _, tc := range tt { @@ -658,8 +713,12 @@ func TestController_diffEvents(t *testing.T) { var source mocks.Source source.On("GetSourceID").Return("sourceID") + var sink mocks.Sink + sink.On("GetSourceID").Return("sinkID") + var controller = Controller{ source: &source, + sink: &sink, logger: log.Default(), } From 320f03a746abfd661939b4a64707df9e396ff983 Mon Sep 17 00:00:00 2001 From: Michael Eischer Date: Sat, 7 Oct 2023 15:31:01 +0200 Subject: [PATCH 3/3] refactor: rename Source/Sink.GetSourceID to GetCalendarID The method returns an ID that can be used to identify the underlying calendar. Thus use a more neutral name than GetSourceID. --- internal/adapter/google/adapter.go | 8 ++++---- internal/adapter/google/client.go | 12 ++++------- internal/adapter/outlook_http/adapter.go | 6 +++--- internal/adapter/outlook_http/client.go | 4 ++-- internal/adapter/sink_adapter.go | 4 ++-- internal/adapter/source_adapter.go | 4 ++-- internal/adapter/zep/client.go | 8 ++++---- internal/sync/controller.go | 10 ++++----- internal/sync/controller_test.go | 26 ++++++++++++------------ internal/sync/mocks/Sink.go | 4 ++-- internal/sync/mocks/Source.go | 4 ++-- internal/sync/synchronisation.go | 4 ++-- 12 files changed, 45 insertions(+), 49 deletions(-) diff --git a/internal/adapter/google/adapter.go b/internal/adapter/google/adapter.go index 3df94a0..384bbc1 100644 --- a/internal/adapter/google/adapter.go +++ b/internal/adapter/google/adapter.go @@ -24,7 +24,7 @@ type GoogleCalendarClient interface { CreateEvent(ctx context.Context, event models.Event) error UpdateEvent(ctx context.Context, event models.Event) error DeleteEvent(ctx context.Context, event models.Event) error - GetSourceID() string + GetCalendarID() string InitGoogleCalendarClient(calId string, log *log.Logger) error } @@ -219,12 +219,12 @@ func (c *CalendarAPI) Name() string { return "Google Calendar" } -// GetSourceID calculates a unique SourceID for this adapter based on the current calendar. +// GetCalendarID calculates a unique ID for this adapter based on the current calendar. // This is used to distinguish between adapters in order to not overwrite or delete events // which are maintained by different adapters. // A simple use-case for this is if you have multiple google calendars as source adapters configured. -func (c *CalendarAPI) GetSourceID() string { - return c.gcalClient.GetSourceID() +func (c *CalendarAPI) GetCalendarID() string { + return c.gcalClient.GetCalendarID() } func (c *CalendarAPI) SetLogger(logger *log.Logger) { diff --git a/internal/adapter/google/client.go b/internal/adapter/google/client.go index 6fee773..0fe3592 100644 --- a/internal/adapter/google/client.go +++ b/internal/adapter/google/client.go @@ -67,7 +67,7 @@ func (g *GCalClient) ListEvents(ctx context.Context, starttime time.Time, endtim var loadedEvents []models.Event for _, event := range eventList.Items { - loadedEvents = append(loadedEvents, calendarEventToEvent(event, g.GetSourceID())) + loadedEvents = append(loadedEvents, calendarEventToEvent(event, g.GetCalendarID())) } // if the responses 'nextPageToken' is set, the result is paginated and more data to be loaded recursively @@ -77,7 +77,7 @@ func (g *GCalClient) ListEvents(ctx context.Context, starttime time.Time, endtim return nil, err } for _, pageEvent := range eventList.Items { - loadedEvents = append(loadedEvents, calendarEventToEvent(pageEvent, g.GetSourceID())) + loadedEvents = append(loadedEvents, calendarEventToEvent(pageEvent, g.GetCalendarID())) } } return loadedEvents, nil @@ -214,15 +214,11 @@ func (g *GCalClient) loadPages(listCall *calendar.EventsListCall, events *[]*cal return g.loadPages(listCall, events, pageEvents.NextPageToken) } -// TODO -// it is not ideal to have the GetSourceID func here as well, it is not used in the CalendarAPI Client anymore but we still need it to satisfy the "Source" interface -// defined in sync/sychronisation.go - -// GetSourceID calculates a unique SourceID for this adapter based on the current calendar. +// GetCalendarID calculates a unique ID for this adapter based on the current calendar. // This is used to distinguish between adapters in order to not overwrite or delete events // which are maintained by different adapters. // A simple use-case for this is if you have multiple google calendars as source adapters configured. -func (g *GCalClient) GetSourceID() string { +func (g *GCalClient) GetCalendarID() string { var id []byte sum := sha1.Sum([]byte(g.CalendarId)) diff --git a/internal/adapter/outlook_http/adapter.go b/internal/adapter/outlook_http/adapter.go index 5b71746..b672215 100644 --- a/internal/adapter/outlook_http/adapter.go +++ b/internal/adapter/outlook_http/adapter.go @@ -25,7 +25,7 @@ type OutlookCalendarClient interface { CreateEvent(ctx context.Context, event models.Event) error UpdateEvent(ctx context.Context, event models.Event) error DeleteEvent(ctx context.Context, event models.Event) error - GetSourceID() string + GetCalendarID() string } type CalendarAPI struct { @@ -212,8 +212,8 @@ func (c *CalendarAPI) DeleteEvent(ctx context.Context, e models.Event) error { return nil } -func (c *CalendarAPI) GetSourceID() string { - return c.outlookClient.GetSourceID() +func (c *CalendarAPI) GetCalendarID() string { + return c.outlookClient.GetCalendarID() } func (c *CalendarAPI) Name() string { diff --git a/internal/adapter/outlook_http/client.go b/internal/adapter/outlook_http/client.go index 223f5c9..441ed49 100644 --- a/internal/adapter/outlook_http/client.go +++ b/internal/adapter/outlook_http/client.go @@ -76,7 +76,7 @@ func (o *OutlookClient) ListEvents(ctx context.Context, start time.Time, end tim var events []models.Event for _, evt := range eventList.Events { - evt, err := o.outlookEventToEvent(evt, o.GetSourceID()) + evt, err := o.outlookEventToEvent(evt, o.GetCalendarID()) if err != nil { return nil, err } @@ -168,7 +168,7 @@ func (o *OutlookClient) DeleteEvent(ctx context.Context, event models.Event) err return nil } -func (o OutlookClient) GetSourceID() string { +func (o OutlookClient) GetCalendarID() string { var id []byte sum := sha1.Sum([]byte(o.CalendarID)) id = append(id, sum[:]...) diff --git a/internal/adapter/sink_adapter.go b/internal/adapter/sink_adapter.go index dd19bda..7a53a24 100644 --- a/internal/adapter/sink_adapter.go +++ b/internal/adapter/sink_adapter.go @@ -103,6 +103,6 @@ func (a SinkAdapter) EventsInTimeframe(ctx context.Context, start time.Time, end return a.client.EventsInTimeframe(ctx, start, end) } -func (a SinkAdapter) GetSourceID() string { - return a.client.GetSourceID() +func (a SinkAdapter) GetCalendarID() string { + return a.client.GetCalendarID() } diff --git a/internal/adapter/source_adapter.go b/internal/adapter/source_adapter.go index 4417d27..322c91b 100644 --- a/internal/adapter/source_adapter.go +++ b/internal/adapter/source_adapter.go @@ -90,8 +90,8 @@ func (a SourceAdapter) Name() string { func (a SourceAdapter) CalendarID() string { return a.calendarID } -func (a SourceAdapter) GetSourceID() string { - return a.client.GetSourceID() +func (a SourceAdapter) GetCalendarID() string { + return a.client.GetCalendarID() } func (a SourceAdapter) EventsInTimeframe(ctx context.Context, start time.Time, end time.Time) ([]models.Event, error) { diff --git a/internal/adapter/zep/client.go b/internal/adapter/zep/client.go index 70b0051..12cf9bc 100644 --- a/internal/adapter/zep/client.go +++ b/internal/adapter/zep/client.go @@ -36,11 +36,11 @@ type CalendarAPI struct { homeSet string } -func (zep *CalendarAPI) GetSourceID() string { - return zep.generateSourceID() +func (zep *CalendarAPI) GetCalendarID() string { + return zep.generateCalendarID() } -func (zep *CalendarAPI) generateSourceID() string { +func (zep *CalendarAPI) generateCalendarID() string { var id []byte components := []string{zep.username, zep.homeSet, zep.calendarID} @@ -104,7 +104,7 @@ func (zep *CalendarAPI) EventsInTimeframe(ctx context.Context, start time.Time, Description: v.Description, StartTime: v.Start, EndTime: v.End, - Metadata: models.NewEventMetadata(v.ID, "", zep.GetSourceID()), + Metadata: models.NewEventMetadata(v.ID, "", zep.GetCalendarID()), }) } diff --git a/internal/sync/controller.go b/internal/sync/controller.go index f463eb6..5061ae7 100644 --- a/internal/sync/controller.go +++ b/internal/sync/controller.go @@ -143,7 +143,7 @@ func (p Controller) CleanUp(ctx context.Context, start time.Time, end time.Time) for _, event := range sink { // Check if the sink event was synced by us, if there's no metadata the event may // be there because we were invited or because it is not managed by us - if event.Metadata.SourceID == p.source.GetSourceID() { + if event.Metadata.SourceID == p.source.GetCalendarID() { // redefine to let the closure capture individual variables event := event tasks = append(tasks, func() error { @@ -185,18 +185,18 @@ func (p Controller) diffEvents(sourceEvents []models.Event, sinkEvents []models. // - Run sync from calendar B to calendar A. This will copy (and thereby resurrect) the event. // // Solution: Ignore events the originate from the sink, but no longer exist there. - if event.Metadata.SourceID == p.sink.GetSourceID() { + if event.Metadata.SourceID == p.sink.GetCalendarID() { p.logger.Info("skipping event as it originates from the sink, but no longer exists there", logFields(event)...) continue } p.logger.Info("new event, needs sync", logFields(event)...) createEvents = append(createEvents, event) - case sinkEvent.Metadata.SourceID != p.source.GetSourceID(): + case sinkEvent.Metadata.SourceID != p.source.GetCalendarID(): p.logger.Info("event was not synced by this source adapter, skipping", logFields(event)...) // Only update the event if the event differs AND we synced it prior and set the correct metadata - case !models.IsSameEvent(event, sinkEvent) && sinkEvent.Metadata.SourceID == p.source.GetSourceID(): + case !models.IsSameEvent(event, sinkEvent) && sinkEvent.Metadata.SourceID == p.source.GetCalendarID(): p.logger.Info("event content changed, needs sync", logFields(event)...) updateEvents = append(updateEvents, sinkEvent.Overwrite(event)) @@ -215,7 +215,7 @@ func (p Controller) diffEvents(sourceEvents []models.Event, sinkEvents []models. case exists: // Nothing to do - case event.Metadata.SourceID == p.source.GetSourceID(): + case event.Metadata.SourceID == p.source.GetCalendarID(): p.logger.Info("sinkEvent is not (anymore) in sourceEvents, marked for removal", logFields(event)...) deleteEvents = append(deleteEvents, event) diff --git a/internal/sync/controller_test.go b/internal/sync/controller_test.go index cc2a85a..7aaaa32 100644 --- a/internal/sync/controller_test.go +++ b/internal/sync/controller_test.go @@ -94,8 +94,8 @@ func (suite *ControllerTestSuite) TestDryRun() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(sourceEvents, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(sinkEvents, nil) suite.sink.On("DeleteEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) - suite.sink.On("GetSourceID").Return("sinkID") - suite.source.On("GetSourceID").Return("sourceID") + suite.sink.On("GetCalendarID").Return("sinkID") + suite.source.On("GetCalendarID").Return("sourceID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, true) assert.NoError(suite.T(), err) @@ -171,8 +171,8 @@ func (suite *ControllerTestSuite) TestCleanUp() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(sourceEvents, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(sinkEvents, nil) suite.sink.On("DeleteEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) - suite.sink.On("GetSourceID").Return("sinkID") - suite.source.On("GetSourceID").Return("sourceID") + suite.sink.On("GetCalendarID").Return("sinkID") + suite.source.On("GetCalendarID").Return("sourceID") err := suite.controller.CleanUp(ctx, startTime, endTime) assert.NoError(suite.T(), err) @@ -215,7 +215,7 @@ func (suite *ControllerTestSuite) TestCreateEventsEmptySink() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(eventsToCreate, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(nil, nil) suite.sink.On("CreateEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) - suite.sink.On("GetSourceID").Return("sinkID") + suite.sink.On("GetCalendarID").Return("sinkID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, false) assert.NoError(suite.T(), err) @@ -299,8 +299,8 @@ func (suite *ControllerTestSuite) TestDeleteEventsNotInSink() { suite.sink.On("DeleteEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) // UpdateEvent gets called because the remaining event in the sink will get updated because there are no transformers configured suite.sink.On("UpdateEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) - suite.sink.On("GetSourceID").Return("sinkID") - suite.source.On("GetSourceID").Return("sourceID") + suite.sink.On("GetCalendarID").Return("sinkID") + suite.source.On("GetCalendarID").Return("sourceID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, false) assert.NoError(suite.T(), err) @@ -336,8 +336,8 @@ func (suite *ControllerTestSuite) TestDoNotResurrectEvents() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(sourceEvents, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(sinkEvents, nil) - suite.sink.On("GetSourceID").Return("sinkID") - suite.source.On("GetSourceID").Return("sourceID") + suite.sink.On("GetCalendarID").Return("sinkID") + suite.source.On("GetCalendarID").Return("sourceID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, false) assert.NoError(suite.T(), err) @@ -466,8 +466,8 @@ func (suite *ControllerTestSuite) TestUpdateEventsPrefilledSink() { suite.source.On("EventsInTimeframe", ctx, startTime, endTime).Return(sourceEvents, nil) suite.sink.On("EventsInTimeframe", ctx, startTime, endTime).Return(sinkEvents, nil) suite.sink.On("UpdateEvent", ctx, mock.AnythingOfType("models.Event")).Return(nil) - suite.sink.On("GetSourceID").Return("sinkID") - suite.source.On("GetSourceID").Return("sourceID") + suite.sink.On("GetCalendarID").Return("sinkID") + suite.source.On("GetCalendarID").Return("sourceID") err := suite.controller.SynchroniseTimeframe(ctx, startTime, endTime, false) assert.NoError(suite.T(), err) @@ -711,10 +711,10 @@ func TestController_diffEvents(t *testing.T) { for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { var source mocks.Source - source.On("GetSourceID").Return("sourceID") + source.On("GetCalendarID").Return("sourceID") var sink mocks.Sink - sink.On("GetSourceID").Return("sinkID") + sink.On("GetCalendarID").Return("sinkID") var controller = Controller{ source: &source, diff --git a/internal/sync/mocks/Sink.go b/internal/sync/mocks/Sink.go index 615e692..4a350b1 100644 --- a/internal/sync/mocks/Sink.go +++ b/internal/sync/mocks/Sink.go @@ -70,8 +70,8 @@ func (_m *Sink) EventsInTimeframe(ctx context.Context, start time.Time, end time return r0, r1 } -// GetSourceID provides a mock function with given fields: -func (_m *Sink) GetSourceID() string { +// GetCalendarID provides a mock function with given fields: +func (_m *Sink) GetCalendarID() string { ret := _m.Called() var r0 string diff --git a/internal/sync/mocks/Source.go b/internal/sync/mocks/Source.go index 2bc4309..d7b5b53 100644 --- a/internal/sync/mocks/Source.go +++ b/internal/sync/mocks/Source.go @@ -42,8 +42,8 @@ func (_m *Source) EventsInTimeframe(ctx context.Context, start time.Time, end ti return r0, r1 } -// GetSourceID provides a mock function with given fields: -func (_m *Source) GetSourceID() string { +// GetCalendarID provides a mock function with given fields: +func (_m *Source) GetCalendarID() string { ret := _m.Called() var r0 string diff --git a/internal/sync/synchronisation.go b/internal/sync/synchronisation.go index c2e68fb..3edb84d 100644 --- a/internal/sync/synchronisation.go +++ b/internal/sync/synchronisation.go @@ -22,7 +22,7 @@ type Source interface { NamedComponent // EventsInTimeframe return all events in a certain timeframe EventsInTimeframe(ctx context.Context, start time.Time, end time.Time) ([]models.Event, error) - GetSourceID() string + GetCalendarID() string } // Sink describes a NamedComponent allows write-access to events. @@ -36,5 +36,5 @@ type Sink interface { UpdateEvent(ctx context.Context, e models.Event) error // DeleteEvent deletes the given Event in the external calendar DeleteEvent(ctx context.Context, e models.Event) error - GetSourceID() string + GetCalendarID() string }