forked from hetznercloud/hcloud-cloud-controller-manager
-
Notifications
You must be signed in to change notification settings - Fork 7
🌱 Force Cache Refresh when Server was not found by name. #84
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
Merged
Merged
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
3742073
fix(robot): refresh stale cache on bare-metal name lookup miss
guettli a8f2d65
fix(robot): refresh stale cache on bare-metal name lookup miss
guettli 98d256a
use type assertion to keep diff smaller.
guettli 1d9d7da
fix(robot): refresh stale cache on bare-metal name lookup miss
guettli 2997209
docs.
guettli 750b722
cache of names which triggered a refresh of cache.
guettli 6078c4d
docs.
guettli b890440
cache with timeout, not simple slice.
guettli 5197fb8
PR feedback.
guettli 6029b1f
move this up:
guettli a2dfd76
docs.
guettli ca4fd5d
docs.
guettli 945a2ea
Fix lint in robot client wrappers
guettli f032308
one method, not two.
guettli 88585c9
comment added.
guettli 4cfba46
add comments to TestInstances_InstanceExistsRobotServerRepeatedMissin…
guettli 57538d0
added comments, inlined nodeTriggeredForcedRefresh.
guettli File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package client | ||
|
|
||
| import ( | ||
| hrobot "github.com/syself/hrobot-go" | ||
| "github.com/syself/hrobot-go/models" | ||
| ) | ||
|
|
||
| var _ Client = &adapter{} | ||
|
|
||
| type adapter struct { | ||
| hrobot.RobotClient | ||
| } | ||
|
|
||
| // New wraps a plain Robot client so it satisfies the local Client interface. | ||
| func New(robotClient hrobot.RobotClient) Client { | ||
| if robotClient == nil { | ||
| return nil | ||
| } | ||
| return &adapter{RobotClient: robotClient} | ||
| } | ||
|
|
||
| // ServerGetListForceRefresh falls back to the plain list call because the | ||
| // uncached behavior only exists in the cache-backed client implementation. | ||
| func (a *adapter) ServerGetListForceRefresh(_ string) ([]models.Server, error) { | ||
| return a.ServerGetList() | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,6 +18,7 @@ const ( | |
| robotUserNameENVVar = "ROBOT_USER_NAME" | ||
| robotPasswordENVVar = "ROBOT_PASSWORD" | ||
| cacheTimeoutENVVar = "CACHE_TIMEOUT" | ||
| defaultCacheTimeout = 5 * time.Minute | ||
| ) | ||
|
|
||
| var _ robotclient.Client = &cacheRobotClient{} | ||
|
|
@@ -27,10 +28,16 @@ type cacheRobotClient struct { | |
| timeout time.Duration | ||
|
|
||
| lastUpdate time.Time | ||
| now func() time.Time | ||
|
|
||
| // cache | ||
| l []models.Server | ||
| m map[int]*models.Server | ||
|
|
||
| // forcedRefreshServerNames stores when a node name last triggered a forced Robot server list | ||
| // refresh. While that timestamp is still within the cache timeout window, repeated lookups for | ||
| // the same missing server name skip the extra uncached Robot API call. | ||
| forcedRefreshServerNames map[string]time.Time | ||
| } | ||
|
|
||
| // NewCachedRobotClient creates a new robot client with caching enabled. | ||
|
|
@@ -51,7 +58,7 @@ func NewCachedRobotClient(rootDir string, httpClient *http.Client, baseURL strin | |
| } | ||
|
|
||
| if cacheTimeout == 0 { | ||
| cacheTimeout = 5 * time.Minute | ||
| cacheTimeout = defaultCacheTimeout | ||
| } | ||
|
|
||
| credentialsDir := credentials.GetDirectory(rootDir) | ||
|
|
@@ -85,6 +92,8 @@ func NewCachedRobotClient(rootDir string, httpClient *http.Client, baseURL strin | |
| handler := &cacheRobotClient{} | ||
| handler.timeout = cacheTimeout | ||
| handler.robotClient = c | ||
| handler.now = time.Now | ||
| handler.forcedRefreshServerNames = make(map[string]time.Time) | ||
| return handler, nil | ||
| } | ||
|
|
||
|
|
@@ -105,7 +114,7 @@ func (c *cacheRobotClient) ServerGet(id int) (*models.Server, error) { | |
| } | ||
|
|
||
| // set time of last update | ||
| c.lastUpdate = time.Now() | ||
| c.lastUpdate = c.currentTime() | ||
| } | ||
|
|
||
| server, found := c.m[id] | ||
|
|
@@ -134,30 +143,88 @@ func (c *cacheRobotClient) ServerGetList() ([]models.Server, error) { | |
| } | ||
|
|
||
| // set time of last update | ||
| c.lastUpdate = time.Now() | ||
| c.lastUpdate = c.currentTime() | ||
| } | ||
|
|
||
| return c.l, nil | ||
| } | ||
|
|
||
| // ServerGetListForceRefresh invalidates the current cache and reloads the list | ||
| // from Robot unless nodeName already triggered a forced refresh within the | ||
| // current timeout window. | ||
| func (c *cacheRobotClient) ServerGetListForceRefresh(nodeName string) ([]models.Server, error) { | ||
| if nodeName != "" && c.nodeHasAlreadyForcedRefresh(nodeName) { | ||
| return c.ServerGetList() | ||
| } | ||
|
|
||
| // setting cache of serverId to serverName mapping to nil, so that the next ServerGetList() will | ||
| // call the robot API to get the new data. | ||
| c.m = nil | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you add a comment that you do this in order to delete the cache and to call the actual API?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. part of 57538d0 |
||
|
|
||
| list, err := c.ServerGetList() | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| if nodeName != "" { | ||
guettli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| c.forcedRefreshServerNames[nodeName] = c.currentTime() | ||
| } | ||
|
|
||
| return list, nil | ||
| } | ||
|
|
||
| // nodeHasAlreadyForcedRefresh reports whether nodeName already triggered a | ||
| // forced refresh within the current cache timeout window. | ||
| func (c *cacheRobotClient) nodeHasAlreadyForcedRefresh(nodeName string) bool { | ||
| if c.forcedRefreshServerNames == nil { | ||
| return false | ||
| } | ||
|
|
||
| forcedAt, found := c.forcedRefreshServerNames[nodeName] | ||
guettli marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| if !found { | ||
| return false | ||
| } | ||
|
|
||
| if c.currentTime().After(forcedAt.Add(c.forceRefreshTimeout())) { | ||
| delete(c.forcedRefreshServerNames, nodeName) | ||
| return false | ||
| } | ||
|
|
||
| return true | ||
| } | ||
| func (c *cacheRobotClient) shouldSync() bool { | ||
| // map is nil means we have no cached value yet | ||
| if c.m == nil { | ||
| c.m = make(map[int]*models.Server) | ||
| return true | ||
| } | ||
| if time.Now().After(c.lastUpdate.Add(c.timeout)) { | ||
| if c.currentTime().After(c.lastUpdate.Add(c.timeout)) { | ||
| return true | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| func (c *cacheRobotClient) currentTime() time.Time { | ||
| if c.now == nil { | ||
| return time.Now() | ||
| } | ||
| return c.now() | ||
| } | ||
|
|
||
| func (c *cacheRobotClient) forceRefreshTimeout() time.Duration { | ||
| if c.timeout == 0 { | ||
| return defaultCacheTimeout | ||
| } | ||
| return c.timeout | ||
| } | ||
|
|
||
| func (c *cacheRobotClient) SetCredentials(username, password string) error { | ||
| err := c.robotClient.SetCredentials(username, password) | ||
| if err != nil { | ||
| return err | ||
| } | ||
| // The credentials have been updated, so we need to invalidate the cache. | ||
| c.m = nil | ||
| c.forcedRefreshServerNames = nil | ||
| return nil | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.