using the cache lmao

This commit is contained in:
partisan 2024-05-20 22:14:48 +02:00
parent 18fe1baf0d
commit 3ad4c37d97
2 changed files with 66 additions and 20 deletions

View file

@ -3,6 +3,7 @@ package main
import ( import (
"fmt" "fmt"
"sync" "sync"
"time"
) )
// TextSearchResult represents a single search result item. // TextSearchResult represents a single search result item.
@ -21,16 +22,24 @@ type CacheKey struct {
Lang string Lang string
} }
// CachedItem represents an item stored in the cache with an expiration time.
type CachedItem struct {
Results []TextSearchResult
StoredTime time.Time
}
// ResultsCache is a thread-safe map for caching search results by composite keys. // ResultsCache is a thread-safe map for caching search results by composite keys.
type ResultsCache struct { type ResultsCache struct {
mu sync.Mutex mu sync.Mutex
results map[string][]TextSearchResult results map[string]CachedItem
expiration time.Duration
} }
// NewResultsCache creates a new ResultsCache. // NewResultsCache creates a new ResultsCache with a specified expiration duration.
func NewResultsCache() *ResultsCache { func NewResultsCache(expiration time.Duration) *ResultsCache {
return &ResultsCache{ return &ResultsCache{
results: make(map[string][]TextSearchResult), results: make(map[string]CachedItem),
expiration: expiration,
} }
} }
@ -38,15 +47,29 @@ func NewResultsCache() *ResultsCache {
func (rc *ResultsCache) Get(key CacheKey) ([]TextSearchResult, bool) { func (rc *ResultsCache) Get(key CacheKey) ([]TextSearchResult, bool) {
rc.mu.Lock() rc.mu.Lock()
defer rc.mu.Unlock() defer rc.mu.Unlock()
results, exists := rc.results[rc.keyToString(key)]
return results, exists item, exists := rc.results[rc.keyToString(key)]
if !exists {
return nil, false
}
// Check if the item has expired
if time.Since(item.StoredTime) > rc.expiration {
delete(rc.results, rc.keyToString(key))
return nil, false
}
return item.Results, true
} }
// Set stores the results for a given key in the cache. // Set stores the results for a given key in the cache.
func (rc *ResultsCache) Set(key CacheKey, results []TextSearchResult) { func (rc *ResultsCache) Set(key CacheKey, results []TextSearchResult) {
rc.mu.Lock() rc.mu.Lock()
defer rc.mu.Unlock() defer rc.mu.Unlock()
rc.results[rc.keyToString(key)] = results rc.results[rc.keyToString(key)] = CachedItem{
Results: results,
StoredTime: time.Now(),
}
} }
// keyToString converts a CacheKey to a string representation. // keyToString converts a CacheKey to a string representation.

39
text.go
View file

@ -1,4 +1,3 @@
// text.go
package main package main
import ( import (
@ -14,7 +13,7 @@ import (
var ( var (
debugMode bool debugMode bool
resultsCache = NewResultsCache() resultsCache = NewResultsCache(6 * time.Hour) // Cache with 6-hour expiration
) )
func init() { func init() {
@ -27,21 +26,45 @@ func HandleTextSearch(w http.ResponseWriter, query, safe, lang string, page int)
const resultsPerPage = 10 const resultsPerPage = 10
cacheKey := CacheKey{Query: query, Page: page, Safe: safe, Lang: lang} cacheKey := CacheKey{Query: query, Page: page, Safe: safe, Lang: lang}
cacheChan := make(chan []TextSearchResult)
var combinedResults []TextSearchResult
var fromCache bool
// Try to get results from cache go func() {
combinedResults, exists := resultsCache.Get(cacheKey) results, exists := resultsCache.Get(cacheKey)
if !exists { if exists {
// Fetch results for the current page log.Println("Cache hit")
cacheChan <- results
} else {
log.Println("Cache miss")
cacheChan <- nil
}
}()
select {
case combinedResults = <-cacheChan:
if combinedResults != nil {
fromCache = true
} else {
combinedResults = fetchAndCacheResults(query, safe, lang, page, resultsPerPage)
resultsCache.Set(cacheKey, combinedResults)
}
case <-time.After(2 * time.Second):
log.Println("Cache check timeout")
combinedResults = fetchAndCacheResults(query, safe, lang, page, resultsPerPage) combinedResults = fetchAndCacheResults(query, safe, lang, page, resultsPerPage)
resultsCache.Set(cacheKey, combinedResults) resultsCache.Set(cacheKey, combinedResults)
} }
// Pre-fetch and cache results for the next page // Only pre-fetch and cache results for the next page if we fetched new results
if !fromCache {
go func() {
nextPageResults := fetchAndCacheResults(query, safe, lang, page+1, resultsPerPage) nextPageResults := fetchAndCacheResults(query, safe, lang, page+1, resultsPerPage)
resultsCache.Set(CacheKey{Query: query, Page: page + 1, Safe: safe, Lang: lang}, nextPageResults) resultsCache.Set(CacheKey{Query: query, Page: page + 1, Safe: safe, Lang: lang}, nextPageResults)
}()
}
hasPrevPage := page > 1 hasPrevPage := page > 1
hasNextPage := len(nextPageResults) > 0 hasNextPage := len(combinedResults) == resultsPerPage
displayResults(w, combinedResults, query, lang, time.Since(startTime).Seconds(), page, hasPrevPage, hasNextPage) displayResults(w, combinedResults, query, lang, time.Since(startTime).Seconds(), page, hasPrevPage, hasNextPage)
} }