-
Notifications
You must be signed in to change notification settings - Fork 0
cache fmsgid requests #16
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ import ( | |
| "log" | ||
| "net/http" | ||
| "strings" | ||
| "sync" | ||
| "time" | ||
|
|
||
| "github.com/gin-gonic/gin" | ||
|
|
@@ -221,11 +222,41 @@ func IsValidAddr(addr string) bool { | |
| return strings.Contains(rest, "@") | ||
| } | ||
|
|
||
| // fmsgIDClient is a dedicated HTTP client with a bounded timeout so that a | ||
| // slow or hung fmsgid never blocks an API request goroutine indefinitely | ||
| // (which would otherwise hold the inbound HTTP connection open and exhaust | ||
| // the browser's per-host connection limit). | ||
| var fmsgIDClient = &http.Client{Timeout: 5 * time.Second} | ||
|
|
||
| // fmsgIDCacheTTL is how long a positive fmsgid lookup is cached. Tokens are | ||
| // re-validated every time, but the relatively expensive network round-trip to | ||
| // fmsgid is short-circuited for this window. Negative results are not cached. | ||
| const fmsgIDCacheTTL = 30 * time.Second | ||
|
|
||
| type fmsgIDEntry struct { | ||
| expires time.Time | ||
| code int | ||
| acceptingNew bool | ||
| } | ||
|
|
||
| var fmsgIDCache sync.Map // map[string]fmsgIDEntry, key = addr | ||
|
|
||
| // checkFmsgID queries the fmsgid service for a user address. | ||
| // Returns (statusCode, acceptingNew, error). | ||
| // Returns (statusCode, acceptingNew, error). Successful 200 responses are | ||
| // cached for fmsgIDCacheTTL to avoid hammering fmsgid when a browser fires | ||
| // many concurrent requests with the same JWT. | ||
| func checkFmsgID(idURL, addr string) (int, bool, error) { | ||
| cacheKey := idURL + "|" + addr | ||
| if v, ok := fmsgIDCache.Load(cacheKey); ok { | ||
| entry := v.(fmsgIDEntry) | ||
|
Comment on lines
260
to
+262
|
||
| if time.Now().Before(entry.expires) { | ||
| return entry.code, entry.acceptingNew, nil | ||
| } | ||
| fmsgIDCache.Delete(cacheKey) | ||
| } | ||
|
Comment on lines
+243
to
+282
|
||
|
|
||
| url := strings.TrimRight(idURL, "/") + "/fmsgid/" + addr | ||
| resp, err := http.Get(url) //nolint:gosec // URL constructed from trusted config + validated addr | ||
| resp, err := fmsgIDClient.Get(url) //nolint:gosec // URL constructed from trusted config + validated addr | ||
| if err != nil { | ||
|
Comment on lines
290
to
292
|
||
| return 0, false, err | ||
| } | ||
|
|
@@ -244,5 +275,11 @@ func checkFmsgID(idURL, addr string) (int, bool, error) { | |
| if err := decodeJSON(resp.Body, &result); err != nil { | ||
| return http.StatusOK, true, nil // assume accepting if parse fails | ||
| } | ||
|
|
||
| fmsgIDCache.Store(cacheKey, fmsgIDEntry{ | ||
| expires: time.Now().Add(fmsgIDCacheTTL), | ||
| code: http.StatusOK, | ||
| acceptingNew: result.AcceptingNew, | ||
| }) | ||
| return http.StatusOK, result.AcceptingNew, 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.
The inline comment on
fmsgIDCachesays the key isaddr, but the implementation keys byidURL + "|" + addr. Please update the comment to match reality (and ideally clarify the key format) to avoid misleading future maintainers.