mirror of
https://github.com/elyby/chrly.git
synced 2024-12-22 21:19:55 +05:30
Removed amqp worker command implementation
Removed Accounts Ely.by api implementation
This commit is contained in:
parent
f5f8fbc65e
commit
855302ec60
20
Gopkg.lock
generated
20
Gopkg.lock
generated
@ -7,12 +7,6 @@
|
||||
revision = "f6df55f235c24f236d11dbcf665249a59ac2021f"
|
||||
version = "1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/assembla/cony"
|
||||
packages = ["."]
|
||||
revision = "dd62697b0adb9adfda8589520cb85f4cbc2361f1"
|
||||
version = "v0.3.2"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/certifi/gocertifi"
|
||||
packages = ["."]
|
||||
@ -169,12 +163,6 @@
|
||||
revision = "25b30aa063fc18e48662b86996252eabdcf2f0c7"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/streadway/amqp"
|
||||
packages = ["."]
|
||||
revision = "2cbfe40c9341ad63ba23e53013b3ddc7989d801c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = ["assert"]
|
||||
@ -206,12 +194,6 @@
|
||||
packages = ["internal/gen","internal/triegen","internal/ucd","transform","unicode/cldr","unicode/norm"]
|
||||
revision = "bd91bbf73e9a4a801adbfb97133c992678533126"
|
||||
|
||||
[[projects]]
|
||||
name = "gopkg.in/h2non/gock.v1"
|
||||
packages = ["."]
|
||||
revision = "84d599244901620fb3eb96473eb9e50619f69b47"
|
||||
version = "v1.0.6"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
@ -221,6 +203,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "b7c6dd9fffc543dc24b5832c7767632e4c066189be7c40868ba5612f5f45dc64"
|
||||
inputs-digest = "b85cbbca8b4283a0977ee92789c9beee468f2d355da5dfa28a4176934548f6f3"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
@ -19,10 +19,6 @@ ignored = ["elyby/minecraft-skinsystem"]
|
||||
[[constraint]]
|
||||
name = "github.com/getsentry/raven-go"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/assembla/cony"
|
||||
version = "^0.3.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/SermoDigital/jose"
|
||||
version = "~1.1.0"
|
||||
|
@ -1,166 +0,0 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Addr string
|
||||
Id string
|
||||
Secret string
|
||||
Scopes []string
|
||||
|
||||
Client *http.Client
|
||||
}
|
||||
|
||||
type Token struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
TokenType string `json:"token_type"`
|
||||
ExpiresIn int `json:"expires_in"`
|
||||
config *Config
|
||||
}
|
||||
|
||||
func (config *Config) GetToken() (*Token, error) {
|
||||
form := url.Values{}
|
||||
form.Add("client_id", config.Id)
|
||||
form.Add("client_secret", config.Secret)
|
||||
form.Add("grant_type", "client_credentials")
|
||||
form.Add("scope", strings.Join(config.Scopes, ","))
|
||||
|
||||
response, err := config.getHttpClient().Post(config.getTokenUrl(), "application/x-www-form-urlencoded", strings.NewReader(form.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
var result *Token
|
||||
responseError := handleResponse(response)
|
||||
if responseError != nil {
|
||||
return nil, responseError
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(response.Body)
|
||||
unmarshalError := json.Unmarshal(body, &result)
|
||||
if unmarshalError != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result.config = config
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (config *Config) getTokenUrl() string {
|
||||
return concatenateHostAndPath(config.Addr, "/api/oauth2/v1/token")
|
||||
}
|
||||
|
||||
func (config *Config) getHttpClient() *http.Client {
|
||||
if config.Client == nil {
|
||||
config.Client = &http.Client{}
|
||||
}
|
||||
|
||||
return config.Client
|
||||
}
|
||||
|
||||
type AccountInfoResponse struct {
|
||||
Id int `json:"id"`
|
||||
Uuid string `json:"uuid"`
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
func (token *Token) AccountInfo(attribute string, value string) (*AccountInfoResponse, error) {
|
||||
request := token.newRequest("GET", token.accountInfoUrl(), nil)
|
||||
|
||||
query := request.URL.Query()
|
||||
query.Add(attribute, value)
|
||||
request.URL.RawQuery = query.Encode()
|
||||
|
||||
response, err := token.config.Client.Do(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer response.Body.Close()
|
||||
|
||||
var info *AccountInfoResponse
|
||||
|
||||
responseError := handleResponse(response)
|
||||
if responseError != nil {
|
||||
return nil, responseError
|
||||
}
|
||||
|
||||
body, _ := ioutil.ReadAll(response.Body)
|
||||
json.Unmarshal(body, &info)
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func (token *Token) accountInfoUrl() string {
|
||||
return concatenateHostAndPath(token.config.Addr, "/api/internal/accounts/info")
|
||||
}
|
||||
|
||||
func (token *Token) newRequest(method string, urlStr string, body io.Reader) *http.Request {
|
||||
request, err := http.NewRequest(method, urlStr, body)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
request.Header.Add("Authorization", "Bearer " + token.AccessToken)
|
||||
|
||||
return request
|
||||
}
|
||||
|
||||
func concatenateHostAndPath(host string, pathToJoin string) string {
|
||||
u, _ := url.Parse(host)
|
||||
u.Path = path.Join(u.Path, pathToJoin)
|
||||
|
||||
return u.String()
|
||||
}
|
||||
|
||||
type UnauthorizedResponse struct {}
|
||||
|
||||
func (err UnauthorizedResponse) Error() string {
|
||||
return "Unauthorized response"
|
||||
}
|
||||
|
||||
type ForbiddenResponse struct {}
|
||||
|
||||
func (err ForbiddenResponse) Error() string {
|
||||
return "Forbidden response"
|
||||
}
|
||||
|
||||
type NotFoundResponse struct {}
|
||||
|
||||
func (err NotFoundResponse) Error() string {
|
||||
return "Not found"
|
||||
}
|
||||
|
||||
type NotSuccessResponse struct {
|
||||
StatusCode int
|
||||
}
|
||||
|
||||
func (err NotSuccessResponse) Error() string {
|
||||
return fmt.Sprintf("Response code is \"%d\"", err.StatusCode)
|
||||
}
|
||||
|
||||
func handleResponse(response *http.Response) error {
|
||||
switch status := response.StatusCode; status {
|
||||
case 200:
|
||||
return nil
|
||||
case 401:
|
||||
return &UnauthorizedResponse{}
|
||||
case 403:
|
||||
return &ForbiddenResponse{}
|
||||
case 404:
|
||||
return &NotFoundResponse{}
|
||||
default:
|
||||
return &NotSuccessResponse{status}
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
testify "github.com/stretchr/testify/assert"
|
||||
"gopkg.in/h2non/gock.v1"
|
||||
)
|
||||
|
||||
func TestConfig_GetToken(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
defer gock.Off()
|
||||
gock.New("https://account.ely.by").
|
||||
Post("/api/oauth2/v1/token").
|
||||
Body(strings.NewReader("client_id=mock-id&client_secret=mock-secret&grant_type=client_credentials&scope=scope1%2Cscope2")).
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"access_token": "mocked-token",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 86400,
|
||||
})
|
||||
|
||||
client := &http.Client{}
|
||||
gock.InterceptClient(client)
|
||||
|
||||
config := &Config{
|
||||
Addr: "https://account.ely.by",
|
||||
Id: "mock-id",
|
||||
Secret: "mock-secret",
|
||||
Scopes: []string{"scope1", "scope2"},
|
||||
Client: client,
|
||||
}
|
||||
|
||||
result, err := config.GetToken()
|
||||
if assert.NoError(err) {
|
||||
assert.Equal("mocked-token", result.AccessToken)
|
||||
assert.Equal("Bearer", result.TokenType)
|
||||
assert.Equal(86400, result.ExpiresIn)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToken_AccountInfo(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
defer gock.Off()
|
||||
// To test valid behavior
|
||||
gock.New("https://account.ely.by").
|
||||
Get("/api/internal/accounts/info").
|
||||
MatchParam("id", "1").
|
||||
MatchHeader("Authorization", "Bearer mock-token").
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"id": 1,
|
||||
"uuid": "0f657aa8-bfbe-415d-b700-5750090d3af3",
|
||||
"username": "dummy",
|
||||
"email": "dummy@ely.by",
|
||||
})
|
||||
|
||||
// To test behavior on invalid or expired token
|
||||
gock.New("https://account.ely.by").
|
||||
Get("/api/internal/accounts/info").
|
||||
MatchParam("id", "1").
|
||||
MatchHeader("Authorization", "Bearer mock-token").
|
||||
Reply(401).
|
||||
JSON(map[string]interface{}{
|
||||
"name": "Unauthorized",
|
||||
"message": "Incorrect token",
|
||||
"code": 0,
|
||||
"status": 401,
|
||||
})
|
||||
|
||||
client := &http.Client{}
|
||||
gock.InterceptClient(client)
|
||||
|
||||
token := &Token{
|
||||
AccessToken: "mock-token",
|
||||
config: &Config{
|
||||
Addr: "https://account.ely.by",
|
||||
Client: client,
|
||||
},
|
||||
}
|
||||
|
||||
result, err := token.AccountInfo("id", "1")
|
||||
if assert.NoError(err) {
|
||||
assert.Equal(1, result.Id)
|
||||
assert.Equal("0f657aa8-bfbe-415d-b700-5750090d3af3", result.Uuid)
|
||||
assert.Equal("dummy", result.Username)
|
||||
assert.Equal("dummy@ely.by", result.Email)
|
||||
}
|
||||
|
||||
result2, err2 := token.AccountInfo("id", "1")
|
||||
assert.Nil(result2)
|
||||
assert.Error(err2)
|
||||
assert.IsType(&UnauthorizedResponse{}, err2)
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package accounts
|
||||
|
||||
type AutoRefresh struct {
|
||||
token *Token
|
||||
config *Config
|
||||
repeatsCount int
|
||||
}
|
||||
|
||||
const repeatsLimit = 3
|
||||
|
||||
func (config *Config) GetTokenWithAutoRefresh() *AutoRefresh {
|
||||
return &AutoRefresh{
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
func (refresher *AutoRefresh) AccountInfo(attribute string, value string) (*AccountInfoResponse, error) {
|
||||
defer refresher.resetRepeatsCount()
|
||||
|
||||
apiToken, err := refresher.getToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result, err := apiToken.AccountInfo(attribute, value)
|
||||
if err != nil {
|
||||
_, isTokenExpire := err.(*UnauthorizedResponse)
|
||||
if !isTokenExpire || refresher.repeatsCount >= repeatsLimit - 1 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refresher.repeatsCount++
|
||||
refresher.token = nil
|
||||
|
||||
return refresher.AccountInfo(attribute, value)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (refresher *AutoRefresh) getToken() (*Token, error) {
|
||||
if refresher.token == nil {
|
||||
newToken, err := refresher.config.GetToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
refresher.token = newToken
|
||||
}
|
||||
|
||||
return refresher.token, nil
|
||||
}
|
||||
|
||||
func (refresher *AutoRefresh) resetRepeatsCount() {
|
||||
refresher.repeatsCount = 0
|
||||
}
|
@ -1,242 +0,0 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
testify "github.com/stretchr/testify/assert"
|
||||
"gopkg.in/h2non/gock.v1"
|
||||
)
|
||||
|
||||
var config = &Config{
|
||||
Addr: "https://account.ely.by",
|
||||
Id: "mock-id",
|
||||
Secret: "mock-secret",
|
||||
Scopes: []string{"scope1", "scope2"},
|
||||
}
|
||||
|
||||
func TestConfig_GetTokenWithAutoRefresh(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
testConfig := &Config{}
|
||||
*testConfig = *config
|
||||
|
||||
result := testConfig.GetTokenWithAutoRefresh()
|
||||
assert.Equal(testConfig, result.config)
|
||||
}
|
||||
|
||||
func TestAutoRefresh_AccountInfo(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
defer gock.Off()
|
||||
gock.New("https://account.ely.by").
|
||||
Post("/api/oauth2/v1/token").
|
||||
Body(strings.NewReader("client_id=mock-id&client_secret=mock-secret&grant_type=client_credentials&scope=scope1%2Cscope2")).
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"access_token": "mocked-token",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 86400,
|
||||
})
|
||||
|
||||
gock.New("https://account.ely.by").
|
||||
Get("/api/internal/accounts/info").
|
||||
Times(2).
|
||||
MatchParam("id", "1").
|
||||
MatchHeader("Authorization", "Bearer mocked-token").
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"id": 1,
|
||||
"uuid": "0f657aa8-bfbe-415d-b700-5750090d3af3",
|
||||
"username": "dummy",
|
||||
"email": "dummy@ely.by",
|
||||
})
|
||||
|
||||
client := &http.Client{}
|
||||
gock.InterceptClient(client)
|
||||
|
||||
testConfig := &Config{}
|
||||
*testConfig = *config
|
||||
testConfig.Client = client
|
||||
|
||||
autoRefresher := testConfig.GetTokenWithAutoRefresh()
|
||||
result, err := autoRefresher.AccountInfo("id", "1")
|
||||
if assert.NoError(err) {
|
||||
assert.Equal(1, result.Id)
|
||||
assert.Equal("0f657aa8-bfbe-415d-b700-5750090d3af3", result.Uuid)
|
||||
assert.Equal("dummy", result.Username)
|
||||
assert.Equal("dummy@ely.by", result.Email)
|
||||
}
|
||||
|
||||
result2, err2 := autoRefresher.AccountInfo("id", "1")
|
||||
if assert.NoError(err2) {
|
||||
assert.Equal(result, result2, "Results should still be same without token refreshing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoRefresh_AccountInfo2(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
defer gock.Off()
|
||||
gock.New("https://account.ely.by").
|
||||
Post("/api/oauth2/v1/token").
|
||||
Body(strings.NewReader("client_id=mock-id&client_secret=mock-secret&grant_type=client_credentials&scope=scope1%2Cscope2")).
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"access_token": "mocked-token-1",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 86400,
|
||||
})
|
||||
|
||||
gock.New("https://account.ely.by").
|
||||
Get("/api/internal/accounts/info").
|
||||
MatchParam("id", "1").
|
||||
MatchHeader("Authorization", "Bearer mocked-token-1").
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"id": 1,
|
||||
"uuid": "0f657aa8-bfbe-415d-b700-5750090d3af3",
|
||||
"username": "dummy",
|
||||
"email": "dummy@ely.by",
|
||||
})
|
||||
|
||||
gock.New("https://account.ely.by").
|
||||
Get("/api/internal/accounts/info").
|
||||
MatchParam("id", "1").
|
||||
MatchHeader("Authorization", "Bearer mocked-token-1").
|
||||
Reply(401).
|
||||
JSON(map[string]interface{}{
|
||||
"name": "Unauthorized",
|
||||
"message": "Incorrect token",
|
||||
"code": 0,
|
||||
"status": 401,
|
||||
})
|
||||
|
||||
gock.New("https://account.ely.by").
|
||||
Post("/api/oauth2/v1/token").
|
||||
Body(strings.NewReader("client_id=mock-id&client_secret=mock-secret&grant_type=client_credentials&scope=scope1%2Cscope2")).
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"access_token": "mocked-token-2",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 86400,
|
||||
})
|
||||
|
||||
gock.New("https://account.ely.by").
|
||||
Get("/api/internal/accounts/info").
|
||||
MatchParam("id", "1").
|
||||
MatchHeader("Authorization", "Bearer mocked-token-2").
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"id": 1,
|
||||
"uuid": "0f657aa8-bfbe-415d-b700-5750090d3af3",
|
||||
"username": "dummy",
|
||||
"email": "dummy@ely.by",
|
||||
})
|
||||
|
||||
client := &http.Client{}
|
||||
gock.InterceptClient(client)
|
||||
|
||||
testConfig := &Config{}
|
||||
*testConfig = *config
|
||||
testConfig.Client = client
|
||||
|
||||
autoRefresher := testConfig.GetTokenWithAutoRefresh()
|
||||
result, err := autoRefresher.AccountInfo("id", "1")
|
||||
if assert.NoError(err) {
|
||||
assert.Equal(1, result.Id)
|
||||
assert.Equal("0f657aa8-bfbe-415d-b700-5750090d3af3", result.Uuid)
|
||||
assert.Equal("dummy", result.Username)
|
||||
assert.Equal("dummy@ely.by", result.Email)
|
||||
}
|
||||
|
||||
result2, err2 := autoRefresher.AccountInfo("id", "1")
|
||||
if assert.NoError(err2) {
|
||||
assert.Equal(result, result2, "Results should still be same with refreshed token")
|
||||
}
|
||||
}
|
||||
|
||||
func TestAutoRefresh_AccountInfo3(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
defer gock.Off()
|
||||
gock.New("https://account.ely.by").
|
||||
Post("/api/oauth2/v1/token").
|
||||
Body(strings.NewReader("client_id=mock-id&client_secret=mock-secret&grant_type=client_credentials&scope=scope1%2Cscope2")).
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"access_token": "mocked-token-1",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 86400,
|
||||
})
|
||||
|
||||
gock.New("https://account.ely.by").
|
||||
Get("/api/internal/accounts/info").
|
||||
MatchParam("id", "1").
|
||||
MatchHeader("Authorization", "Bearer mocked-token-1").
|
||||
Reply(404).
|
||||
JSON(map[string]interface{}{
|
||||
"name": "Not Found",
|
||||
"message": "Page not found.",
|
||||
"code": 0,
|
||||
"status": 404,
|
||||
})
|
||||
|
||||
client := &http.Client{}
|
||||
gock.InterceptClient(client)
|
||||
|
||||
testConfig := &Config{}
|
||||
*testConfig = *config
|
||||
testConfig.Client = client
|
||||
|
||||
autoRefresher := testConfig.GetTokenWithAutoRefresh()
|
||||
result, err := autoRefresher.AccountInfo("id", "1")
|
||||
assert.Nil(result)
|
||||
assert.Error(err)
|
||||
assert.IsType(&NotFoundResponse{}, err)
|
||||
}
|
||||
|
||||
func TestAutoRefresh_AccountInfo4(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
defer gock.Off()
|
||||
gock.New("https://account.ely.by").
|
||||
Post("/api/oauth2/v1/token").
|
||||
Times(3).
|
||||
Body(strings.NewReader("client_id=mock-id&client_secret=mock-secret&grant_type=client_credentials&scope=scope1%2Cscope2")).
|
||||
Reply(200).
|
||||
JSON(map[string]interface{}{
|
||||
"access_token": "mocked-token-1",
|
||||
"token_type": "Bearer",
|
||||
"expires_in": 86400,
|
||||
})
|
||||
|
||||
gock.New("https://account.ely.by").
|
||||
Get("/api/internal/accounts/info").
|
||||
Times(3).
|
||||
MatchParam("id", "1").
|
||||
MatchHeader("Authorization", "Bearer mocked-token-1").
|
||||
Reply(401).
|
||||
JSON(map[string]interface{}{
|
||||
"name": "Unauthorized",
|
||||
"message": "Incorrect token",
|
||||
"code": 0,
|
||||
"status": 401,
|
||||
})
|
||||
|
||||
client := &http.Client{}
|
||||
gock.InterceptClient(client)
|
||||
|
||||
testConfig := &Config{}
|
||||
*testConfig = *config
|
||||
testConfig.Client = client
|
||||
|
||||
autoRefresher := testConfig.GetTokenWithAutoRefresh()
|
||||
result, err := autoRefresher.AccountInfo("id", "1")
|
||||
assert.Nil(result)
|
||||
assert.Error(err)
|
||||
if !assert.IsType(&UnauthorizedResponse{}, err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
@ -1,11 +1,8 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
|
||||
"github.com/assembla/cony"
|
||||
"github.com/getsentry/raven-go"
|
||||
"github.com/mono83/slf/rays"
|
||||
"github.com/mono83/slf/recievers/sentry"
|
||||
@ -74,17 +71,3 @@ type RabbitMQConfig struct {
|
||||
Vhost string
|
||||
}
|
||||
|
||||
func CreateRabbitMQClient(config *RabbitMQConfig) *cony.Client {
|
||||
addr := fmt.Sprintf(
|
||||
"amqp://%s:%s@%s:%d/%s",
|
||||
config.Username,
|
||||
config.Password,
|
||||
config.Host,
|
||||
config.Port,
|
||||
url.PathEscape(config.Vhost),
|
||||
)
|
||||
|
||||
client := cony.NewClient(cony.URL(addr), cony.Backoff(cony.DefaultBackoff))
|
||||
|
||||
return client
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"elyby/minecraft-skinsystem/api/accounts"
|
||||
"elyby/minecraft-skinsystem/bootstrap"
|
||||
"elyby/minecraft-skinsystem/db"
|
||||
"elyby/minecraft-skinsystem/worker"
|
||||
)
|
||||
|
||||
var amqpWorkerCmd = &cobra.Command{
|
||||
Use: "amqp-worker",
|
||||
Short: "Launches a worker which listens to events and processes them",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
logger, err := bootstrap.CreateLogger(viper.GetString("statsd.addr"), viper.GetString("sentry.dsn"))
|
||||
if err != nil {
|
||||
log.Fatal(fmt.Printf("Cannot initialize logger: %v", err))
|
||||
}
|
||||
logger.Info("Logger successfully initialized")
|
||||
|
||||
storageFactory := db.StorageFactory{Config: viper.GetViper()}
|
||||
|
||||
logger.Info("Initializing skins repository")
|
||||
skinsRepo, err := storageFactory.CreateFactory("redis").CreateSkinsRepository()
|
||||
if err != nil {
|
||||
logger.Emergency(fmt.Sprintf("Error on creating skins repo: %+v", err))
|
||||
return
|
||||
}
|
||||
logger.Info("Skins repository successfully initialized")
|
||||
|
||||
logger.Info("Creating AMQP client")
|
||||
amqpClient := bootstrap.CreateRabbitMQClient(&bootstrap.RabbitMQConfig{
|
||||
Host: viper.GetString("amqp.host"),
|
||||
Port: viper.GetInt("amqp.port"),
|
||||
Username: viper.GetString("amqp.username"),
|
||||
Password: viper.GetString("amqp.password"),
|
||||
Vhost: viper.GetString("amqp.vhost"),
|
||||
})
|
||||
|
||||
accountsApi := (&accounts.Config{
|
||||
Addr: viper.GetString("api.accounts.host"),
|
||||
Id: viper.GetString("api.accounts.id"),
|
||||
Secret: viper.GetString("api.accounts.secret"),
|
||||
Scopes: viper.GetStringSlice("api.accounts.scopes"),
|
||||
}).GetTokenWithAutoRefresh()
|
||||
|
||||
services := &worker.Services{
|
||||
Logger: logger,
|
||||
AmqpClient: amqpClient,
|
||||
SkinsRepo: skinsRepo,
|
||||
AccountsAPI: accountsApi,
|
||||
}
|
||||
|
||||
if err := services.Run(); err != nil {
|
||||
logger.Error(fmt.Sprintf("Cannot initialize worker: %+v", err))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(amqpWorkerCmd)
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package interfaces
|
||||
|
||||
import (
|
||||
"elyby/minecraft-skinsystem/api/accounts"
|
||||
)
|
||||
|
||||
type AccountsAPI interface {
|
||||
AccountInfo(attribute string, value string) (*accounts.AccountInfoResponse, error)
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: interfaces/api.go
|
||||
|
||||
package mock_interfaces
|
||||
|
||||
import (
|
||||
accounts "elyby/minecraft-skinsystem/api/accounts"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
reflect "reflect"
|
||||
)
|
||||
|
||||
// MockAccountsAPI is a mock of AccountsAPI interface
|
||||
type MockAccountsAPI struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAccountsAPIMockRecorder
|
||||
}
|
||||
|
||||
// MockAccountsAPIMockRecorder is the mock recorder for MockAccountsAPI
|
||||
type MockAccountsAPIMockRecorder struct {
|
||||
mock *MockAccountsAPI
|
||||
}
|
||||
|
||||
// NewMockAccountsAPI creates a new mock instance
|
||||
func NewMockAccountsAPI(ctrl *gomock.Controller) *MockAccountsAPI {
|
||||
mock := &MockAccountsAPI{ctrl: ctrl}
|
||||
mock.recorder = &MockAccountsAPIMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use
|
||||
func (_m *MockAccountsAPI) EXPECT() *MockAccountsAPIMockRecorder {
|
||||
return _m.recorder
|
||||
}
|
||||
|
||||
// AccountInfo mocks base method
|
||||
func (_m *MockAccountsAPI) AccountInfo(attribute string, value string) (*accounts.AccountInfoResponse, error) {
|
||||
ret := _m.ctrl.Call(_m, "AccountInfo", attribute, value)
|
||||
ret0, _ := ret[0].(*accounts.AccountInfoResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// AccountInfo indicates an expected call of AccountInfo
|
||||
func (_mr *MockAccountsAPIMockRecorder) AccountInfo(arg0, arg1 interface{}) *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCallWithMethodType(_mr.mock, "AccountInfo", reflect.TypeOf((*MockAccountsAPI)(nil).AccountInfo), arg0, arg1)
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
mockgen -source=interfaces/repositories.go -destination=interfaces/mock_interfaces/mock_interfaces.go
|
||||
mockgen -source=interfaces/api.go -destination=interfaces/mock_interfaces/mock_api.go
|
||||
mockgen -source=interfaces/auth.go -destination=interfaces/mock_interfaces/mock_auth.go
|
||||
|
@ -1,186 +0,0 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
testify "github.com/stretchr/testify/assert"
|
||||
|
||||
"elyby/minecraft-skinsystem/api/accounts"
|
||||
"elyby/minecraft-skinsystem/db"
|
||||
"elyby/minecraft-skinsystem/interfaces/mock_interfaces"
|
||||
"elyby/minecraft-skinsystem/interfaces/mock_wd"
|
||||
"elyby/minecraft-skinsystem/model"
|
||||
)
|
||||
|
||||
func TestServices_HandleChangeUsername(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
services, skinRepo, _, wd := setupMocks(ctrl)
|
||||
|
||||
resultModel := createSourceModel()
|
||||
resultModel.Username = "new_username"
|
||||
|
||||
// Запись о скине существует, никаких осложнений
|
||||
skinRepo.EXPECT().FindByUserId(1).Return(createSourceModel(), nil)
|
||||
skinRepo.EXPECT().Save(resultModel)
|
||||
wd.EXPECT().IncCounter("worker.change_username", int64(1))
|
||||
|
||||
assert.True(services.HandleChangeUsername(&UsernameChanged{
|
||||
AccountId: 1,
|
||||
OldUsername: "mock_user",
|
||||
NewUsername: "new_username",
|
||||
}))
|
||||
|
||||
// Событие с пустым ником, т.е это регистрация, так что нужно создать запись о скине
|
||||
skinRepo.EXPECT().FindByUserId(1).Times(0)
|
||||
skinRepo.EXPECT().Save(&model.Skin{UserId: 1, Username: "new_mock"})
|
||||
wd.EXPECT().IncCounter("worker.change_username", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.change_username_empty_old_username", int64(1))
|
||||
|
||||
assert.True(services.HandleChangeUsername(&UsernameChanged{
|
||||
AccountId: 1,
|
||||
OldUsername: "",
|
||||
NewUsername: "new_mock",
|
||||
}))
|
||||
|
||||
// В базе системы скинов нет записи об указанном пользователе, так что её нужно восстановить
|
||||
skinRepo.EXPECT().FindByUserId(1).Return(nil, &db.SkinNotFoundError{})
|
||||
skinRepo.EXPECT().Save(&model.Skin{UserId: 1, Username: "new_mock2"})
|
||||
wd.EXPECT().IncCounter("worker.change_username", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.change_username_id_not_found", int64(1))
|
||||
wd.EXPECT().Info("Cannot find user id :accountId. Trying to search.", gomock.Any())
|
||||
|
||||
assert.True(services.HandleChangeUsername(&UsernameChanged{
|
||||
AccountId: 1,
|
||||
OldUsername: "mock_user",
|
||||
NewUsername: "new_mock2",
|
||||
}))
|
||||
|
||||
// Репозиторий вернул неожиданную ошибку
|
||||
skinRepo.EXPECT().FindByUserId(1).Return(nil, errors.New("mock error"))
|
||||
skinRepo.EXPECT().Save(&model.Skin{UserId: 1, Username: "new_mock2"})
|
||||
wd.EXPECT().IncCounter("worker.change_username", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.change_username_id_not_found", int64(1))
|
||||
wd.EXPECT().Info("Cannot find user id :accountId. Trying to search.", gomock.Any())
|
||||
wd.EXPECT().Error("Unknown error when requesting a skin from the repository: :err", gomock.Any())
|
||||
|
||||
assert.True(services.HandleChangeUsername(&UsernameChanged{
|
||||
AccountId: 1,
|
||||
OldUsername: "mock_user",
|
||||
NewUsername: "new_mock2",
|
||||
}))
|
||||
}
|
||||
|
||||
func TestServices_HandleSkinChanged(t *testing.T) {
|
||||
assert := testify.New(t)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
services, skinRepo, accountsAPI, wd := setupMocks(ctrl)
|
||||
|
||||
event := &SkinChanged{
|
||||
AccountId: 1,
|
||||
Uuid: "cdb907ce-84f4-4c38-801d-1e287dca2623",
|
||||
SkinId: 2,
|
||||
Hash: "f76caa016e07267a05b7daf9ebc7419c",
|
||||
Is1_8: true,
|
||||
IsSlim: false,
|
||||
Url: "http://ely.by/minecraft/skins/69c6740d2993e5d6f6a7fc92420efc29.png",
|
||||
MojangTextures: "new mocked textures base64",
|
||||
MojangSignature: "new mocked signature",
|
||||
}
|
||||
|
||||
resultModel := createSourceModel()
|
||||
resultModel.SkinId = event.SkinId
|
||||
resultModel.Hash = event.Hash
|
||||
resultModel.Is1_8 = event.Is1_8
|
||||
resultModel.IsSlim = event.IsSlim
|
||||
resultModel.Url = event.Url
|
||||
resultModel.MojangTextures = event.MojangTextures
|
||||
resultModel.MojangSignature = event.MojangSignature
|
||||
|
||||
// Запись о скине существует, никаких осложнений
|
||||
skinRepo.EXPECT().FindByUserId(1).Return(createSourceModel(), nil)
|
||||
skinRepo.EXPECT().Save(resultModel)
|
||||
wd.EXPECT().IncCounter("worker.skin_changed", int64(1))
|
||||
|
||||
assert.True(services.HandleSkinChanged(event))
|
||||
|
||||
// Записи о скине не существует, она должна быть восстановлена
|
||||
skinRepo.EXPECT().FindByUserId(1).Return(nil, &db.SkinNotFoundError{"mock_user"})
|
||||
skinRepo.EXPECT().Save(resultModel)
|
||||
accountsAPI.EXPECT().AccountInfo("id", "1").Return(&accounts.AccountInfoResponse{
|
||||
Id: 1,
|
||||
Username: "mock_user",
|
||||
Uuid: "cdb907ce-84f4-4c38-801d-1e287dca2623",
|
||||
Email: "mock-user@ely.by",
|
||||
}, nil)
|
||||
wd.EXPECT().IncCounter("worker.skin_changed", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.skin_changed_id_not_found", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.skin_changed_id_restored", int64(1))
|
||||
wd.EXPECT().Info("Cannot find user id :accountId. Trying to search.", gomock.Any())
|
||||
wd.EXPECT().Info("User info successfully restored.")
|
||||
|
||||
assert.True(services.HandleSkinChanged(event))
|
||||
|
||||
// Записи о скине не существует, и Ely.by Accounts internal API не знает о таком пользователе
|
||||
skinRepo.EXPECT().FindByUserId(1).Return(nil, &db.SkinNotFoundError{"mock_user"})
|
||||
accountsAPI.EXPECT().AccountInfo("id", "1").Return(nil, &accounts.NotFoundResponse{})
|
||||
wd.EXPECT().IncCounter("worker.skin_changed", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.skin_changed_id_not_found", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.skin_changed_id_not_restored", int64(1))
|
||||
wd.EXPECT().Info("Cannot find user id :accountId. Trying to search.", gomock.Any())
|
||||
wd.EXPECT().Error("Cannot restore user info for :accountId: :err", gomock.Any(), gomock.Any())
|
||||
|
||||
assert.True(services.HandleSkinChanged(event))
|
||||
|
||||
// Репозиторий скинов вернул неизвестную ошибку, и Ely.by Accounts internal API не знает о таком пользователе
|
||||
skinRepo.EXPECT().FindByUserId(1).Return(nil, errors.New("mocked error"))
|
||||
accountsAPI.EXPECT().AccountInfo("id", "1").Return(nil, &accounts.NotFoundResponse{})
|
||||
wd.EXPECT().IncCounter("worker.skin_changed", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.skin_changed_id_not_found", int64(1))
|
||||
wd.EXPECT().IncCounter("worker.skin_changed_id_not_restored", int64(1))
|
||||
wd.EXPECT().Error("Unknown error when requesting a skin from the repository: :err", gomock.Any())
|
||||
wd.EXPECT().Info("Cannot find user id :accountId. Trying to search.", gomock.Any())
|
||||
wd.EXPECT().Error("Cannot restore user info for :accountId: :err", gomock.Any(), gomock.Any())
|
||||
|
||||
assert.True(services.HandleSkinChanged(event))
|
||||
}
|
||||
|
||||
func createSourceModel() *model.Skin {
|
||||
return &model.Skin{
|
||||
UserId: 1,
|
||||
Uuid: "cdb907ce-84f4-4c38-801d-1e287dca2623",
|
||||
Username: "mock_user",
|
||||
SkinId: 1,
|
||||
Url: "http://ely.by/minecraft/skins/3a345c701f473ac08c8c5b8ecb58ecf3.png",
|
||||
Is1_8: false,
|
||||
IsSlim: false,
|
||||
Hash: "3a345c701f473ac08c8c5b8ecb58ecf3",
|
||||
MojangTextures: "mocked textures base64",
|
||||
MojangSignature: "mocked signature",
|
||||
}
|
||||
}
|
||||
|
||||
func setupMocks(ctrl *gomock.Controller) (
|
||||
*Services,
|
||||
*mock_interfaces.MockSkinsRepository,
|
||||
*mock_interfaces.MockAccountsAPI,
|
||||
*mock_wd.MockWatchdog,
|
||||
) {
|
||||
skinsRepo := mock_interfaces.NewMockSkinsRepository(ctrl)
|
||||
accountApi := mock_interfaces.NewMockAccountsAPI(ctrl)
|
||||
wd := mock_wd.NewMockWatchdog(ctrl)
|
||||
|
||||
return &Services{
|
||||
SkinsRepo: skinsRepo,
|
||||
AccountsAPI: accountApi,
|
||||
Logger: wd,
|
||||
}, skinsRepo, accountApi, wd
|
||||
}
|
219
worker/worker.go
219
worker/worker.go
@ -1,219 +0,0 @@
|
||||
package worker
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/assembla/cony"
|
||||
"github.com/mono83/slf/wd"
|
||||
"github.com/streadway/amqp"
|
||||
|
||||
"elyby/minecraft-skinsystem/db"
|
||||
"elyby/minecraft-skinsystem/interfaces"
|
||||
"elyby/minecraft-skinsystem/model"
|
||||
)
|
||||
|
||||
type Services struct {
|
||||
AmqpClient *cony.Client
|
||||
SkinsRepo interfaces.SkinsRepository
|
||||
AccountsAPI interfaces.AccountsAPI
|
||||
Logger wd.Watchdog
|
||||
}
|
||||
|
||||
type UsernameChanged struct {
|
||||
AccountId int `json:"accountId"`
|
||||
OldUsername string `json:"oldUsername"`
|
||||
NewUsername string `json:"newUsername"`
|
||||
}
|
||||
|
||||
type SkinChanged struct {
|
||||
AccountId int `json:"userId"`
|
||||
Uuid string `json:"uuid"`
|
||||
SkinId int `json:"skinId"`
|
||||
Hash string `json:"hash"`
|
||||
Is1_8 bool `json:"is1_8"`
|
||||
IsSlim bool `json:"isSlim"`
|
||||
Url string `json:"url"`
|
||||
MojangTextures string `json:"mojangTextures"`
|
||||
MojangSignature string `json:"mojangSignature"`
|
||||
}
|
||||
|
||||
const exchangeName string = "events"
|
||||
const queueName string = "skinsystem-accounts-events"
|
||||
|
||||
func (service *Services) Run() error {
|
||||
clientErrs, consumerErrs, deliveryChannel := setupClient(service.AmqpClient)
|
||||
shouldReturnError := true
|
||||
|
||||
for service.AmqpClient.Loop() {
|
||||
select {
|
||||
case msg := <-deliveryChannel:
|
||||
shouldReturnError = false
|
||||
service.HandleDelivery(&msg)
|
||||
case err := <-consumerErrs:
|
||||
if shouldReturnError {
|
||||
return err
|
||||
}
|
||||
|
||||
service.Logger.Error("Consume error: :err", wd.ErrParam(err))
|
||||
case err := <-clientErrs:
|
||||
if shouldReturnError {
|
||||
return err
|
||||
}
|
||||
|
||||
service.Logger.Error("Client error: :err", wd.ErrParam(err))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (service *Services) HandleDelivery(delivery *amqp.Delivery) {
|
||||
service.Logger.Debug("Incoming message with routing key " + delivery.RoutingKey)
|
||||
var result bool = true
|
||||
switch delivery.RoutingKey {
|
||||
case "accounts.username-changed":
|
||||
var event *UsernameChanged
|
||||
json.Unmarshal(delivery.Body, &event)
|
||||
result = service.HandleChangeUsername(event)
|
||||
case "accounts.skin-changed":
|
||||
var event *SkinChanged
|
||||
json.Unmarshal(delivery.Body, &event)
|
||||
result = service.HandleSkinChanged(event)
|
||||
default:
|
||||
service.Logger.Info("Unknown delivery with routing key " + delivery.RoutingKey)
|
||||
delivery.Ack(false)
|
||||
return
|
||||
}
|
||||
|
||||
if result {
|
||||
delivery.Ack(false)
|
||||
} else {
|
||||
delivery.Reject(true)
|
||||
}
|
||||
}
|
||||
|
||||
func (service *Services) HandleChangeUsername(event *UsernameChanged) bool {
|
||||
service.Logger.IncCounter("worker.change_username", 1)
|
||||
if event.OldUsername == "" {
|
||||
service.Logger.IncCounter("worker.change_username_empty_old_username", 1)
|
||||
record := &model.Skin{
|
||||
UserId: event.AccountId,
|
||||
Username: event.NewUsername,
|
||||
}
|
||||
|
||||
service.SkinsRepo.Save(record)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
record, err := service.SkinsRepo.FindByUserId(event.AccountId)
|
||||
if err != nil {
|
||||
service.Logger.Info("Cannot find user id :accountId. Trying to search.", wd.IntParam("accountId", event.AccountId))
|
||||
if _, isSkinNotFound := err.(*db.SkinNotFoundError); !isSkinNotFound {
|
||||
service.Logger.Error("Unknown error when requesting a skin from the repository: :err", wd.ErrParam(err))
|
||||
}
|
||||
|
||||
service.Logger.IncCounter("worker.change_username_id_not_found", 1)
|
||||
record = &model.Skin{
|
||||
UserId: event.AccountId,
|
||||
}
|
||||
}
|
||||
|
||||
record.Username = event.NewUsername
|
||||
service.SkinsRepo.Save(record)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// TODO: возможно стоит добавить проверку на совпадение id аккаунтов
|
||||
func (service *Services) HandleSkinChanged(event *SkinChanged) bool {
|
||||
service.Logger.IncCounter("worker.skin_changed", 1)
|
||||
var record *model.Skin
|
||||
record, err := service.SkinsRepo.FindByUserId(event.AccountId)
|
||||
if err != nil {
|
||||
if _, isSkinNotFound := err.(*db.SkinNotFoundError); !isSkinNotFound {
|
||||
service.Logger.Error("Unknown error when requesting a skin from the repository: :err", wd.ErrParam(err))
|
||||
}
|
||||
|
||||
service.Logger.IncCounter("worker.skin_changed_id_not_found", 1)
|
||||
service.Logger.Info("Cannot find user id :accountId. Trying to search.", wd.IntParam("accountId", event.AccountId))
|
||||
response, err := service.AccountsAPI.AccountInfo("id", strconv.Itoa(event.AccountId))
|
||||
if err != nil {
|
||||
service.Logger.IncCounter("worker.skin_changed_id_not_restored", 1)
|
||||
service.Logger.Error(
|
||||
"Cannot restore user info for :accountId: :err",
|
||||
wd.IntParam("accountId", event.AccountId),
|
||||
wd.ErrParam(err),
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
service.Logger.IncCounter("worker.skin_changed_id_restored", 1)
|
||||
service.Logger.Info("User info successfully restored.")
|
||||
|
||||
record = &model.Skin{
|
||||
UserId: response.Id,
|
||||
Username: response.Username,
|
||||
}
|
||||
}
|
||||
|
||||
record.Uuid = event.Uuid
|
||||
record.SkinId = event.SkinId
|
||||
record.Hash = event.Hash
|
||||
record.Is1_8 = event.Is1_8
|
||||
record.IsSlim = event.IsSlim
|
||||
record.Url = event.Url
|
||||
record.MojangTextures = event.MojangTextures
|
||||
record.MojangSignature = event.MojangSignature
|
||||
|
||||
service.SkinsRepo.Save(record)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func setupClient(client *cony.Client) (<-chan error, <-chan error, <-chan amqp.Delivery ) {
|
||||
exchange := cony.Exchange{
|
||||
Name: exchangeName,
|
||||
Kind: "topic",
|
||||
Durable: true,
|
||||
AutoDelete: false,
|
||||
}
|
||||
|
||||
queue := &cony.Queue{
|
||||
Name: queueName,
|
||||
Durable: true,
|
||||
AutoDelete: false,
|
||||
Exclusive: false,
|
||||
}
|
||||
|
||||
usernameEventBinding := cony.Binding{
|
||||
Exchange: exchange,
|
||||
Queue: queue,
|
||||
Key: "accounts.username-changed",
|
||||
}
|
||||
|
||||
skinEventBinding := cony.Binding{
|
||||
Exchange: exchange,
|
||||
Queue: queue,
|
||||
Key: "accounts.skin-changed",
|
||||
}
|
||||
|
||||
declarations := []cony.Declaration{
|
||||
cony.DeclareExchange(exchange),
|
||||
cony.DeclareQueue(queue),
|
||||
cony.DeclareBinding(usernameEventBinding),
|
||||
cony.DeclareBinding(skinEventBinding),
|
||||
}
|
||||
|
||||
client.Declare(declarations)
|
||||
|
||||
consumer := cony.NewConsumer(queue,
|
||||
cony.Qos(10),
|
||||
cony.AutoTag(),
|
||||
)
|
||||
client.Consume(consumer)
|
||||
|
||||
return client.Errors(), consumer.Errors(), consumer.Deliveries()
|
||||
}
|
Loading…
Reference in New Issue
Block a user