Merge demo into main branch #2

Merged
illyum merged 10 commits from dev/demo into master 2024-10-30 03:43:55 -06:00
3 changed files with 54 additions and 40 deletions
Showing only changes of commit ecad53b6b1 - Show all commits

View File

@ -28,24 +28,27 @@ func NewAsyncPlayerFetcher(playerName string, cache ICache, retries int, retryDe
} }
} }
// FetchPlayerData fetches the player data asynchronously // FetchPlayerData fetches the player data asynchronously using channels
func (pf *AsyncPlayerFetcher) FetchPlayerData(resultChan chan map[string]interface{}, errorChan chan error) { func (pf *AsyncPlayerFetcher) FetchPlayerData(resultChan chan *FetchedPlayerResult, errorChan chan error) {
go func() { go func() {
cachedData, found := pf.cache.Get(pf.playerName) cachedData, found := pf.cache.Get(pf.playerName)
if found { if found {
resultChan <- cachedData resultChan <- (*FetchedPlayerResult)(cachedData)
return return
} }
var data map[string]interface{} // If not in cache, make request to Mojang API
var player FetchedPlayerResult
for i := 0; i < pf.retries; i++ { for i := 0; i < pf.retries; i++ {
resp, err := pf.makeRequest(pf.playerName) resp, err := pf.makeRequest(pf.playerName)
if err == nil { if err == nil {
defer resp.Body.Close() defer resp.Body.Close()
if err := json.NewDecoder(resp.Body).Decode(&data); err == nil { // Decode the response into FetchedPlayerResult
pf.cache.Set(pf.playerName, data) if err := json.NewDecoder(resp.Body).Decode(&player); err == nil {
// Store the result in the cache and return the data
pf.cache.Set(pf.playerName, (*CacheResult)(&player))
pf.cache.Sync() pf.cache.Sync()
resultChan <- data resultChan <- &player
return return
} }
} }

View File

@ -8,11 +8,16 @@ import (
"sync" "sync"
) )
type CacheResult struct {
UUID string `json:"id"`
Name string `json:"name"`
}
type ICache interface { type ICache interface {
Init() Init()
Load() Load()
Get(key string) (map[string]interface{}, bool) Get(key string) (*CacheResult, bool)
Set(key string, data map[string]interface{}) Set(key string, data *CacheResult)
Save() Save()
Sync() Sync()
Purge() Purge()
@ -21,31 +26,31 @@ type ICache interface {
// MemoryCache implementation // MemoryCache implementation
type MemoryCache struct { type MemoryCache struct {
cache map[string]interface{} cache map[string]*CacheResult
mu sync.RWMutex mu sync.RWMutex
} }
// Init initializes the cache (no-op for MemoryCache) // Init initializes the cache (no-op for MemoryCache)
func (c *MemoryCache) Init() { func (c *MemoryCache) Init() {
c.cache = make(map[string]interface{}) c.cache = make(map[string]*CacheResult)
} }
// Load loads the cache (no-op for MemoryCache) // Load loads the cache (no-op for MemoryCache)
func (c *MemoryCache) Load() {} func (c *MemoryCache) Load() {}
// Get retrieves an item from the cache // Get retrieves an item from the cache
func (c *MemoryCache) Get(key string) (map[string]interface{}, bool) { func (c *MemoryCache) Get(key string) (*CacheResult, bool) {
c.mu.RLock() c.mu.RLock()
defer c.mu.RUnlock() defer c.mu.RUnlock()
value, found := c.cache[key] value, found := c.cache[key]
if !found { if !found {
return nil, false return nil, false
} }
return value.(map[string]interface{}), true return value, true
} }
// Set stores an item in the cache // Set stores an item in the cache
func (c *MemoryCache) Set(key string, data map[string]interface{}) { func (c *MemoryCache) Set(key string, data *CacheResult) {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
c.cache[key] = data c.cache[key] = data
@ -64,19 +69,19 @@ func (c *MemoryCache) Purge() {}
func (c *MemoryCache) Clear() { func (c *MemoryCache) Clear() {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
c.cache = make(map[string]interface{}) c.cache = make(map[string]*CacheResult)
} }
// JsonFileCache implementation // JsonFileCache implementation
type JsonFileCache struct { type JsonFileCache struct {
filename string filename string
cache map[string]interface{} cache map[CacheResult]interface{}
mu sync.RWMutex mu sync.RWMutex
} }
// Init initializes the cache // Init initializes the cache
func (c *JsonFileCache) Init() { func (c *JsonFileCache) Init() {
c.cache = make(map[string]interface{}) c.cache = make(map[CacheResult]interface{})
} }
// Load loads the cache from a JSON file // Load loads the cache from a JSON file
@ -104,21 +109,22 @@ func (c *JsonFileCache) Load() {
} }
// Get retrieves an item from the cache // Get retrieves an item from the cache
func (c *JsonFileCache) Get(key string) (map[string]interface{}, bool) { func (c *JsonFileCache) Get(key string) (*CacheResult, bool) {
c.mu.RLock() //c.mu.RLock()
defer c.mu.RUnlock() //defer c.mu.RUnlock()
value, found := c.cache[key] //value, found := c.cache[key]
if !found { //if !found {
return nil, false // return nil, false
} //}
return value.(map[string]interface{}), true //return value, true
return nil, false
} }
// Set stores an item in the cache // Set stores an item in the cache
func (c *JsonFileCache) Set(key string, data map[string]interface{}) { func (c *JsonFileCache) Set(key string, data *CacheResult) {
c.mu.Lock() //c.mu.Lock()
defer c.mu.Unlock() //defer c.mu.Unlock()
c.cache[key] = data //c.cache[key] = data
} }
// Save saves the cache to a JSON file // Save saves the cache to a JSON file
@ -150,5 +156,5 @@ func (c *JsonFileCache) Purge() {}
func (c *JsonFileCache) Clear() { func (c *JsonFileCache) Clear() {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
c.cache = make(map[string]interface{}) c.cache = make(map[CacheResult]interface{})
} }

View File

@ -16,6 +16,11 @@ type PlayerFetcher struct {
cache ICache cache ICache
} }
type FetchedPlayerResult struct {
UUID string `json:"id"`
Name string `json:"name"`
}
// NewPlayerFetcher creates a new PlayerFetcher with an abstract cache (ICache) // NewPlayerFetcher creates a new PlayerFetcher with an abstract cache (ICache)
func NewPlayerFetcher(playerName string, cache ICache, retries int, retryDelay time.Duration, timeout time.Duration) *PlayerFetcher { func NewPlayerFetcher(playerName string, cache ICache, retries int, retryDelay time.Duration, timeout time.Duration) *PlayerFetcher {
cache.Init() cache.Init()
@ -29,21 +34,21 @@ func NewPlayerFetcher(playerName string, cache ICache, retries int, retryDelay t
} }
// FetchPlayerData fetches the player data synchronously // FetchPlayerData fetches the player data synchronously
func (pf *PlayerFetcher) FetchPlayerData() (map[string]interface{}, error) { func (pf *PlayerFetcher) FetchPlayerData() (*FetchedPlayerResult, error) {
cachedData, found := pf.cache.Get(pf.playerName) //cachedData, found := pf.cache.Get(pf.playerName)
if found { //if found {
return cachedData, nil // return &FetchedPlayerResult{}, nil
} //}
var data map[string]interface{} var player FetchedPlayerResult
for i := 0; i < pf.retries; i++ { for i := 0; i < pf.retries; i++ {
resp, err := pf.makeRequest(pf.playerName) resp, err := pf.makeRequest(pf.playerName)
if err == nil { if err == nil {
defer resp.Body.Close() defer resp.Body.Close()
if err := json.NewDecoder(resp.Body).Decode(&data); err == nil { if err := json.NewDecoder(resp.Body).Decode(&player); err == nil {
pf.cache.Set(pf.playerName, data) // pf.cache.Set(pf.playerName, player)
pf.cache.Sync() // pf.cache.Sync()
return data, nil return &player, nil
} }
} }
time.Sleep(pf.retryDelay) time.Sleep(pf.retryDelay)