Create & Init Project...

This commit is contained in:
2019-04-22 18:49:16 +08:00
commit fc4fa37393
25440 changed files with 4054998 additions and 0 deletions

View File

@@ -0,0 +1,19 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/job/main/broadcast/cmd:all-srcs",
"//app/job/main/broadcast/conf:all-srcs",
"//app/job/main/broadcast/server/http:all-srcs",
"//app/job/main/broadcast/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,33 @@
### v1.1.4
> 1.添加兼容v1消息
### v1.1.3
> 1.修改env
### v1.1.2
> 1.使用paladin config sdk
### v1.1.1
> 1.修复退出没推送完消息
### v1.1.0
> 1.修正grpc api
### v1.0.5
> 1.添加compress和content-type
> 2.更改心跳返回类型
### v1.0.4
> 1.修复服务发现没有watch
### v1.0.3
> 1.添加推送包ver=1
### v1.0.2
> 1. fix bug
### v1.0.1
> 1. fix golint
### v1.0.0
> 1. init

View File

@@ -0,0 +1,14 @@
# Owner
chenzhihui
caoguoliang
guhao
# Author
chenzhihui
caoguoliang
guhao
# Reviewer
chenzhihui
caoguoliang
guhao

View File

@@ -0,0 +1,16 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- caoguoliang
- chenzhihui
- guhao
labels:
- job
- job/main/broadcast
- main
options:
no_parent_owners: true
reviewers:
- caoguoliang
- chenzhihui
- guhao

View File

@@ -0,0 +1,44 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_binary",
"go_library",
)
go_binary(
name = "cmd",
embed = [":go_default_library"],
tags = ["automanaged"],
)
go_library(
name = "go_default_library",
srcs = ["main.go"],
data = ["broadcast-job.toml"],
importpath = "go-common/app/job/main/broadcast/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/broadcast/conf:go_default_library",
"//app/job/main/broadcast/server/http:go_default_library",
"//app/job/main/broadcast/service:go_default_library",
"//library/conf/paladin:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,46 @@
# This is a TOML document. Boom
debug = true
[log]
stdout=true
[push]
chan = 16
size = 100
[routine]
chan = 16
size = 100
[room]
batch = 40
signal = "1s"
refresh = "5s"
[rpc]
dial = "1s"
timeout = "1s"
[databus]
key = "170e302355453683"
secret = "3d0e8db7bed0503949e545a469789279"
group = "ZergJob-MainCommunity-S"
topic = "ZergJob-T"
action ="sub"
name = "zerg/service"
proto = "tcp"
addr = "172.18.33.50:6205"
idle = 2
active = 5
offset = "old"
dialTimeout = "1s"
readTimeout = "60s"
writeTimeout = "1s"
idleTimeout = "10s"
expire = "1h"
[discovery]
domain = "api.bilibili.co"
key = "6a29f8ed87407c11"
secret = "d3c5a85f5b895a03735b5d20a273bc57"
env = "dev"
zone = "sh001"

View File

@@ -0,0 +1,46 @@
package main
import (
"flag"
"os"
"os/signal"
"syscall"
"go-common/app/job/main/broadcast/conf"
"go-common/app/job/main/broadcast/server/http"
"go-common/app/job/main/broadcast/service"
"go-common/library/conf/paladin"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
)
func main() {
flag.Parse()
if err := paladin.Init(); err != nil {
panic(err)
}
if err := paladin.Watch("broadcast-job.toml", conf.Conf); err != nil {
panic(err)
}
log.Init(conf.Conf.Log)
defer log.Close()
log.Info("broadcast job start")
ecode.Init(conf.Conf.Ecode)
svc := service.New(conf.Conf)
http.Init(conf.Conf)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("broadcast get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
log.Info("broadcast exit")
svc.Close()
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@@ -0,0 +1,38 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["conf.go"],
importpath = "go-common/app/job/main/broadcast/conf",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/ecode/tip:go_default_library",
"//library/log:go_default_library",
"//library/naming/discovery:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/rpc/warden:go_default_library",
"//library/queue/databus:go_default_library",
"//library/time:go_default_library",
"//vendor/github.com/BurntSushi/toml:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,55 @@
package conf
import (
ecode "go-common/library/ecode/tip"
"go-common/library/log"
"go-common/library/naming/discovery"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/rpc/warden"
"go-common/library/queue/databus"
xtime "go-common/library/time"
"github.com/BurntSushi/toml"
)
var (
// Conf config
Conf = &Config{}
)
// Config .
type Config struct {
Log *log.Config
Ecode *ecode.Config
HTTP *bm.ServerConfig
RPC *warden.ClientConfig
Databus *databus.Config
Discovery *discovery.Config
Routine *Routine
Room *Room
}
// Routine routine.
type Routine struct {
Size uint64
Chan uint64
}
// Room room.
type Room struct {
Refresh xtime.Duration
Idle xtime.Duration
Batch int
Signal xtime.Duration
Compress bool
}
// Set set config and decode.
func (c *Config) Set(text string) error {
var tmp Config
if _, err := toml.Decode(text, &tmp); err != nil {
return err
}
*c = tmp
return nil
}

View File

@@ -0,0 +1,33 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/job/main/broadcast/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/job/main/broadcast/conf:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,25 @@
package http
import (
"go-common/app/job/main/broadcast/conf"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
)
// Init init http.
func Init(c *conf.Config) {
engine := bm.DefaultServer(c.HTTP)
outerRouter(engine)
if err := engine.Start(); err != nil {
log.Error("bm.DefaultServer error(%v)", err)
panic(err)
}
}
func outerRouter(e *bm.Engine) {
e.Ping(ping)
}
func ping(c *bm.Context) {
}

View File

@@ -0,0 +1,58 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"comet.go",
"push.go",
"room.go",
"service.go",
],
importpath = "go-common/app/job/main/broadcast/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/interface/main/broadcast/api/grpc/v1:go_default_library",
"//app/job/main/broadcast/conf:go_default_library",
"//app/service/main/broadcast/libs/bytes:go_default_library",
"//app/service/main/broadcast/model:go_default_library",
"//library/conf/env:go_default_library",
"//library/log:go_default_library",
"//library/naming:go_default_library",
"//library/naming/discovery:go_default_library",
"//library/queue/databus:go_default_library",
"//library/time:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["service_test.go"],
embed = [":go_default_library"],
rundir = ".",
tags = ["automanaged"],
deps = [
"//app/job/main/broadcast/conf:go_default_library",
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
],
)

View File

@@ -0,0 +1,154 @@
package service
import (
"context"
"fmt"
"net/url"
"sync/atomic"
"time"
client "go-common/app/interface/main/broadcast/api/grpc/v1"
"go-common/app/job/main/broadcast/conf"
"go-common/library/log"
"go-common/library/naming"
)
// CometOptions comet options.
type CometOptions struct {
RoutineSize uint64
RoutineChan uint64
}
// Comet is a broadcast comet.
type Comet struct {
serverID string
broadcastClient client.ZergClient
pushChan []chan *client.PushMsgReq
roomChan []chan *client.BroadcastRoomReq
broadcastChan chan *client.BroadcastReq
pushChanNum uint64
roomChanNum uint64
options CometOptions
ctx context.Context
cancel context.CancelFunc
}
// Push push a user message.
func (c *Comet) Push(arg *client.PushMsgReq) (err error) {
idx := atomic.AddUint64(&c.pushChanNum, 1) % c.options.RoutineSize
c.pushChan[idx] <- arg
return
}
// BroadcastRoom broadcast a room message.
func (c *Comet) BroadcastRoom(arg *client.BroadcastRoomReq) (err error) {
idx := atomic.AddUint64(&c.roomChanNum, 1) % c.options.RoutineSize
c.roomChan[idx] <- arg
return
}
// Broadcast broadcast a message.
func (c *Comet) Broadcast(arg *client.BroadcastReq) (err error) {
c.broadcastChan <- arg
return
}
// process
func (c *Comet) process(pushChan chan *client.PushMsgReq, roomChan chan *client.BroadcastRoomReq, broadcastChan chan *client.BroadcastReq) {
var err error
for {
select {
case broadcastArg := <-broadcastChan:
_, err = c.broadcastClient.Broadcast(context.Background(), &client.BroadcastReq{
Proto: broadcastArg.Proto,
ProtoOp: broadcastArg.ProtoOp,
Speed: broadcastArg.Speed,
Platform: broadcastArg.Platform,
})
if err != nil {
log.Error("c.broadcastClient.Broadcast(%s, %v, reply) serverId:%d error(%v)", broadcastArg, c.serverID, err)
}
case roomArg := <-roomChan:
_, err = c.broadcastClient.BroadcastRoom(context.Background(), &client.BroadcastRoomReq{
RoomID: roomArg.RoomID,
Proto: roomArg.Proto,
})
if err != nil {
log.Error("c.broadcastClient.BroadcastRoom(%s, %v, reply) serverId:%d error(%v)", roomArg, c.serverID, err)
}
case pushArg := <-pushChan:
_, err = c.broadcastClient.PushMsg(context.Background(), &client.PushMsgReq{
Keys: pushArg.Keys,
Proto: pushArg.Proto,
ProtoOp: pushArg.ProtoOp,
})
if err != nil {
log.Error("c.broadcastClient.PushMsg(%s, %v, reply) serverId:%d error(%v)", pushArg, c.serverID, err)
}
case <-c.ctx.Done():
return
}
}
}
// Close close the resouces.
func (c *Comet) Close() (err error) {
finish := make(chan bool)
go func() {
for {
n := len(c.broadcastChan)
for _, ch := range c.pushChan {
n += len(ch)
}
for _, ch := range c.roomChan {
n += len(ch)
}
if n == 0 {
finish <- true
return
}
time.Sleep(time.Second)
}
}()
select {
case <-finish:
log.Info("close comet finish")
case <-time.After(5 * time.Second):
err = fmt.Errorf("close comet(server:%s push:%d room:%d broadcast:%d) timeout", c.serverID, len(c.pushChan), len(c.roomChan), len(c.broadcastChan))
}
c.cancel()
return
}
// NewComet new a comet.
func NewComet(data *naming.Instance, conf *conf.Config, options CometOptions) (*Comet, error) {
c := &Comet{
serverID: data.Hostname,
pushChan: make([]chan *client.PushMsgReq, options.RoutineSize),
roomChan: make([]chan *client.BroadcastRoomReq, options.RoutineSize),
broadcastChan: make(chan *client.BroadcastReq, options.RoutineSize),
options: options,
}
var grpcAddr string
for _, addrs := range data.Addrs {
u, err := url.Parse(addrs)
if err == nil && u.Scheme == "grpc" {
grpcAddr = u.Host
}
}
if grpcAddr == "" {
return nil, fmt.Errorf("invalid grpc address:%v", data.Addrs)
}
var err error
if c.broadcastClient, err = client.NewClient(grpcAddr, conf.RPC); err != nil {
return nil, err
}
c.ctx, c.cancel = context.WithCancel(context.Background())
for i := uint64(0); i < options.RoutineSize; i++ {
c.pushChan[i] = make(chan *client.PushMsgReq, options.RoutineChan)
c.roomChan[i] = make(chan *client.BroadcastRoomReq, options.RoutineChan)
go c.process(c.pushChan[i], c.roomChan[i], c.broadcastChan)
}
return c, nil
}

View File

@@ -0,0 +1,141 @@
package service
import (
"encoding/json"
"fmt"
pb "go-common/app/interface/main/broadcast/api/grpc/v1"
"go-common/app/service/main/broadcast/model"
"go-common/library/log"
)
const (
_pushMsg = "push"
_broadcastMsg = "broadcast"
_broadcastRoomMsg = "broadcast_room"
)
type databusMsg struct {
Type string `json:"type,omitempty"`
Operation int32 `json:"operation,omitempty"`
Server string `json:"server,omitempty"`
Keys []string `json:"keys,omitempty"`
Room string `json:"room,omitempty"`
Speed int32 `json:"speed,omitempty"`
Platform string `json:"platform,omitempty"`
ContentType int32 `json:"content_type,omitempty"`
Message json.RawMessage `json:"message,omitempty"`
}
func (s *Service) pushMsg(msg []byte) (err error) {
m := &databusMsg{}
if err = json.Unmarshal(msg, m); err != nil {
log.Error("json.Unmarshal(%s) error(%s)", msg, err)
return
}
log.Info("push message:%s", msg)
switch m.Type {
case _pushMsg:
if len(m.Keys) == 0 {
log.Error("service push keys is invalid:%+v", m)
return
}
s.pushKeys(m.Operation, m.Server, m.Keys, m.Message, m.ContentType)
case _broadcastMsg:
s.broadcast(m.Operation, m.Message, m.Speed, m.Platform, m.ContentType)
case _broadcastRoomMsg:
if m.Room == "" {
log.Error("service broadcast room is invalid:%+v", m)
return
}
if err = s.room(m.Room).Push(m.Operation, m.Message, m.ContentType); err != nil {
log.Error("room.Push(%s) roomId:%s error(%v)", m.Message, m.Room, err)
}
// NOTE: 弹幕兼容老协议推送等web播放器接完可以去掉了
if m.Operation == 1000 {
s.broadcastRoom(m.Room, 5, []byte(fmt.Sprintf(`{"cmd":"DM","info":%s}`, m.Message)))
}
default:
log.Error("unknown message type:%s", m.Type)
}
return
}
// pushKeys push a message to a batch of subkeys.
func (s *Service) pushKeys(operation int32, serverID string, subKeys []string, body []byte, contentType int32) {
p := &model.Proto{
Ver: 1,
Operation: operation,
ContentType: contentType,
Body: body,
}
var args = pb.PushMsgReq{
Keys: subKeys,
ProtoOp: operation,
Proto: p,
}
if c, ok := s.cometServers[serverID]; ok {
if err := c.Push(&args); err != nil {
log.Error("c.Push(%v) serverId:%s error(%v)", args, serverID, err)
}
}
}
// broadcast broadcast a message to all.
func (s *Service) broadcast(operation int32, body []byte, speed int32, platform string, contentType int32) {
p := &model.Proto{
Ver: 1,
Operation: operation,
ContentType: contentType,
Body: body,
}
comets := s.cometServers
speed /= int32(len(comets))
var args = pb.BroadcastReq{
ProtoOp: operation,
Proto: p,
Speed: speed,
Platform: platform,
}
for serverID, c := range comets {
if err := c.Broadcast(&args); err != nil {
log.Error("c.Broadcast(%v) serverId:%s error(%v)", args, serverID, err)
}
}
}
// broadcastRoomRawBytes broadcast aggregation messages to room.
func (s *Service) broadcastRoomRawBytes(roomID string, body []byte) {
args := pb.BroadcastRoomReq{
RoomID: roomID,
Proto: &model.Proto{
Ver: 1,
Operation: model.OpRaw,
Body: body,
},
}
comets := s.cometServers
for serverID, c := range comets {
if err := c.BroadcastRoom(&args); err != nil {
log.Error("c.BroadcastRoom(%v) roomID:%s serverId:%s error(%v)", args, roomID, serverID, err)
}
}
}
// broadcastRoom broadcast messages to room.
func (s *Service) broadcastRoom(roomID string, op int32, body []byte) {
args := pb.BroadcastRoomReq{
RoomID: roomID,
Proto: &model.Proto{
Ver: 1,
Operation: op,
Body: body,
},
}
comets := s.cometServers
for serverID, c := range comets {
if err := c.BroadcastRoom(&args); err != nil {
log.Error("c.BroadcastRoom(%v) roomID:%s serverId:%s error(%v)", args, roomID, serverID, err)
}
}
}

View File

@@ -0,0 +1,106 @@
package service
import (
"time"
"go-common/app/service/main/broadcast/libs/bytes"
"go-common/app/service/main/broadcast/model"
"go-common/library/log"
)
// RoomOptions room options.
type RoomOptions struct {
BatchNum int
SignalTime time.Duration
}
// Room room.
type Room struct {
s *Service
id string
proto chan *model.Proto
}
var (
roomReadyProto = new(model.Proto)
)
// NewRoom new a room struct, store channel room info.
func NewRoom(s *Service, id string, options RoomOptions) (r *Room) {
r = &Room{
s: s,
id: id,
proto: make(chan *model.Proto, options.BatchNum*2),
}
go r.pushproc(options.BatchNum, options.SignalTime)
return
}
// Push push msg to the room, if chan full discard it.
func (r *Room) Push(op int32, msg []byte, contentType int32) (err error) {
var p = &model.Proto{
Ver: 1,
Operation: op,
ContentType: contentType,
Body: msg,
}
select {
case r.proto <- p:
default:
err = ErrRoomFull
}
return
}
// pushproc merge proto and push msgs in batch.
func (r *Room) pushproc(batch int, sigTime time.Duration) {
var (
n int
last time.Time
p *model.Proto
buf = bytes.NewWriterSize(int(model.MaxBodySize))
)
log.Info("start room:%s goroutine", r.id)
td := time.AfterFunc(sigTime, func() {
select {
case r.proto <- roomReadyProto:
default:
}
})
defer td.Stop()
for {
if p = <-r.proto; p == nil {
break // exit
} else if p != roomReadyProto {
// merge buffer ignore error, always nil
p.WriteTo(buf)
if n++; n == 1 {
last = time.Now()
td.Reset(sigTime)
continue
} else if n < batch {
if sigTime > time.Since(last) {
continue
}
}
} else {
if n == 0 {
break
}
}
r.s.broadcastRoomRawBytes(r.id, buf.Buffer())
// TODO use reset buffer
// after push to room channel, renew a buffer, let old buffer gc
buf = bytes.NewWriterSize(buf.Size())
n = 0
if r.s.conf.Room.Idle != 0 {
td.Reset(time.Duration(r.s.conf.Room.Idle))
} else {
td.Reset(time.Minute)
}
}
r.s.roomsMutex.Lock()
delete(r.s.rooms, r.id)
r.s.roomsMutex.Unlock()
log.Info("room:%s goroutine exit", r.id)
}

View File

@@ -0,0 +1,175 @@
package service
import (
"context"
"errors"
"fmt"
"sync"
"time"
"go-common/app/job/main/broadcast/conf"
"go-common/library/conf/env"
"go-common/library/log"
"go-common/library/naming"
"go-common/library/naming/discovery"
"go-common/library/queue/databus"
xtime "go-common/library/time"
)
const (
broadcastAppID = "push.interface.broadcast"
)
var (
// ErrComet commet error.
ErrComet = errors.New("comet rpc is not available")
// ErrCometFull comet chan full.
ErrCometFull = errors.New("comet proto chan full")
// ErrRoomFull room chan full.
ErrRoomFull = errors.New("room proto chan full")
)
// Service is a service.
type Service struct {
conf *conf.Config
consumer *databus.Databus
cometServers map[string]*Comet
rooms map[string]*Room
roomsMutex sync.RWMutex
options RoomOptions
}
// New new a service and return.
func New(c *conf.Config) *Service {
if c.Room.Refresh <= 0 {
c.Room.Refresh = xtime.Duration(time.Second)
}
s := &Service{
conf: c,
consumer: databus.New(c.Databus),
cometServers: make(map[string]*Comet),
rooms: make(map[string]*Room, 1024),
roomsMutex: sync.RWMutex{},
options: RoomOptions{
BatchNum: c.Room.Batch,
SignalTime: time.Duration(c.Room.Signal),
},
}
dis := discovery.New(c.Discovery)
s.watchComet(dis.Build(broadcastAppID))
go s.consume()
return s
}
func (s *Service) consume() {
msgs := s.consumer.Messages()
for {
msg, ok := <-msgs
if !ok {
log.Warn("[job] consumer has been closed")
return
}
if msg.Topic != s.conf.Databus.Topic {
log.Error("unknown message:%v", msg)
continue
}
s.pushMsg(msg.Value)
msg.Commit()
}
}
// Close close the resources.
func (s *Service) Close() error {
if err := s.consumer.Close(); err != nil {
return err
}
for _, c := range s.cometServers {
if err := c.Close(); err != nil {
log.Error("c.Close() error(%v)", err)
}
}
return nil
}
func (s *Service) watchComet(resolver naming.Resolver) {
event := resolver.Watch()
select {
case _, ok := <-event:
if !ok {
panic("watchComet init failed")
}
if ins, ok := resolver.Fetch(context.Background()); ok {
if err := s.newAddress(ins); err != nil {
panic(err)
}
log.Info("watchComet init newAddress:%+v", ins)
}
case <-time.After(10 * time.Second):
log.Error("watchComet init instances timeout")
}
go func() {
for {
if _, ok := <-event; !ok {
log.Info("watchComet exit")
return
}
ins, ok := resolver.Fetch(context.Background())
if ok {
if err := s.newAddress(ins); err != nil {
log.Error("watchComet newAddress(%+v) error(%+v)", ins, err)
continue
}
log.Info("watchComet change newAddress:%+v", ins)
}
}
}()
}
func (s *Service) newAddress(insMap map[string][]*naming.Instance) error {
ins := insMap[env.Zone]
if len(ins) == 0 {
return fmt.Errorf("watchComet instance is empty")
}
comets := map[string]*Comet{}
options := CometOptions{
RoutineSize: s.conf.Routine.Size,
RoutineChan: s.conf.Routine.Chan,
}
for _, data := range ins {
if old, ok := s.cometServers[data.Hostname]; ok {
comets[data.Hostname] = old
continue
}
c, err := NewComet(data, s.conf, options)
if err != nil {
log.Error("watchComet NewComet(%+v) error(%v)", data, err)
return err
}
comets[data.Hostname] = c
log.Info("watchComet AddComet grpc:%+v", data)
}
for key, old := range s.cometServers {
if _, ok := comets[key]; !ok {
old.cancel()
log.Info("watchComet DelComet:%s", key)
}
}
s.cometServers = comets
return nil
}
func (s *Service) room(roomID string) *Room {
s.roomsMutex.RLock()
room, ok := s.rooms[roomID]
s.roomsMutex.RUnlock()
if !ok {
s.roomsMutex.Lock()
if room, ok = s.rooms[roomID]; !ok {
room = NewRoom(s, roomID, s.options)
s.rooms[roomID] = room
}
s.roomsMutex.Unlock()
log.Info("new a room:%s active:%d", roomID, len(s.rooms))
}
return room
}

View File

@@ -0,0 +1,38 @@
package service
import (
"testing"
"go-common/app/job/main/broadcast/conf"
. "github.com/smartystreets/goconvey/convey"
)
func TestNewService(t *testing.T) {
Convey("TestNewService", t, func() {
s := New(conf.Conf)
So(s, ShouldNotBeNil)
Convey("TestPush", func() {
err := s.pushMsg([]byte("test"))
So(err, ShouldBeNil)
})
Convey("TestPushComet", func() {
s.pushKeys(1, "test", nil, []byte("test"), 0)
})
Convey("TestBroadCast", func() {
s.broadcast(1, []byte("test"), 100, "", 0)
})
Convey("TestBroadCast", func() {
s.broadcastRoomRawBytes("1", []byte("test"))
})
Convey("TestNewRoom", func() {
r := NewRoom(s, "test", RoomOptions{})
So(r, ShouldNotBeNil)
Convey("TestNewPush", func() {
err := r.Push(7, []byte("test"), 0)
So(err, ShouldBeNil)
})
})
})
}