-
Notifications
You must be signed in to change notification settings - Fork 22
Implement Response Caching for Currency and Institution Endpoints #394
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
base: main
Are you sure you want to change the base?
Changes from all commits
41e766e
64ebee8
27b22f8
62bfcc6
3bb24ef
9803137
854148f
9aafd08
acc971b
fa92eef
f74f640
432d27e
1757dcf
f9bba3b
882c2cb
f11c979
3e264ef
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 |
|---|---|---|
|
|
@@ -6,19 +6,22 @@ toolchain go1.23.6 | |
|
|
||
| require ( | ||
| github.com/JGLTechnologies/gin-rate-limit v1.5.4 | ||
| github.com/alicebob/miniredis/v2 v2.34.0 | ||
| github.com/anaskhan96/base58check v0.0.0-20181220122047-b05365d494c4 | ||
| github.com/btcsuite/btcd/btcec/v2 v2.3.2 | ||
| github.com/chadsr/logrus-sentry v0.4.1 | ||
| github.com/getsentry/sentry-go v0.13.0 | ||
| github.com/gin-gonic/gin v1.9.1 | ||
| github.com/go-co-op/gocron v1.35.0 | ||
| github.com/go-redis/redismock/v9 v9.2.0 | ||
| github.com/golang-jwt/jwt/v5 v5.0.0 | ||
| github.com/jarcoal/httpmock v1.3.1 | ||
| github.com/mailgun/mailgun-go/v3 v3.6.4 | ||
| github.com/mattn/go-sqlite3 v1.14.16 | ||
| github.com/opus-domini/fast-shot v0.10.0 | ||
| github.com/paycrest/tron-wallet v1.0.13 | ||
| github.com/redis/go-redis/v9 v9.1.0 | ||
| github.com/prometheus/client_golang v1.16.0 | ||
| github.com/redis/go-redis/v9 v9.2.0 | ||
| github.com/sendgrid/sendgrid-go v3.14.0+incompatible | ||
| github.com/sirupsen/logrus v1.9.3 | ||
| github.com/spf13/viper v1.16.0 | ||
|
|
@@ -35,6 +38,8 @@ require ( | |
| github.com/Microsoft/go-winio v0.6.1 // indirect | ||
| github.com/alicebob/miniredis/v2 v2.35.0 // indirect | ||
| github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect | ||
| github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect | ||
| github.com/beorn7/perks v1.0.1 // indirect | ||
| github.com/bits-and-blooms/bitset v1.7.0 // indirect | ||
| github.com/bmatcuk/doublestar v1.3.4 // indirect | ||
| github.com/btcsuite/btcd v0.22.1 // indirect | ||
|
Contributor
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. 🧩 Analysis chainCritical upstream vulns present (btcd). OSV flags multiple critical advisories for github.com/btcsuite/btcd v0.22.1 (indirect). Not introduced by this PR, but it’s a material risk. Consider upgrading or constraining transitive deps pulling btcd, or vendor a patched version. Run to list advisories and reverse-deps: 🏁 Script executed: #!/bin/bash
# Show advisories
gh api graphql -f query='
{ securityVulnerabilities(first: 20, ecosystem: GO, package: "github.com/btcsuite/btcd") {
nodes { advisory { summary severity permalink } vulnerableVersionRange firstPatchedVersion { identifier } }
}
}
'
# Who pulls btcd in module graph
go mod graph | rg -nP 'btcsuite/btcd@' -C2Length of output: 6138 Critical upstream vulns present (btcd v0.22.1). 🤖 Prompt for AI Agents |
||
|
|
@@ -69,17 +74,16 @@ require ( | |
| github.com/klauspost/compress v1.16.7 // indirect | ||
| github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 // indirect | ||
| github.com/mattn/go-runewidth v0.0.14 // indirect | ||
| github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect | ||
| github.com/mmcloughlin/addchain v0.4.0 // indirect | ||
| github.com/mr-tron/base58 v1.2.0 // indirect | ||
| github.com/pkg/errors v0.9.1 // indirect | ||
| github.com/pmezard/go-difflib v1.0.0 // indirect | ||
| github.com/prometheus/client_golang v1.16.0 // indirect | ||
| github.com/prometheus/client_model v0.4.0 // indirect | ||
| github.com/prometheus/common v0.44.0 // indirect | ||
| github.com/prometheus/procfs v0.11.0 // indirect | ||
| github.com/rivo/uniseg v0.4.4 // indirect | ||
| github.com/robfig/cron/v3 v3.0.1 // indirect | ||
| github.com/rogpeppe/go-internal v1.10.0 // indirect | ||
| github.com/sendgrid/rest v2.6.9+incompatible // indirect | ||
| github.com/sergi/go-diff v1.3.1 // indirect | ||
| github.com/shengdoushi/base58 v1.0.0 // indirect | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,12 @@ | ||
| package routers | ||
|
|
||
| import ( | ||
| "log" | ||
| "net/http" | ||
| "time" | ||
|
|
||
| "github.com/gin-gonic/gin" | ||
| "github.com/paycrest/aggregator/config" | ||
| "github.com/paycrest/aggregator/controllers" | ||
| "github.com/paycrest/aggregator/controllers/accounts" | ||
| "github.com/paycrest/aggregator/controllers/provider" | ||
|
|
@@ -14,6 +17,13 @@ import ( | |
|
|
||
| // RegisterRoutes add all routing list here automatically get main router | ||
| func RegisterRoutes(route *gin.Engine) { | ||
| conf := config.RedisConfig() | ||
| serverConf := config.ServerConfig() | ||
|
|
||
| cacheService, err := middleware.NewCacheService(conf) | ||
| if err != nil { | ||
| log.Fatalf("Failed to initialize cache: %v", err) | ||
| } | ||
|
Comment on lines
+23
to
+26
Contributor
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. 🧩 Analysis chainDon’t crash the app if Redis is unavailable; fall back to pass‑through. Fatal here violates “gracefully handle cache failures by falling back to direct responses”. Provide a no‑op middleware when cache init fails. Apply: - cacheService, err := middleware.NewCacheService(conf)
- if err != nil {
- log.Fatalf("Failed to initialize cache: %v", err)
- }
+ cacheService, err := middleware.NewCacheService(conf)
+ var cacheMW func(time.Duration) gin.HandlerFunc
+ if err != nil {
+ log.Printf("Failed to initialize cache: %v. Proceeding without caching.", err)
+ cacheMW = func(_ time.Duration) gin.HandlerFunc {
+ return func(c *gin.Context) { c.Next() }
+ }
+ } else {
+ cacheMW = cacheService.CacheMiddleware
+ }And use cacheMW: - cacheService.CacheMiddleware(time.Duration(serverConf.CurrenciesCacheDuration)*time.Hour),
+ cacheMW(time.Duration(serverConf.CurrenciesCacheDuration)*time.Hour),- cacheService.CacheMiddleware(time.Duration(serverConf.InstitutionsCacheDuration)*time.Hour),
+ cacheMW(time.Duration(serverConf.InstitutionsCacheDuration)*time.Hour),- v1.GET("pubkey",
- cacheService.CacheMiddleware(time.Duration(serverConf.PubKeyCacheDuration)*24*time.Hour),
- ctrl.GetAggregatorPublicKey,
- )
+ v1.GET("pubkey",
+ cacheMW(time.Duration(serverConf.PubKeyCacheDuration)*24*time.Hour),
+ ctrl.GetAggregatorPublicKey,
+ )Also, where is WarmCache invoked on startup? If not yet wired, consider calling it after routes are registered (non-blocking), or from main bootstrap. Also applies to: 42-55 🏁 Script executed: #!/bin/bash
set -e
# Locate routers/index.go
echo "Finding routers/index.go path..."
ROUTERS_FILE=$(rg -l "middleware.NewCacheService" -g "*.go")
echo "routers/index.go located at: $ROUTERS_FILE"
echo "Printing first 100 lines of routers/index.go..."
sed -n '1,100p' "$ROUTERS_FILE"
# Find NewCacheService implementation
echo "Searching for NewCacheService definition..."
SERVICE_FILE=$(rg -l "func NewCacheService" -g "*.go")
echo "NewCacheService defined in: $SERVICE_FILE"
echo "Printing the implementation of NewCacheService..."
sed -n '1,200p' "$SERVICE_FILE"Length of output: 9776 Use no-op cache middleware on Redis failure and invoke WarmCache on startup
🤖 Prompt for AI Agents |
||
|
|
||
| route.NoRoute(func(ctx *gin.Context) { | ||
| u.APIResponse(ctx, http.StatusNotFound, "error", "Route Not Found", nil) | ||
|
|
@@ -31,15 +41,20 @@ func RegisterRoutes(route *gin.Engine) { | |
|
|
||
| v1.GET( | ||
| "currencies", | ||
| cacheService.CacheMiddleware(time.Duration(serverConf.CurrenciesCacheDuration)*time.Hour), | ||
| ctrl.GetFiatCurrencies, | ||
| ) | ||
| v1.GET( | ||
| "institutions/:currency_code", | ||
| cacheService.CacheMiddleware(time.Duration(serverConf.InstitutionsCacheDuration)*time.Hour), | ||
| ctrl.GetInstitutionsByCurrency, | ||
| ) | ||
| v1.GET("pubkey", | ||
| cacheService.CacheMiddleware(time.Duration(serverConf.PubKeyCacheDuration)*24*time.Hour), | ||
| ctrl.GetAggregatorPublicKey, | ||
| ) | ||
| v1.GET("tokens", ctrl.GetSupportedTokens) | ||
| v1.GET("rates/:token/:amount/:fiat", ctrl.GetTokenRate) | ||
| v1.GET("pubkey", ctrl.GetAggregatorPublicKey) | ||
| v1.POST("verify-account", ctrl.VerifyAccount) | ||
| v1.GET("orders/:chain_id/:id", ctrl.GetLockPaymentOrderStatus) | ||
|
|
||
|
|
||
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.
Guard against empty CACHE_VERSION to avoid “:api:*” keys.
If CACHE_VERSION is unset, keys become “:api:*”, which breaks consistency and tests. Default to "v1".
Apply:
type RedisConfiguration struct { Host string Port string Password string DB int - CacheVersion string + CacheVersion string } func RedisConfig() RedisConfiguration { - return RedisConfiguration{ + cv := viper.GetString("CACHE_VERSION") + if cv == "" { + cv = "v1" + } + return RedisConfiguration{ Host: viper.GetString("REDIS_HOST"), Port: viper.GetString("REDIS_PORT"), Password: viper.GetString("REDIS_PASSWORD"), DB: viper.GetInt("REDIS_DB"), - CacheVersion: viper.GetString("CACHE_VERSION"), + CacheVersion: cv, } }Also applies to: 25-26
🤖 Prompt for AI Agents