-
Notifications
You must be signed in to change notification settings - Fork 3
GitLab Redirects #777
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
GitLab Redirects #777
Conversation
internal/redirects/redirect_store.go
Outdated
| } | ||
| } | ||
|
|
||
| func queryRenkuApi(renkuCredentials ServerCredentials, endpoint string) ([]byte, 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.
NOTE: we should open an issue to replace this with code generated from the API spec.
Co-authored-by: Flora Thiebaut <[email protected]>
Co-authored-by: Flora Thiebaut <[email protected]>
70ebf3e to
7f430da
Compare
internal/redirects/redirect_store.go
Outdated
| type RedirectStore struct { | ||
| Config config.RedirectsStoreConfig | ||
| EntryTtl time.Duration | ||
| RedirectMap map[string]RedirectStoreRedirectEntry |
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.
The redirect map should not be public:
| RedirectMap map[string]RedirectStoreRedirectEntry | |
| redirectMap map[string]RedirectStoreRedirectEntry |
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.
Fixed in 959944f
internal/redirects/redirect_store.go
Outdated
| entry, ok := rs.RedirectMap[key] | ||
| if ok && entry.UpdatedAt.Add(rs.EntryTtl).After(time.Now()) { | ||
| return &entry, nil | ||
| } | ||
|
|
||
| rs.redirectMapMutex.Lock() | ||
| defer rs.redirectMapMutex.Unlock() | ||
| // Re-check after acquiring the lock, since it might have been updated meanwhile | ||
| entry, ok = rs.RedirectMap[key] | ||
| if !ok || entry.UpdatedAt.Add(rs.EntryTtl).Before(time.Now()) { |
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.
The current code does not protect bad reads of the RedirectMap from happening.
Since the RedirectMap is only ever accessed in this method, we can use the simple sync.Mutex and we should lock the read+update access:
| entry, ok := rs.RedirectMap[key] | |
| if ok && entry.UpdatedAt.Add(rs.EntryTtl).After(time.Now()) { | |
| return &entry, nil | |
| } | |
| rs.redirectMapMutex.Lock() | |
| defer rs.redirectMapMutex.Unlock() | |
| // Re-check after acquiring the lock, since it might have been updated meanwhile | |
| entry, ok = rs.RedirectMap[key] | |
| if !ok || entry.UpdatedAt.Add(rs.EntryTtl).Before(time.Now()) { | |
| rs.redirectMapMutex.Lock() | |
| defer rs.redirectMapMutex.Unlock() | |
| entry, ok := rs.RedirectMap[key] | |
| if ok && entry.UpdatedAt.Add(rs.EntryTtl).After(time.Now()) { | |
| return &entry, nil | |
| } | |
| if !ok || entry.UpdatedAt.Add(rs.EntryTtl).Before(time.Now()) { |
Doing so will make sure that:
- Reads do not happen while the map is being updated
- This map will not be updated multiple times at once
The downside of this simple approach is that it will have poor read performance (full lock when just reading the map).
To enable better read performance, you can use a sync.RWMutex and protect reads and writes separately:
| entry, ok := rs.RedirectMap[key] | |
| if ok && entry.UpdatedAt.Add(rs.EntryTtl).After(time.Now()) { | |
| return &entry, nil | |
| } | |
| rs.redirectMapMutex.Lock() | |
| defer rs.redirectMapMutex.Unlock() | |
| // Re-check after acquiring the lock, since it might have been updated meanwhile | |
| entry, ok = rs.RedirectMap[key] | |
| if !ok || entry.UpdatedAt.Add(rs.EntryTtl).Before(time.Now()) { | |
| rs.redirectMapMutex.RLock() | |
| entry, ok := rs.RedirectMap[key] | |
| rs.redirectMapMutex.RUnlock() | |
| if ok && entry.UpdatedAt.Add(rs.EntryTtl).After(time.Now()) { | |
| return &entry, nil | |
| } | |
| rs.redirectMapMutex.Lock() | |
| defer rs.redirectMapMutex.Unlock() | |
| // Re-check after acquiring the lock, since it might have been updated meanwhile | |
| entry, ok = rs.RedirectMap[key] | |
| if !ok || entry.UpdatedAt.Add(rs.EntryTtl).Before(time.Now()) { |
Here, we can have as many read locks as we want, which corresponds to the read-heavy model of this map.
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.
Fixed in e98ef85
866938d to
e98ef85
Compare
leafty
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
No description provided.