Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
41e766e
feat: implement caching service with Redis integration
sundayonah Jan 21, 2025
64ebee8
feat: update Redis configuration to use centralized config management
sundayonah Jan 22, 2025
27b22f8
feat: enhance caching mechanism with configurable durations and versi…
sundayonah Jan 22, 2025
62bfcc6
feat: add redismock dependency and enhance caching logic with improve…
sundayonah Jan 22, 2025
3bb24ef
feat: refactor cache service initialization and make cache durations …
sundayonah Jan 28, 2025
9803137
feat: update cache key generation to use configurable cache version
sundayonah Jan 30, 2025
854148f
feat: update import paths to use aggregator package
sundayonah Jan 30, 2025
9aafd08
feat: update import paths to use protocol package
sundayonah Jan 30, 2025
acc971b
feat: resolve merge conflict in config and routers
sundayonah Mar 12, 2025
fa92eef
Revert "feat: resolve merge conflict in config and routers"
sundayonah Mar 12, 2025
f74f640
feat: update response caching and resolve merge conflicts in config a…
sundayonah Mar 12, 2025
432d27e
chore: merge main into implement-response-caching-for-currency-and-in…
sundayonah Mar 12, 2025
1757dcf
chore: remove duplicate imports in routers
sundayonah Mar 12, 2025
f9bba3b
Merge branch 'main' into implement-response-caching-for-currency-and-…
sundayonah Apr 3, 2025
882c2cb
Merge branch 'main' into implement-response-caching-for-currency-and-…
sundayonah May 16, 2025
f11c979
fix: update code to use correct ServerConfiguration fields
sundayonah May 16, 2025
3e264ef
Merge branch 'main' into implement-response-caching-for-currency-and-…
chibie Sep 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ JWT_REFRESH_LIFESPAN=10080
HMAC_TIMESTAMP_AGE=5
ENVIRONMENT=local # local, staging, production
SENTRY_DSN=
HOST_DOMAIN=http://localhost:8000
CURRENCIES_CACHE_DURATION=24
PUBKEY_CACHE_DURATION=365
INSTITUTIONS_CACHE_DURATION=24

# Database Config
DB_NAME=paycrest
Expand All @@ -25,6 +29,7 @@ REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
CACHE_VERSION=v1

# Order Config
ORDER_FULFILLMENT_VALIDITY=1 # value in minutes
Expand Down
2 changes: 2 additions & 0 deletions config/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type RedisConfiguration struct {
Port string
Password string
DB int
CacheVersion string
}
Comment on lines +15 to 16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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
In config/redis.go around lines 15-16 (and also apply the same change at lines
25-26), the CacheVersion field may be empty which yields keys like ":api:*";
guard against an empty CACHE_VERSION by defaulting it to "v1". Update the struct
initialization or constructor to set CacheVersion = "v1" when the env/config
value is empty and ensure any key-building helper uses CacheVersionFallback :=
CacheVersion; if CacheVersionFallback == "" { CacheVersionFallback = "v1" } so
generated keys never start with a leading colon.


// RedisConfig retrieves the Redis configuration
Expand All @@ -21,6 +22,7 @@ func RedisConfig() RedisConfiguration {
Port: viper.GetString("REDIS_PORT"),
Password: viper.GetString("REDIS_PASSWORD"),
DB: viper.GetInt("REDIS_DB"),
CacheVersion: viper.GetString("CACHE_VERSION"),
}
}

Expand Down
55 changes: 33 additions & 22 deletions config/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,21 @@ import (

// ServerConfiguration type defines the server configurations
type ServerConfiguration struct {
Debug bool
Host string
Port string
Timezone string
AllowedHosts string
Environment string
SentryDSN string
ServerURL string
RateLimitUnauthenticated int
RateLimitAuthenticated int
SlackWebhookURL string
Debug bool
Host string
Port string
Timezone string
AllowedHosts string
Environment string
SentryDSN string
HostDomain string
RateLimitUnauthenticated int
RateLimitAuthenticated int
CurrenciesCacheDuration int
InstitutionsCacheDuration int
PubKeyCacheDuration int
ServerURL string
SlackWebhookURL string
}

// ServerConfig sets the server configuration
Expand All @@ -30,23 +34,30 @@ func ServerConfig() *ServerConfiguration {
viper.SetDefault("ALLOWED_HOSTS", "*")
viper.SetDefault("ENVIRONMENT", "local")
viper.SetDefault("SENTRY_DSN", "")
viper.SetDefault("CURRENCIES_CACHE_DURATION", 24)
viper.SetDefault("INSTITUTIONS_CACHE_DURATION", 24)
viper.SetDefault("PUBKEY_CACHE_DURATION", 365)
viper.SetDefault("RATE_LIMIT_UNAUTHENTICATED", 20)
viper.SetDefault("RATE_LIMIT_AUTHENTICATED", 500)
viper.SetDefault("SLACK_WEBHOOK_URL", "")
viper.SetDefault("SERVER_URL", "")

return &ServerConfiguration{
Debug: viper.GetBool("DEBUG"),
Host: viper.GetString("SERVER_HOST"),
Port: viper.GetString("SERVER_PORT"),
Timezone: viper.GetString("SERVER_TIMEZONE"),
AllowedHosts: viper.GetString("ALLOWED_HOSTS"),
Environment: viper.GetString("ENVIRONMENT"),
SentryDSN: viper.GetString("SENTRY_DSN"),
ServerURL: viper.GetString("SERVER_URL"),
RateLimitUnauthenticated: viper.GetInt("RATE_LIMIT_UNAUTHENTICATED"),
RateLimitAuthenticated: viper.GetInt("RATE_LIMIT_AUTHENTICATED"),
SlackWebhookURL: viper.GetString("SLACK_WEBHOOK_URL"),
Debug: viper.GetBool("DEBUG"),
Host: viper.GetString("SERVER_HOST"),
Port: viper.GetString("SERVER_PORT"),
Timezone: viper.GetString("SERVER_TIMEZONE"),
AllowedHosts: viper.GetString("ALLOWED_HOSTS"),
Environment: viper.GetString("ENVIRONMENT"),
SentryDSN: viper.GetString("SENTRY_DSN"),
ServerURL: viper.GetString("SERVER_URL"),
HostDomain: viper.GetString("HOST_DOMAIN"),
RateLimitUnauthenticated: viper.GetInt("RATE_LIMIT_UNAUTHENTICATED"),
RateLimitAuthenticated: viper.GetInt("RATE_LIMIT_AUTHENTICATED"),
SlackWebhookURL: viper.GetString("SLACK_WEBHOOK_URL"),
CurrenciesCacheDuration: viper.GetInt("CURRENCIES_CACHE_DURATION"),
InstitutionsCacheDuration: viper.GetInt("INSTITUTIONS_CACHE_DURATION"),
PubKeyCacheDuration: viper.GetInt("PUBKEY_CACHE_DURATION"),
}
}

Expand Down
10 changes: 7 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Critical 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@' -C2

Length of output: 6138


Critical upstream vulns present (btcd v0.22.1).
OSV reports GHSA-2chg-86hq-7w38 (CRITICAL), GHSA-27vh-h6mc-q6g8 (HIGH) and GHSA-3jgf-r68h-xfqm (MODERATE). go.mod transitively pulls v0.22.1. Upgrade btcd to ≥0.24.2-beta.rc1 (or ≥0.23.2 to patch the critical issue), or constrain your transitive deps/vendor a patched fork.

🤖 Prompt for AI Agents
In go.mod around line 45, the project pulls github.com/btcsuite/btcd v0.22.1
which has critical/high OSV vulns; update the dependency to a patched release
(bump to >= v0.24.2-beta.rc1 or at minimum >= v0.23.2) by editing go.mod (or
adding a replace directive for transitive deps to force a patched fork), then
run go get github.com/btcsuite/btcd@v0.24.2-beta.rc1 (or @v0.23.2), followed by
go mod tidy (and go mod vendor if you vendor), verify the effective version with
go list -m all | grep btcd, and run CI/tests to ensure nothing breaks.

Expand Down Expand Up @@ -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
Expand Down
25 changes: 17 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBA
github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE=
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI=
github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM=
github.com/anaskhan96/base58check v0.0.0-20181220122047-b05365d494c4 h1:FUDNaUiPOxrVtUmsRSdx7hrvCKXpfQafPpPU0Yh27os=
Expand All @@ -81,10 +83,10 @@ github.com/bits-and-blooms/bitset v1.7.0 h1:YjAGVd3XmtK9ktAbX8Zg2g2PwLIMjGREZJHl
github.com/bits-and-blooms/bitset v1.7.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0=
github.com/bsm/ginkgo/v2 v2.9.5/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c=
github.com/btcsuite/btcd v0.22.1/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y=
Expand Down Expand Up @@ -245,6 +247,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.15.0 h1:nDU5XeOKtB3GEa+uB7GNYwhVKsgjAR7VgKoNB6ryXfw=
github.com/go-playground/validator/v10 v10.15.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw=
github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
Expand Down Expand Up @@ -491,13 +495,19 @@ github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5Vgl
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.25.0 h1:Vw7br2PCDYijJHSfBOWhov+8cAnUf8MfMaIOV323l6Y=
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
github.com/opus-domini/fast-shot v0.10.0 h1:zWbPy6KJZvNs0pUa0erF9TyeDsLZHDVZf4oDHOd6JGY=
github.com/opus-domini/fast-shot v0.10.0/go.mod h1:sg5+f0VviAIIdrv24WLHL6kV7kWs4PsVDbSkr2TPYWw=
github.com/paycrest/tron-wallet v1.0.13 h1:TEkjovg6i2zBTZFMfYpBrwswwnYAy6Q/Vc6g12PZh54=
Expand All @@ -523,8 +533,8 @@ github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdO
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.11.0 h1:5EAgkfkMl659uZPbe9AS2N68a7Cc1TJbPEuGzFuRbyk=
github.com/prometheus/procfs v0.11.0/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY=
github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c=
github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI=
github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
Expand Down Expand Up @@ -568,8 +578,6 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
Expand Down Expand Up @@ -1037,6 +1045,7 @@ gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
Expand Down
17 changes: 16 additions & 1 deletion routers/index.go
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"
Expand All @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Don’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

  • In routers/index.go (around lines 23–26), replace the log.Fatalf on middleware.NewCacheService error with a cacheMW wrapper that returns func(c *gin.Context){c.Next()} when init fails, then use cacheMW(...) instead of cacheService.CacheMiddleware(...) in your routes.
  • After routes are registered (or in your main bootstrap), call go cacheService.WarmCache(context.Background()) to prime the cache asynchronously.
🤖 Prompt for AI Agents
In routers/index.go around lines 23 to 26, replace the current fatal log on
NewCacheService error with a no-op cache middleware function that simply calls
the next handler in Gin's context. Assign this no-op function to cacheMW if
initialization fails, otherwise assign cacheMW as cacheService.CacheMiddleware.
Then update route registrations to use cacheMW instead of
cacheService.CacheMiddleware directly. Finally, after all routes are registered
or in the main application startup, invoke go cacheService.WarmCache with a
background context to asynchronously warm the cache.


route.NoRoute(func(ctx *gin.Context) {
u.APIResponse(ctx, http.StatusNotFound, "error", "Route Not Found", nil)
Expand All @@ -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)

Expand Down
Loading
Loading