Merge demo into main branch #2
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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{})
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user