2020-06-03 15:21:28 +00:00
|
|
|
package repository
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-06-12 16:26:48 +00:00
|
|
|
"encoding/json"
|
2020-06-03 15:21:28 +00:00
|
|
|
"fmt"
|
|
|
|
"time"
|
|
|
|
|
2020-06-12 16:26:48 +00:00
|
|
|
"github.com/go-redis/redis/v8"
|
|
|
|
|
2020-06-03 15:21:28 +00:00
|
|
|
"github.com/tribalwarshelp/api/ennoblement"
|
|
|
|
|
|
|
|
"github.com/go-pg/pg/v10"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/tribalwarshelp/shared/models"
|
|
|
|
)
|
|
|
|
|
2020-06-12 16:26:48 +00:00
|
|
|
var (
|
|
|
|
cacheKey = "ennoblements-%s"
|
|
|
|
expiration = time.Second * 15
|
|
|
|
)
|
|
|
|
|
2020-06-03 15:21:28 +00:00
|
|
|
type pgRepository struct {
|
|
|
|
*pg.DB
|
2020-06-12 16:26:48 +00:00
|
|
|
cache redis.UniversalClient
|
2020-06-03 15:21:28 +00:00
|
|
|
}
|
|
|
|
|
2020-06-12 16:26:48 +00:00
|
|
|
func NewPGRepository(db *pg.DB, cache redis.UniversalClient) ennoblement.Repository {
|
|
|
|
return &pgRepository{db, cache}
|
2020-06-03 15:21:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (repo *pgRepository) Fetch(ctx context.Context, server string) ([]*models.Ennoblement, error) {
|
2020-06-12 16:26:48 +00:00
|
|
|
if ennoblements, loaded := repo.loadEnnoblementsFromCache(server); loaded {
|
|
|
|
return ennoblements, nil
|
|
|
|
}
|
|
|
|
|
2020-06-03 15:21:28 +00:00
|
|
|
s := &models.Server{}
|
|
|
|
if err := repo.Model(s).Where("key = ?", server).Relation("LangVersion").Select(); err != nil {
|
|
|
|
if err == pg.ErrNoRows {
|
|
|
|
return nil, fmt.Errorf("Server not found")
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil, errors.Wrap(err, "Internal server error")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.Status == models.ServerStatusClosed {
|
|
|
|
return nil, fmt.Errorf("Server is " + models.ServerStatusClosed.String())
|
|
|
|
}
|
|
|
|
|
|
|
|
url := "https://" + s.Key + "." + s.LangVersion.Host +
|
|
|
|
fmt.Sprintf(ennoblement.EndpointGetConquer, time.Now().Add(-1*time.Hour).Unix())
|
|
|
|
lines, err := getCSVData(url)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.Wrap(err, "Cannot fetch ennoblements")
|
|
|
|
}
|
|
|
|
|
|
|
|
e := []*models.Ennoblement{}
|
2020-06-07 14:53:32 +00:00
|
|
|
lineParser, err := newLineParser(s.LangVersion.Timezone)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-06-03 15:21:28 +00:00
|
|
|
for _, line := range lines {
|
2020-06-07 14:53:32 +00:00
|
|
|
ennoblement, err := lineParser.parse(line)
|
2020-06-03 15:21:28 +00:00
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
e = append(e, ennoblement)
|
|
|
|
}
|
|
|
|
|
2020-06-12 16:26:48 +00:00
|
|
|
go repo.cacheEnnoblements(server, e)
|
|
|
|
|
2020-06-03 15:21:28 +00:00
|
|
|
return e, nil
|
|
|
|
}
|
2020-06-12 16:26:48 +00:00
|
|
|
|
|
|
|
func (repo *pgRepository) loadEnnoblementsFromCache(server string) ([]*models.Ennoblement, bool) {
|
|
|
|
ennoblementsJSON, err := repo.cache.Get(context.Background(), fmt.Sprintf(cacheKey, server)).Result()
|
|
|
|
if err != nil || ennoblementsJSON == "" {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
ennoblements := []*models.Ennoblement{}
|
|
|
|
if json.Unmarshal([]byte(ennoblementsJSON), &ennoblements) != nil {
|
|
|
|
return nil, false
|
|
|
|
}
|
|
|
|
return ennoblements, true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (repo *pgRepository) cacheEnnoblements(server string, ennoblements []*models.Ennoblement) error {
|
|
|
|
ennoblementsJSON, err := json.Marshal(&ennoblements)
|
|
|
|
if err != nil {
|
|
|
|
return errors.Wrap(err, "cacheEnnoblements")
|
|
|
|
}
|
|
|
|
if err := repo.cache.Set(context.Background(), fmt.Sprintf(cacheKey, server), ennoblementsJSON, expiration).Err(); err != nil {
|
|
|
|
return errors.Wrap(err, "cacheEnnoblements")
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|