Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,7 @@
## 2026-05-27 - Reducing Allocations with bufio.Scanner
**Learning:** Parsing large embedded strings (like blocklists) using `strings.Split` creates a large slice of strings that persists until the loop finishes. This is inefficient for one-time map population.
**Action:** Use `bufio.Scanner` with `strings.NewReader` to process the string line-by-line. This minimizes temporary allocations and is significantly more memory-efficient for large text datasets.

## 2026-06-11 - Optimizing Redis Pipeline HGetAll to HGet
**Learning:** When using Redis pipelines to batch retrieve session data, using `HGetAll` is inefficient if only a single field (like "status") is needed. `HGetAll` fetches all fields and allocates a full map in memory, which is slow and memory-intensive, especially for large datasets.
**Action:** Replace `HGetAll` with `HGet` inside the pipeline when only a specific field is required. This drastically reduces network I/O, Redis CPU overhead, and Go memory allocations. Update corresponding types (e.g., `MapStringStringCmd` to `StringCmd`) and validation logic accordingly.
20 changes: 10 additions & 10 deletions internal/core/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,19 @@ func HasActiveSessions(ip string) bool {
return false
}

// ⚡ Bolt optimization: Batch HGetAll requests to avoid N+1 queries.
// ⚡ Bolt optimization: Batch HGet requests to avoid N+1 queries.
pipe := TokenDB.Pipeline()
cmds := make(map[string]*redis.MapStringStringCmd, len(tokens))
cmds := make(map[string]*redis.StringCmd, len(tokens))
for _, token := range tokens {
cmds[token] = pipe.HGetAll(Ctx, "X-rauth-authtoken="+token)
cmds[token] = pipe.HGet(Ctx, "X-rauth-authtoken="+token, "status")
}
_, _ = pipe.Exec(Ctx)

var stale []interface{}
hasActive := false
for _, token := range tokens {
data, err := cmds[token].Result()
if err == nil && len(data) > 0 && data["status"] == "valid" {
status, err := cmds[token].Result()
if err == nil && status == "valid" {
hasActive = true
} else {
stale = append(stale, token)
Expand Down Expand Up @@ -197,18 +197,18 @@ func reconcileIndexSets(pattern string) int64 {
continue
}

// ⚡ Bolt optimization: Batch HGetAll requests in a pipeline and remove stale tokens variadically.
// ⚡ Bolt optimization: Batch HGet requests in a pipeline and remove stale tokens variadically.
pipe := TokenDB.Pipeline()
cmds := make(map[string]*redis.MapStringStringCmd, len(tokens))
cmds := make(map[string]*redis.StringCmd, len(tokens))
for _, token := range tokens {
cmds[token] = pipe.HGetAll(Ctx, "X-rauth-authtoken="+token)
cmds[token] = pipe.HGet(Ctx, "X-rauth-authtoken="+token, "status")
}
_, _ = pipe.Exec(Ctx)

var stale []interface{}
for _, token := range tokens {
data, err := cmds[token].Result()
if err == nil && len(data) > 0 && data["status"] == "valid" {
status, err := cmds[token].Result()
if err == nil && status == "valid" {
live++
} else {
stale = append(stale, token)
Expand Down
Loading