Compare commits

..

6 Commits
4.2.1 ... 4.2.3

Author SHA1 Message Date
ErickSkrauch
334e60ff2f Prepare 4.2.3 release 2019-10-03 01:26:34 +03:00
ErickSkrauch
6d6d0e4b79 Decrease queue batch size. Log all 400 response from the Mojang's API. Resolves #10. 2019-10-03 01:24:25 +03:00
ErickSkrauch
0cfed45b64 Prepare 4.2.2 release 2019-06-19 01:02:41 +03:00
ErickSkrauch
f872fe4698 Fix race condition, introduced in the previous commit 2019-06-19 00:56:09 +03:00
ErickSkrauch
5b4761e4e5 Fixes #9. Start GC loop for in-memory textures cache. 2019-06-18 23:34:16 +03:00
ErickSkrauch
e81ca1520d Add codecov shield [skip ci] 2019-05-06 17:26:55 +03:00
6 changed files with 46 additions and 20 deletions

View File

@@ -4,7 +4,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] ## [Unreleased] - xxxx-xx-xx
## [4.2.3] - 2019-10-03
### Changed
- Mojang's textures queue batch size [reduced to 10](https://wiki.vg/index.php?title=Mojang_API&type=revision&diff=14964&oldid=14954).
- 400 BadRequest errors from the Mojang's API are now logged.
## [4.2.2] - 2019-06-19
### Fixed
- GC for in-memory textures cache has not been initialized.
## [4.2.1] - 2019-05-06 ## [4.2.1] - 2019-05-06
### Changed ### Changed
@@ -57,6 +66,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
from the textures link instead. from the textures link instead.
- `hash` field from `POST /api/skins` endpoint. - `hash` field from `POST /api/skins` endpoint.
[Unreleased]: https://github.com/elyby/chrly/compare/4.2.1...HEAD [Unreleased]: https://github.com/elyby/chrly/compare/4.2.3...HEAD
[4.2.3]: https://github.com/elyby/chrly/compare/4.2.2...4.2.3
[4.2.2]: https://github.com/elyby/chrly/compare/4.2.1...4.2.2
[4.2.1]: https://github.com/elyby/chrly/compare/4.2.0...4.2.1 [4.2.1]: https://github.com/elyby/chrly/compare/4.2.0...4.2.1
[4.2.0]: https://github.com/elyby/chrly/compare/4.1.1...4.2.0 [4.2.0]: https://github.com/elyby/chrly/compare/4.1.1...4.2.0

View File

@@ -2,6 +2,7 @@
[![Written in Go][ico-lang]][link-go] [![Written in Go][ico-lang]][link-go]
[![Build Status][ico-build]][link-build] [![Build Status][ico-build]][link-build]
[![Coverage][ico-coverage]][link-coverage]
[![Keep a Changelog][ico-changelog]](CHANGELOG.md) [![Keep a Changelog][ico-changelog]](CHANGELOG.md)
[![Software License][ico-license]](LICENSE) [![Software License][ico-license]](LICENSE)
@@ -260,8 +261,10 @@ To run tests execute `go test ./...`. If your Go version is older than 1.9, then
[ico-lang]: https://img.shields.io/badge/lang-go%201.12-blue.svg?style=flat-square [ico-lang]: https://img.shields.io/badge/lang-go%201.12-blue.svg?style=flat-square
[ico-build]: https://img.shields.io/travis/elyby/chrly.svg?style=flat-square [ico-build]: https://img.shields.io/travis/elyby/chrly.svg?style=flat-square
[ico-coverage]: https://img.shields.io/codecov/c/github/elyby/chrly.svg?style=flat-square
[ico-changelog]: https://img.shields.io/badge/keep%20a-changelog-orange.svg?style=flat-square [ico-changelog]: https://img.shields.io/badge/keep%20a-changelog-orange.svg?style=flat-square
[ico-license]: https://img.shields.io/github/license/elyby/chrly.svg?style=flat-square [ico-license]: https://img.shields.io/github/license/elyby/chrly.svg?style=flat-square
[link-go]: https://golang.org [link-go]: https://golang.org
[link-build]: https://travis-ci.org/elyby/chrly [link-build]: https://travis-ci.org/elyby/chrly
[link-coverage]: https://codecov.io/gh/elyby/chrly

View File

@@ -25,9 +25,11 @@ type inMemoryTexturesStorage struct {
} }
func CreateInMemoryTexturesStorage() *inMemoryTexturesStorage { func CreateInMemoryTexturesStorage() *inMemoryTexturesStorage {
return &inMemoryTexturesStorage{ storage := &inMemoryTexturesStorage{
data: make(map[string]*inMemoryItem), data: make(map[string]*inMemoryItem),
} }
return storage
} }
func (s *inMemoryTexturesStorage) Start() { func (s *inMemoryTexturesStorage) Start() {

View File

@@ -114,7 +114,7 @@ func (ctx *JobsQueue) queueRound() {
} }
queueSize := ctx.queue.Size() queueSize := ctx.queue.Size()
jobs := ctx.queue.Dequeue(100) jobs := ctx.queue.Dequeue(10)
ctx.Logger.UpdateGauge("mojang_textures.usernames.iteration_size", int64(len(jobs))) ctx.Logger.UpdateGauge("mojang_textures.usernames.iteration_size", int64(len(jobs)))
ctx.Logger.UpdateGauge("mojang_textures.usernames.queue_size", int64(queueSize-len(jobs))) ctx.Logger.UpdateGauge("mojang_textures.usernames.queue_size", int64(queueSize-len(jobs)))
var usernames []string var usernames []string
@@ -184,6 +184,12 @@ func (ctx *JobsQueue) handleResponseError(err error, threadName string) {
case mojang.ResponseError: case mojang.ResponseError:
if _, ok := err.(*mojang.TooManyRequestsError); ok { if _, ok := err.(*mojang.TooManyRequestsError); ok {
ctx.Logger.Warning(":name: Got 429 Too Many Requests :err", wd.NameParam(threadName), wd.ErrParam(err)) ctx.Logger.Warning(":name: Got 429 Too Many Requests :err", wd.NameParam(threadName), wd.ErrParam(err))
return
}
if _, ok := err.(*mojang.BadRequestError); ok {
ctx.Logger.Warning(":name: Got 400 Bad Request :err", wd.NameParam(threadName), wd.ErrParam(err))
return
} }
return return

View File

@@ -258,30 +258,30 @@ func (suite *queueTestSuite) TestReceiveTexturesForUsernameWithCachedUnknownUuid
suite.Assert().Nil(<-resultChan) suite.Assert().Nil(<-resultChan)
} }
func (suite *queueTestSuite) TestReceiveTexturesForMoreThan100Usernames() { func (suite *queueTestSuite) TestReceiveTexturesForMoreThan10Usernames() {
usernames := make([]string, 120) usernames := make([]string, 12)
for i := 0; i < 120; i++ { for i := 0; i < cap(usernames); i++ {
usernames[i] = randStr(8) usernames[i] = randStr(8)
} }
suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Times(120) suite.Logger.On("IncCounter", "mojang_textures.request", int64(1)).Times(12)
suite.Logger.On("IncCounter", "mojang_textures.usernames.queued", int64(1)).Times(120) suite.Logger.On("IncCounter", "mojang_textures.usernames.queued", int64(1)).Times(12)
suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(100)).Once() suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(10)).Once()
suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(20)).Once() suite.Logger.On("UpdateGauge", "mojang_textures.usernames.iteration_size", int64(2)).Once()
suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(20)).Once() suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(2)).Once()
suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(0)).Once() suite.Logger.On("UpdateGauge", "mojang_textures.usernames.queue_size", int64(0)).Once()
suite.Logger.On("RecordTimer", "mojang_textures.usernames.round_time", mock.Anything).Twice() suite.Logger.On("RecordTimer", "mojang_textures.usernames.round_time", mock.Anything).Twice()
suite.Logger.On("IncCounter", "mojang_textures.usernames.uuid_miss", int64(1)).Times(120) suite.Logger.On("IncCounter", "mojang_textures.usernames.uuid_miss", int64(1)).Times(12)
suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Times(120) suite.Logger.On("RecordTimer", "mojang_textures.result_time", mock.Anything).Times(12)
suite.Storage.On("GetUuid", mock.Anything).Times(120).Return("", &ValueNotFound{}) suite.Storage.On("GetUuid", mock.Anything).Times(12).Return("", &ValueNotFound{})
suite.Storage.On("StoreUuid", mock.Anything, "").Times(120).Return(nil) // should be called with "" if username is not compared to uuid suite.Storage.On("StoreUuid", mock.Anything, "").Times(12).Return(nil) // should be called with "" if username is not compared to uuid
// Storage.GetTextures and Storage.SetTextures shouldn't be called // Storage.GetTextures and Storage.SetTextures shouldn't be called
suite.MojangApi.On("UsernamesToUuids", usernames[0:100]).Once().Return([]*mojang.ProfileInfo{}, nil) suite.MojangApi.On("UsernamesToUuids", usernames[0:10]).Once().Return([]*mojang.ProfileInfo{}, nil)
suite.MojangApi.On("UsernamesToUuids", usernames[100:120]).Once().Return([]*mojang.ProfileInfo{}, nil) suite.MojangApi.On("UsernamesToUuids", usernames[10:12]).Once().Return([]*mojang.ProfileInfo{}, nil)
channels := make([]chan *mojang.SignedTexturesResponse, 120) channels := make([]chan *mojang.SignedTexturesResponse, 12)
for i, username := range usernames { for i, username := range usernames {
channels[i] = suite.Queue.GetTexturesForUsername(username) channels[i] = suite.Queue.GetTexturesForUsername(username)
} }
@@ -417,6 +417,7 @@ func (suite *queueTestSuite) TestShouldNotLogErrorWhenExpectedErrorReturnedFromU
suite.Logger.On("UpdateGauge", mock.Anything, mock.Anything) suite.Logger.On("UpdateGauge", mock.Anything, mock.Anything)
suite.Logger.On("RecordTimer", mock.Anything, mock.Anything) suite.Logger.On("RecordTimer", mock.Anything, mock.Anything)
suite.Logger.On("Debug", ":name: Got response error :err", mock.Anything, mock.Anything).Times(len(expectedErrors)) suite.Logger.On("Debug", ":name: Got response error :err", mock.Anything, mock.Anything).Times(len(expectedErrors))
suite.Logger.On("Warning", ":name: Got 400 Bad Request :err", mock.Anything, mock.Anything).Once()
suite.Logger.On("Warning", ":name: Got 429 Too Many Requests :err", mock.Anything, mock.Anything).Once() suite.Logger.On("Warning", ":name: Got 429 Too Many Requests :err", mock.Anything, mock.Anything).Once()
suite.Storage.On("GetUuid", "maksimkurb").Return("", &ValueNotFound{}) suite.Storage.On("GetUuid", "maksimkurb").Return("", &ValueNotFound{})
@@ -453,6 +454,7 @@ func (suite *queueTestSuite) TestShouldNotLogErrorWhenExpectedErrorReturnedFromU
suite.Logger.On("UpdateGauge", mock.Anything, mock.Anything) suite.Logger.On("UpdateGauge", mock.Anything, mock.Anything)
suite.Logger.On("RecordTimer", mock.Anything, mock.Anything) suite.Logger.On("RecordTimer", mock.Anything, mock.Anything)
suite.Logger.On("Debug", ":name: Got response error :err", mock.Anything, mock.Anything).Times(len(expectedErrors)) suite.Logger.On("Debug", ":name: Got response error :err", mock.Anything, mock.Anything).Times(len(expectedErrors))
suite.Logger.On("Warning", ":name: Got 400 Bad Request :err", mock.Anything, mock.Anything).Once()
suite.Logger.On("Warning", ":name: Got 429 Too Many Requests :err", mock.Anything, mock.Anything).Once() suite.Logger.On("Warning", ":name: Got 429 Too Many Requests :err", mock.Anything, mock.Anything).Once()
suite.Storage.On("GetUuid", "maksimkurb").Return("", &ValueNotFound{}) suite.Storage.On("GetUuid", "maksimkurb").Return("", &ValueNotFound{})

View File

@@ -51,11 +51,13 @@ var serveCmd = &cobra.Command{
return return
} }
texturesStorage := queue.CreateInMemoryTexturesStorage()
texturesStorage.Start()
mojangTexturesQueue := &queue.JobsQueue{ mojangTexturesQueue := &queue.JobsQueue{
Logger: logger, Logger: logger,
Storage: &queue.SplittedStorage{ Storage: &queue.SplittedStorage{
UuidsStorage: mojangUuidsRepository, UuidsStorage: mojangUuidsRepository,
TexturesStorage: queue.CreateInMemoryTexturesStorage(), TexturesStorage: texturesStorage,
}, },
} }
logger.Info("Mojang's textures queue is successfully initialized") logger.Info("Mojang's textures queue is successfully initialized")