2019-11-21 04:03:13 +05:30
|
|
|
package mojangtextures
|
2019-04-21 22:58:58 +05:30
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/elyby/chrly/api/mojang"
|
|
|
|
)
|
|
|
|
|
|
|
|
type inMemoryItem struct {
|
|
|
|
textures *mojang.SignedTexturesResponse
|
|
|
|
timestamp int64
|
|
|
|
}
|
|
|
|
|
2019-11-21 04:03:13 +05:30
|
|
|
type InMemoryTexturesStorage struct {
|
|
|
|
GCPeriod time.Duration
|
|
|
|
Duration time.Duration
|
|
|
|
|
2020-04-30 02:54:41 +05:30
|
|
|
once sync.Once
|
|
|
|
lock sync.RWMutex
|
|
|
|
data map[string]*inMemoryItem
|
|
|
|
done chan struct{}
|
2019-04-21 22:58:58 +05:30
|
|
|
}
|
|
|
|
|
2019-11-21 04:03:13 +05:30
|
|
|
func NewInMemoryTexturesStorage() *InMemoryTexturesStorage {
|
|
|
|
storage := &InMemoryTexturesStorage{
|
|
|
|
GCPeriod: 10 * time.Second,
|
|
|
|
Duration: time.Minute + 10*time.Second,
|
|
|
|
data: make(map[string]*inMemoryItem),
|
2019-04-21 22:58:58 +05:30
|
|
|
}
|
2019-06-19 02:04:16 +05:30
|
|
|
|
|
|
|
return storage
|
2019-04-21 22:58:58 +05:30
|
|
|
}
|
|
|
|
|
2019-11-21 04:03:13 +05:30
|
|
|
func (s *InMemoryTexturesStorage) GetTextures(uuid string) (*mojang.SignedTexturesResponse, error) {
|
2020-01-06 02:15:11 +05:30
|
|
|
s.lock.RLock()
|
|
|
|
defer s.lock.RUnlock()
|
2019-04-21 22:58:58 +05:30
|
|
|
|
|
|
|
item, exists := s.data[uuid]
|
2019-11-21 04:03:13 +05:30
|
|
|
validRange := s.getMinimalNotExpiredTimestamp()
|
2019-05-06 01:36:29 +05:30
|
|
|
if !exists || validRange > item.timestamp {
|
2020-04-28 20:27:51 +05:30
|
|
|
return nil, nil
|
2019-04-21 22:58:58 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
return item.textures, nil
|
|
|
|
}
|
|
|
|
|
2019-11-21 04:03:13 +05:30
|
|
|
func (s *InMemoryTexturesStorage) StoreTextures(uuid string, textures *mojang.SignedTexturesResponse) {
|
2020-04-30 02:54:41 +05:30
|
|
|
s.once.Do(s.start)
|
2019-04-21 22:58:58 +05:30
|
|
|
|
2019-05-06 01:36:29 +05:30
|
|
|
s.lock.Lock()
|
|
|
|
defer s.lock.Unlock()
|
|
|
|
|
|
|
|
s.data[uuid] = &inMemoryItem{
|
2019-04-21 22:58:58 +05:30
|
|
|
textures: textures,
|
2020-04-30 02:54:41 +05:30
|
|
|
timestamp: unixNanoToUnixMicro(time.Now().UnixNano()),
|
2019-04-21 22:58:58 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-30 02:54:41 +05:30
|
|
|
func (s *InMemoryTexturesStorage) start() {
|
|
|
|
s.done = make(chan struct{})
|
|
|
|
ticker := time.NewTicker(s.GCPeriod)
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-s.done:
|
|
|
|
return
|
|
|
|
case <-ticker.C:
|
|
|
|
s.gc()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *InMemoryTexturesStorage) Stop() {
|
|
|
|
close(s.done)
|
|
|
|
}
|
|
|
|
|
2019-11-21 04:03:13 +05:30
|
|
|
func (s *InMemoryTexturesStorage) gc() {
|
2019-04-21 22:58:58 +05:30
|
|
|
s.lock.Lock()
|
|
|
|
defer s.lock.Unlock()
|
|
|
|
|
2019-11-21 04:03:13 +05:30
|
|
|
maxTime := s.getMinimalNotExpiredTimestamp()
|
2019-04-21 22:58:58 +05:30
|
|
|
for uuid, value := range s.data {
|
|
|
|
if maxTime > value.timestamp {
|
|
|
|
delete(s.data, uuid)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-05-06 01:36:29 +05:30
|
|
|
|
2019-11-21 04:03:13 +05:30
|
|
|
func (s *InMemoryTexturesStorage) getMinimalNotExpiredTimestamp() int64 {
|
2020-04-30 02:54:41 +05:30
|
|
|
return unixNanoToUnixMicro(time.Now().Add(s.Duration * time.Duration(-1)).UnixNano())
|
2019-05-06 01:36:29 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
func unixNanoToUnixMicro(unixNano int64) int64 {
|
|
|
|
return unixNano / 10e5
|
|
|
|
}
|