Skip to content

Commit

Permalink
[Backend] Fix Redis related problems
Browse files Browse the repository at this point in the history
- What if caching server is down? -> local cache
- Fix ranked markers in current area (ZMScore in rueidis has to use AsFloatSlice()
  • Loading branch information
Alfex4936 committed Apr 18, 2024
1 parent fc6aa00 commit 495ef8d
Show file tree
Hide file tree
Showing 9 changed files with 134 additions and 43 deletions.
3 changes: 3 additions & 0 deletions backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ require (
github.com/alphadose/haxmap v1.3.1
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02
github.com/go-pdf/fpdf v0.9.0
github.com/gofiber/contrib/fgprof v1.0.0
github.com/google/generative-ai-go v0.10.0
github.com/puzpuzpuz/xsync/v3 v3.1.0
github.com/redis/rueidis v1.0.34
Expand Down Expand Up @@ -66,6 +67,7 @@ require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect
github.com/fasthttp/websocket v1.5.8 // indirect
github.com/felixge/fgprof v0.9.4 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/flosch/pongo2/v6 v6.0.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
Expand All @@ -78,6 +80,7 @@ require (
github.com/gofiber/utils v1.1.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/pprof v0.0.0-20240416155748-26353dc0451f // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/googleapis/gax-go/v2 v2.12.3 // indirect
Expand Down
20 changes: 20 additions & 0 deletions backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02 h1:bXAPYSbdYbS5VTy92NIUbeDI1qyggi+JYh5op9IFlcQ=
github.com/axiomhq/hyperloglog v0.0.0-20240319100328-84253e514e02/go.mod h1:k08r+Yj1PRAmuayFiRK6MYuR5Ve4IuZtTfxErMIh0+c=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/chromedp/cdproto v0.0.0-20230802225258-3cf4e6d46a89/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
github.com/chromedp/chromedp v0.9.2/go.mod h1:LkSXJKONWTCHAfQasKFUZI+mxqS4tZqhmtGzzhLsnLs=
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -74,6 +80,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fasthttp/websocket v1.5.8 h1:k5DpirKkftIF/w1R8ZzjSgARJrs54Je9YJK37DL/Ah8=
github.com/fasthttp/websocket v1.5.8/go.mod h1:d08g8WaT6nnyvg9uMm8K9zMYyDjfKyj3170AtPRuVU0=
github.com/felixge/fgprof v0.9.4 h1:ocDNwMFlnA0NU0zSB3I52xkO4sFXk80VK9lXjLClu88=
github.com/felixge/fgprof v0.9.4/go.mod h1:yKl+ERSa++RYOs32d8K6WEXCB4uXdLls4ZaZPpayhMM=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
Expand All @@ -98,8 +106,13 @@ github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpv
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho=
github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/gofiber/contrib/fgprof v1.0.0 h1:M9fVuwGIycGnrUb93NuYkV4ozyeCQJ9/UxjKNQk8mFk=
github.com/gofiber/contrib/fgprof v1.0.0/go.mod h1:3QZnyP9Tj3zqQdRph077mDPPBGHAAt5pTpqU228k1Ig=
github.com/gofiber/contrib/websocket v1.3.0 h1:XADFAGorer1VJ1bqC4UkCjqS37kwRTV0415+050NrMk=
github.com/gofiber/contrib/websocket v1.3.0/go.mod h1:xguaOzn2ZZ759LavtosEP+rcxIgBEE/rdumPINhR+Xo=
github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM=
Expand Down Expand Up @@ -144,6 +157,9 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20240416155748-26353dc0451f h1:WpZiq8iqvGjJ3m3wzAVKL6+0vz7VkE79iSy9GII00II=
github.com/google/pprof v0.0.0-20240416155748-26353dc0451f/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
Expand All @@ -156,6 +172,7 @@ github.com/googleapis/gax-go/v2 v2.12.3/go.mod h1:AKloxT6GtNbaLm8QTNSidHUVsHYcBH
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
Expand All @@ -176,6 +193,7 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/loov/hrtime v1.0.3 h1:LiWKU3B9skJwRPUf0Urs9+0+OE3TxdMuiRPOTwR0gcU=
Expand All @@ -198,6 +216,7 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
Expand Down Expand Up @@ -353,6 +372,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand Down
7 changes: 2 additions & 5 deletions backend/handlers/marker_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,14 +515,11 @@ func getFacilitiesHandler(c *fiber.Ctx) error {
var facilities []models.Facility
cacheKey := fmt.Sprintf("facilities:%d", markerID)
cachedFacilities, cacheErr := services.GetCacheEntry[[]models.Facility](cacheKey)
if cacheErr != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to access cache"})
}

if cachedFacilities != nil {
if cacheErr == nil && cachedFacilities != nil {
c.Append("X-Cache", "hit")
// Cache hit, return cached facilities
return c.JSON(cachedFacilities)

}

facilities, err = services.GetFacilitiesByMarkerID(markerID)
Expand Down
2 changes: 1 addition & 1 deletion backend/handlers/marker_location_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func getCurrentAreaMarkerRankingHandler(c *fiber.Ctx) error {

markers, err := services.FindRankedMarkersInCurrentArea(lat, long, currentAreaDistance, limit)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to retrieve markers"})
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{"error": "Failed to retrieve markers " + err.Error()})
}

if markers == nil {
Expand Down
64 changes: 55 additions & 9 deletions backend/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"github.com/Alfex4936/tzf"
"github.com/goccy/go-json"
"github.com/gofiber/contrib/fgprof"
"github.com/gofiber/contrib/websocket"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress"
Expand All @@ -32,6 +33,7 @@ import (
"github.com/gofiber/fiber/v2/middleware/limiter"
"github.com/gofiber/fiber/v2/middleware/monitor"
"github.com/gofiber/fiber/v2/middleware/pprof"

"github.com/gofiber/fiber/v2/middleware/requestid"
"github.com/gofiber/swagger"
"github.com/redis/rueidis"
Expand Down Expand Up @@ -231,6 +233,7 @@ func setUpMiddlewares(app *fiber.App) {
}))

app.Use(pprof.New())
app.Use(fgprof.New())

app.Use(compress.New(compress.Config{
// Next: func(c *fiber.Ctx) bool {
Expand Down Expand Up @@ -296,17 +299,17 @@ func setUpExternalConnections() {

// Initialize redis
rdb, err := rueidis.NewClient(rueidis.ClientOption{
InitAddress: []string{os.Getenv("REDIS_HOST") + ":" + os.Getenv("REDIS_PORT")},
Username: os.Getenv("REDIS_USERNAME"),
Password: os.Getenv("REDIS_PASSWORD"),
DisableCache: true, // dragonfly doesn't support CACHING command
// SelectDB: 0,

InitAddress: []string{os.Getenv("REDIS_HOST") + ":" + os.Getenv("REDIS_PORT")},
Username: os.Getenv("REDIS_USERNAME"),
Password: os.Getenv("REDIS_PASSWORD"),
DisableCache: true, // dragonfly doesn't support CACHING command
SelectDB: 0,
ForceSingleClient: true,
// PoolSize: 10 * runtime.GOMAXPROCS(0),
// MaxRetries: 5,
PipelineMultiplex: 2, // Default is typically sufficient
BlockingPoolSize: 5,
TLSConfig: &tls.Config{InsecureSkipVerify: true},
// PipelineMultiplex: 2, // Default is typically sufficient
// BlockingPoolSize: 5,
TLSConfig: &tls.Config{InsecureSkipVerify: true},
})
if err != nil {
log.Fatalf("Error connecting to Redis: %v", err)
Expand All @@ -322,6 +325,9 @@ func setUpExternalConnections() {
log.Fatalf("Error pinging to Redis: %v", err)
}

// Start the Redis health check routine
go redisHealthCheck(rdb)

if os.Getenv("DEPLOYMENT") == "production" {
// Flush the Redis database to clear all keys
err := rdb.Do(ctx, rdb.B().Flushall().Build()).Error()
Expand Down Expand Up @@ -392,3 +398,43 @@ func countAPIs(app *fiber.App) int {
}
return numAPIs
}

func redisHealthCheck(rdb rueidis.Client) {
ticker := time.NewTicker(10 * time.Minute)
defer ticker.Stop()

for t := range ticker.C {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
err := rdb.Do(ctx, rdb.B().Ping().Build()).Error()
cancel()

if err != nil {
log.Printf("Redis ping failed at %v: %v", t, err)
// Attempt to reconnect
reconnectRedis(rdb)
} else {
log.Printf("Redis ping success at %v", t)
}
}
}
func reconnectRedis(rdb rueidis.Client) {
for i := 0; i < 3; i++ { // Try reconnecting 3 times
time.Sleep(time.Duration(i+1) * time.Second) // Exponential back-off strategy
rdb.Close()
rdb, err := rueidis.NewClient(rueidis.ClientOption{
InitAddress: []string{os.Getenv("REDIS_HOST") + ":" + os.Getenv("REDIS_PORT")},
Username: os.Getenv("REDIS_USERNAME"),
Password: os.Getenv("REDIS_PASSWORD"),
DisableCache: true,
TLSConfig: &tls.Config{InsecureSkipVerify: true},
})
if err == nil {
services.RedisStore = rdb
log.Println("Reconnected to Redis successfully")
return
}
log.Printf("Failed to reconnect to Redis: %v", err)
}

log.Fatal("Failed to reconnect to Redis after several attempts")
}
2 changes: 2 additions & 0 deletions backend/middlewares/auth_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ func AdminOnly(c *fiber.Ctx) error {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{"error": "Access denied"})
}

c.Locals("isAdmin", true)

// Proceed to the next handler if the user is an admin
return c.Next()
}
Expand Down
38 changes: 26 additions & 12 deletions backend/services/marker_location_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,22 +93,36 @@ func FindRankedMarkersInCurrentArea(lat, long float64, distance, limit int) ([]d
markerIDs[i] = strconv.Itoa(marker.MarkerID)
}

// Fetch scores for all markers in one Redis call
RedisStore.Do(context.Background(), RedisStore.B().Zmscore().Key("marker_clicks").Member(markerIDs...).Build())

scores, err := RedisStore.Do(context.Background(), RedisStore.B().Zmscore().Key("marker_clicks").Member(markerIDs...).Build()).AsZScores()
if err != nil {
return nil, err
}

rankedMarkers := make([]dto.MarkerWithDistance, 0, len(scores))
for i, zscore := range scores {
if zscore.Score > float64(MIN_CLICK_RANK) {
nearbyMarkers[i].Distance = zscore.Score // Repurpose Distance to store score
ctx := context.Background()
floatMin := float64(MIN_CLICK_RANK)

result, _ := RedisStore.Do(ctx, RedisStore.B().Zmscore().Key("marker_clicks").Member(markerIDs...).Build()).AsFloatSlice()
rankedMarkers := make([]dto.MarkerWithDistance, 0, len(result))
for i, score := range result {
if score > floatMin { // Include markers with score > minScore
nearbyMarkers[i].Distance = score
rankedMarkers = append(rankedMarkers, nearbyMarkers[i])
}
}

// rankedMarkers := make([]dto.MarkerWithDistance, 0)
// for i, marker := range nearbyMarkers {
// // Build the command to fetch the score for a single member
// scoreCmd := RedisStore.B().Zscore().Key("marker_clicks").Member(markerIDs[i]).Build()
// result := RedisStore.Do(ctx, scoreCmd)

// // Try to parse the score from the result
// score, err := result.AsFloat64()
// if err != nil {
// continue
// }

// if score > floatMin { // Include markers with score > minScore
// marker.Distance = score
// rankedMarkers = append(rankedMarkers, marker)
// }
// }

if len(rankedMarkers) == 0 {
return nil, nil // Return nil to signify no ranked markers
}
Expand Down
39 changes: 24 additions & 15 deletions backend/services/marker_rank_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/axiomhq/hyperloglog"
csmap "github.com/mhmtszr/concurrent-swiss-map"
"github.com/redis/rueidis"
"github.com/zeebo/xxh3"

"chulbong-kr/database"
Expand Down Expand Up @@ -159,6 +160,7 @@ func GetTopMarkers(limit int) []dto.MarkerSimpleWithAddr {
markerIDs := make([]interface{}, len(markerScores))
for i, markerScore := range markerScores {
markerIDs[i] = markerScore.Member // Directly use string ID to avoid unnecessary conversions.
log.Printf("🤣 Marker id: %s and score: %f", markerScore.Member, markerScore.Score)
}

// Query to retrieve markers by a set of IDs in a single SQL call.
Expand Down Expand Up @@ -190,8 +192,6 @@ func RemoveMarkerClick(markerID int) error {
member := fmt.Sprintf("%d", markerID)

// Remove the marker from the "marker_clicks" sorted set
RedisStore.Do(ctx, RedisStore.B().Zrem().Key("marker_clicks").Member(member).Build())

err := RedisStore.Do(ctx, RedisStore.B().Zrem().Key("marker_clicks").Member(member).Build()).Error()
if err != nil {
log.Printf("Error removing marker click: %v", err)
Expand Down Expand Up @@ -224,21 +224,30 @@ func ResetAndRandomizeClickRanking() {

selectedMarkers := markers[:numMarkers]

ctx := context.Background()
// atomic
RedisStore.Dedicated(func(c rueidis.DedicatedClient) error {
// Start a transaction
ctx := context.Background()
c.Do(ctx, c.B().Multi().Build())

// Reset the "marker_clicks" sorted set in Redis
RedisStore.Do(ctx, RedisStore.B().Del().Key("marker_clicks").Build())
// Delete the existing "marker_clicks" sorted set
c.Do(ctx, c.B().Del().Key("marker_clicks").Build())

// Re-populate "marker_clicks" with the selected markers
// Prepare the ZADD command
zaddCmd := RedisStore.B().Zadd().Key("marker_clicks").ScoreMember()
for _, marker := range selectedMarkers {
score := float64(10 + rand.IntN(6)) // Random score between 10 and 15
zaddCmd = zaddCmd.ScoreMember(score, fmt.Sprintf("%d", marker.MarkerID))
}
if err := RedisStore.Do(ctx, zaddCmd.Build()).Error(); err != nil {
log.Printf("Error adding markers to sorted set: %v", err)
}
// Re-populate "marker_clicks" with the selected markers
zaddCmd := c.B().Zadd().Key("marker_clicks").ScoreMember()
for _, marker := range selectedMarkers {
score := float64(10 + rand.IntN(6)) // Random score between 10 and 15
zaddCmd = zaddCmd.ScoreMember(score, fmt.Sprintf("%d", marker.MarkerID))
}
c.Do(ctx, zaddCmd.Build())

// Execute the transaction
if err := c.Do(ctx, c.B().Exec().Build()).Error(); err != nil {
log.Printf("Transaction failed: %v", err)
return err
}
return nil
})

log.Printf("%d markers were randomly selected and added to Redis ranking.", numMarkers)
}
2 changes: 1 addition & 1 deletion backend/services/redis_services.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func SetCacheEntry[T any](key string, value T, expiration time.Duration) error {
Value(rueidis.BinaryString(jsonValue)).
Nx().
Ex(expiration).
Build() // No need to Pin unless reusing
Build()

// Execute the SET command
if err := RedisStore.Do(ctx, setCmd).Error(); err != nil {
Expand Down

0 comments on commit 495ef8d

Please sign in to comment.