-
Notifications
You must be signed in to change notification settings - Fork 19
refact: Updated polling_manager implementation and unit tests. #224
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
|
||
| // SyncConfig gets current datafile and updates projectConfig | ||
| func (cm *PollingProjectConfigManager) SyncConfig(datafile []byte) { | ||
| func (cm *PollingProjectConfigManager) SyncConfig() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
downloads datafile
pkg/config/polling_manager.go
Outdated
| if projectConfig, _ := datafileprojectconfig.NewDatafileProjectConfig(initDatafile); projectConfig != nil { | ||
| _ = pollingProjectConfigManager.setConfig(projectConfig) | ||
| } | ||
| pollingProjectConfigManager.notificationCenter = registry.GetNotificationCenter(sdkKey) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add comment, notificationcenter is set later to avoid hard-coded config update notification.
pkg/config/polling_manager.go
Outdated
| cm.err = nil | ||
| cm.configLock.Unlock() | ||
|
|
||
| if cm.notificationCenter != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should separate notificationCenter in a new method.
msohailhussain
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please address
| func assertPeriodically(t *testing.T, evaluationMethod func() bool) { | ||
| assert.Eventually(t, func() bool { | ||
| return evaluationMethod() | ||
| }, 500*time.Millisecond, 110*time.Millisecond) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think no issue to execute for 1 second and reduce recurring time to 50ms
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This causes issues in tests where we expect no changes in config after second poll. In such cases, 50ms returns true at 150ms, before the second polling is done which will be at 200ms.
pkg/config/polling_manager_test.go
Outdated
| eg.Go(configManager.Start) | ||
| evaluationMethod := func() bool { | ||
| actual, _ := configManager.GetConfig() | ||
| return reflect.DeepEqual(projectConfig, actual) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use actual.GetRevision() == hardcodedRevision.
pkg/config/polling_manager_test.go
Outdated
| eg.Go(configManager.Start) | ||
| evaluationMethod := func() bool { | ||
| actual, _ := configManager.GetConfig() | ||
| return reflect.DeepEqual(projectConfig, actual) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use only revision to identify config version.
pkg/config/polling_manager_test.go
Outdated
| eg.TerminateAndWait() | ||
| } | ||
|
|
||
| func TestSyncConfig(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you are trying to test, please add as a comment. TestSyncConfig is very general name.
pkg/config/polling_manager_test.go
Outdated
| // poll after 100ms | ||
| eg.Go(configManager.Start) | ||
| evaluationMethod := func() bool { | ||
| _, err := configManager.GetConfig() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same as above.
|
|
||
| func TestNewPollingProjectConfigManagerWithSimilarDatafileRevisions(t *testing.T) { | ||
| mockDatafile1 := []byte(`{"revision":"42","botFiltering":true}`) | ||
| mockDatafile2 := []byte(`{"revision":"42","botFiltering":false}`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
botFiltering is false Please make it same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need the difference in datafiles to make sure the original datafile wasn't changed because of same revision.
| eg.TerminateAndWait() | ||
| } | ||
|
|
||
| func TestNewPollingProjectConfigManagerWithSimilarDatafileRevisions(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please assert notification, it shouldn't be sent. request assertion should be true.
| eg.TerminateAndWait() | ||
| } | ||
|
|
||
| func TestNewAsyncPollingProjectConfigManagerWithSimilarDatafileRevisions(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what's here you want to test, please add in the comments.
| asyncConfigManager := NewAsyncPollingProjectConfigManager(sdkKey, WithRequester(mockRequester), WithInitialDatafile(mockDatafile1), WithPollingInterval(100*time.Millisecond)) | ||
|
|
||
| var numberOfCalls uint64 = 0 | ||
| callback := func(notification notification.ProjectConfigUpdateNotification) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we have similar datafile revision, then how it's gonna be called. please explain the reason to declare here.
pkg/config/polling_manager_test.go
Outdated
|
|
||
| // poll after 100ms | ||
| eg.Go(asyncConfigManager.Start) | ||
| evaluationMethod := func() bool { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is not best fit here, just use sleep
pkg/config/polling_manager_test.go
Outdated
| assert.NotNil(t, actual) | ||
| assert.Equal(t, projectConfig1, actual) | ||
| // poll after 100ms to check no changes were made to the previous config because of 304 error code (first poll) | ||
| eg.Go(configManager.Start) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't use Start, use SyncConfig
pkg/config/polling_manager_test.go
Outdated
| actual, err = configManager.GetConfig() | ||
| assert.Equal(t, projectConfig2, actual) | ||
| // poll after 100ms | ||
| eg.Go(configManager.Start) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start immediately while you are instantiating object.
pkg/config/polling_manager_test.go
Outdated
| assert.Equal(t, projectConfig1, actual) | ||
|
|
||
| // poll after 100ms | ||
| eg.Go(asyncConfigManager.Start) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't poll. just use SyncConfig
pawels-optimizely
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please see my comments
pkg/config/polling_manager.go
Outdated
| return cm.projectConfig, nil | ||
| } | ||
|
|
||
| func (cm *PollingProjectConfigManager) setConfig(projectConfig ProjectConfig) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would remove locking mechanism here and minimize the number of calls to locking.
of course cm.sendConfigUpdateNotification() will need to be called in SyncConfig then
pkg/config/polling_manager.go
Outdated
| cm.setConfig(projectConfig) | ||
| cm.err = nil | ||
| } else { | ||
| cm.err = err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think , to be safe, we need to lock cm.err too.
pkg/config/polling_manager.go
Outdated
| cmLogger.Warning("Problem with sending notification") | ||
| } | ||
| } | ||
| cm.sendConfigUpdateNotification() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think cm.setConfig() should still return an error, and we need to sendConfigUpdateNotification only when error is not nil
pawels-optimizely
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it looks much cleaner, thank you for the changes, I put 2 small comments which I think need to be addressed. otherwise lgtm
pkg/config/polling_manager.go
Outdated
| cmLogger.Debug(fmt.Sprintf("New datafile set with revision: %s. Old revision: %s", projectConfig.GetRevision(), previousRevision)) | ||
| cm.sendConfigUpdateNotification() | ||
| } | ||
| closeMutex(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
closing mutex needs to happen before sending notification.
pawels-optimizely
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
closing mutex needs to happen before sending notification.
otherwise looks good
pawels-optimizely
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
msohailhussain
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Summary