Skip to content

Commit

Permalink
Merge 4d78010 into 9e8bd16
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielerzinger committed Sep 17, 2018
2 parents 9e8bd16 + 4d78010 commit 1ae8192
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 40 deletions.
2 changes: 2 additions & 0 deletions constants/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ var (
ErrEtcdGrantLeaseTimeout = errors.New("timed out waiting for etcd lease grant")
ErrFrontSessionCantPushToFront = errors.New("frontend session can't push to front")
ErrIllegalUID = errors.New("illegal uid")
ErrKickingUsers = errors.New("failed to kick users, check array with failed uids")
ErrPushingToUsers = errors.New("failed to push message to users, check array with failed uids")
ErrMemberNotFound = errors.New("member not found in the group")
ErrNatsMessagesBufferSizeZero = errors.New("pitaya.buffer.cluster.rpc.server.nats.messages cant be zero")
ErrNatsNoRequestTimeout = errors.New("pitaya.cluster.rpc.client.nats.requesttimeout cant be empty")
Expand Down
19 changes: 15 additions & 4 deletions kick.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,35 @@ import (
"github.com/topfreegames/pitaya/session"
)

// SendKickToUsers sends kick to an user
func SendKickToUsers(uids []string, frontendType string) error {
// SendKickToUsers sends kick to an user array
func SendKickToUsers(uids []string, frontendType string) ([]string, error) {
if !app.server.Frontend && frontendType == "" {
return constants.ErrFrontendTypeNotSpecified
return uids, constants.ErrFrontendTypeNotSpecified
}

var notKickedUids []string

for _, uid := range uids {
if s := session.GetSessionByUID(uid); s != nil {
if err := s.Kick(context.Background()); err != nil {
notKickedUids = append(notKickedUids, uid)
logger.Log.Errorf("Session kick error, ID=%d, UID=%d, ERROR=%s", s.ID(), s.UID(), err.Error())
}
} else if app.rpcClient != nil {
kick := &protos.KickMsg{UserId: uid}
if err := app.rpcClient.SendKick(uid, frontendType, kick); err != nil {
notKickedUids = append(notKickedUids, uid)
logger.Log.Errorf("RPCClient send kick error, UID=%d, SvType=%s, Error=%s", uid, frontendType, err.Error())
}
} else {
notKickedUids = append(notKickedUids, uid)
}

}
return nil

if len(notKickedUids) != 0 {
return notKickedUids, constants.ErrKickingUsers
}

return nil, nil
}
80 changes: 55 additions & 25 deletions kick_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,46 +28,68 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
clustermocks "github.com/topfreegames/pitaya/cluster/mocks"
"github.com/topfreegames/pitaya/constants"
"github.com/topfreegames/pitaya/protos"
"github.com/topfreegames/pitaya/session"
"github.com/topfreegames/pitaya/session/mocks"
)

func TestSendKickToUsersLocalSession(t *testing.T) {
tables := []struct {
name string
table := struct {
uid1 string
uid2 string
frontendType string
err error
}{
{"success", uuid.New().String(), uuid.New().String(), "connector", nil},
{"fail", uuid.New().String(), uuid.New().String(), "connector", nil},
uuid.New().String(), uuid.New().String(), "connector", nil,
}

for _, table := range tables {
t.Run(table.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockNetworkEntity := mocks.NewMockNetworkEntity(ctrl)
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockNetworkEntity := mocks.NewMockNetworkEntity(ctrl)

s1 := session.New(mockNetworkEntity, true)
err := s1.Bind(context.Background(), table.uid1)
assert.NoError(t, err)
s1 := session.New(mockNetworkEntity, true)
err := s1.Bind(context.Background(), table.uid1)
assert.NoError(t, err)

s2 := session.New(mockNetworkEntity, true)
err = s2.Bind(context.Background(), table.uid2)
assert.NoError(t, err)
s2 := session.New(mockNetworkEntity, true)
err = s2.Bind(context.Background(), table.uid2)
assert.NoError(t, err)

mockNetworkEntity.EXPECT().Kick(context.Background()).Times(2).Return(table.err)
if table.err == nil {
mockNetworkEntity.EXPECT().Close().Times(2)
}
err = SendKickToUsers([]string{table.uid1, table.uid2}, table.frontendType)
mockNetworkEntity.EXPECT().Kick(context.Background()).Times(2).Return(table.err)
if table.err == nil {
mockNetworkEntity.EXPECT().Close().Times(2)
}

assert.NoError(t, err)
})
failedUids, err := SendKickToUsers([]string{table.uid1, table.uid2}, table.frontendType)
assert.Nil(t, failedUids)
assert.NoError(t, err)
}

func TestSendKickToUsersFail(t *testing.T) {
table := struct {
uid1 string
uid2 string
frontendType string
err error
}{
uuid.New().String(), uuid.New().String(), "connector", constants.ErrKickingUsers,
}

ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockNetworkEntity := mocks.NewMockNetworkEntity(ctrl)

s1 := session.New(mockNetworkEntity, true)
err := s1.Bind(context.Background(), table.uid1)
assert.NoError(t, err)

mockNetworkEntity.EXPECT().Kick(context.Background()).Times(1)
mockNetworkEntity.EXPECT().Close()
failedUids, err := SendKickToUsers([]string{table.uid1, table.uid2}, table.frontendType)
assert.Len(t, failedUids, 1)
assert.Equal(t, failedUids[0], table.uid2)
assert.Equal(t, err, table.err)
}

func TestSendKickToUsersRemoteSession(t *testing.T) {
Expand All @@ -78,7 +100,9 @@ func TestSendKickToUsersRemoteSession(t *testing.T) {
err error
}{
{"success", []string{uuid.New().String(), uuid.New().String()}, "connector", nil},
{"fail", []string{uuid.New().String(), uuid.New().String()}, "connector", constants.ErrKickingUsers},
}

for _, table := range tables {
t.Run(table.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
Expand All @@ -88,11 +112,17 @@ func TestSendKickToUsersRemoteSession(t *testing.T) {

for _, uid := range table.uids {
expectedKick := &protos.KickMsg{UserId: uid}
mockRPCClient.EXPECT().SendKick(uid, gomock.Any(), expectedKick)
mockRPCClient.EXPECT().SendKick(uid, gomock.Any(), expectedKick).Return(table.err)
}

err := SendKickToUsers(table.uids, table.frontendType)
assert.NoError(t, err)
failedUids, err := SendKickToUsers(table.uids, table.frontendType)
assert.Equal(t, err, table.err)
if table.err != nil {
assert.NotNil(t, failedUids)
assert.Equal(t, failedUids, table.uids)
} else {
assert.Nil(t, failedUids)
}
})
}
}
2 changes: 1 addition & 1 deletion pitaya-protos
Submodule pitaya-protos updated 1 files
+2 −0 pitaya.proto
18 changes: 14 additions & 4 deletions push.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,24 @@ import (
)

// SendPushToUsers sends a message to the given list of users
func SendPushToUsers(route string, v interface{}, uids []string, frontendType string) error {
func SendPushToUsers(route string, v interface{}, uids []string, frontendType string) ([]string, error) {
data, err := util.SerializeOrRaw(app.serializer, v)
if err != nil {
return err
return uids, err
}

if !app.server.Frontend && frontendType == "" {
return constants.ErrFrontendTypeNotSpecified
return uids, constants.ErrFrontendTypeNotSpecified
}

var notPushedUids []string

logger.Log.Debugf("Type=PushToUsers Route=%s, Data=%+v, SvType=%s, #Users=%d", route, v, frontendType, len(uids))

for _, uid := range uids {
if s := session.GetSessionByUID(uid); s != nil && app.server.Type == frontendType {
if err := s.Push(route, data); err != nil {
notPushedUids = append(notPushedUids, uid)
logger.Log.Errorf("Session push message error, ID=%d, UID=%d, Error=%s",
s.ID(), s.UID(), err.Error())
}
Expand All @@ -55,10 +58,17 @@ func SendPushToUsers(route string, v interface{}, uids []string, frontendType st
Data: data,
}
if err = app.rpcClient.SendPush(uid, &cluster.Server{Type: frontendType}, push); err != nil {
notPushedUids = append(notPushedUids, uid)
logger.Log.Errorf("RPCClient send message error, UID=%d, SvType=%s, Error=%s", uid, frontendType, err.Error())
}
} else {
notPushedUids = append(notPushedUids, uid)
}
}

return err
if len(notPushedUids) != 0 {
return notPushedUids, constants.ErrPushingToUsers
}

return nil, nil
}
25 changes: 19 additions & 6 deletions push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
clustermocks "github.com/topfreegames/pitaya/cluster/mocks"
"github.com/topfreegames/pitaya/constants"
"github.com/topfreegames/pitaya/protos"
serializemocks "github.com/topfreegames/pitaya/serialize/mocks"
"github.com/topfreegames/pitaya/session"
Expand All @@ -50,8 +51,10 @@ func TestSendPushToUsersFailsIfErrSerializing(t *testing.T) {
expectedErr := errors.New("serialize error")
mockSerializer.EXPECT().Marshal(data).Return(nil, expectedErr)

err := SendPushToUsers(route, data, []string{uid}, "test")
errArr, err := SendPushToUsers(route, data, []string{uid}, "test")
assert.Equal(t, expectedErr, err)
assert.Len(t, errArr, 1)
assert.Equal(t, errArr[0], uid)
}

func TestSendToUsersLocalSession(t *testing.T) {
Expand All @@ -60,7 +63,7 @@ func TestSendToUsersLocalSession(t *testing.T) {
err error
}{
{"successful_request", nil},
{"failed_request", errors.New("failed push")},
{"failed_request", constants.ErrPushingToUsers},
}
for _, table := range tables {
t.Run(table.name, func(t *testing.T) {
Expand All @@ -81,8 +84,16 @@ func TestSendToUsersLocalSession(t *testing.T) {
assert.NoError(t, err)

mockNetworkEntity.EXPECT().Push(route, data).Return(table.err).Times(2)
err = SendPushToUsers(route, data, []string{uid1, uid2}, app.server.Type)
assert.NoError(t, err)
errArr, err := SendPushToUsers(route, data, []string{uid1, uid2}, app.server.Type)

if table.err != nil {
assert.Equal(t, err, table.err)
assert.Len(t, errArr, 2)
} else {
assert.NoError(t, err)
assert.Len(t, errArr, 0)
}

})
}
}
Expand All @@ -93,7 +104,7 @@ func TestSendToUsersRemoteSession(t *testing.T) {
err error
}{
{"successful_request", nil},
{"failed_request", errors.New("failed send")},
{"failed_request", constants.ErrPushingToUsers},
}
for _, table := range tables {
t.Run(table.name, func(t *testing.T) {
Expand All @@ -120,11 +131,13 @@ func TestSendToUsersRemoteSession(t *testing.T) {
}
mockRPCClient.EXPECT().SendPush(uid1, gomock.Any(), expectedMsg1).Return(table.err)
mockRPCClient.EXPECT().SendPush(uid2, gomock.Any(), expectedMsg2).Return(table.err)
err := SendPushToUsers(route, data, []string{uid1, uid2}, svType)
errArr, err := SendPushToUsers(route, data, []string{uid1, uid2}, svType)
if table.err != nil {
assert.EqualError(t, err, table.err.Error())
assert.Len(t, errArr, 2)
} else {
assert.NoError(t, err)
assert.Nil(t, errArr)
}
})
}
Expand Down

0 comments on commit 1ae8192

Please sign in to comment.