using the cache lmao
This commit is contained in:
parent
d5bbfe118d
commit
bc85d7d4a2
2 changed files with 66 additions and 20 deletions
37
cache.go
37
cache.go
|
@ -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
39
text.go
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue