ing
This commit is contained in:
parent
6d937770d3
commit
cf875b8b32
6
external/external.go
vendored
6
external/external.go
vendored
|
@ -1,11 +1,9 @@
|
||||||
package external
|
package external
|
||||||
|
|
||||||
import "git.loafle.net/overflow/gateway/external/grpc"
|
|
||||||
|
|
||||||
func InitPackage() {
|
func InitPackage() {
|
||||||
grpc.InitPackage()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func DestroyPackage() {
|
func DestroyPackage() {
|
||||||
grpc.DestroyPackage()
|
|
||||||
}
|
}
|
||||||
|
|
2
external/grpc/grpc.go
vendored
2
external/grpc/grpc.go
vendored
|
@ -14,11 +14,13 @@ import (
|
||||||
var grpcClient oci.OverflowApiServerClient
|
var grpcClient oci.OverflowApiServerClient
|
||||||
|
|
||||||
func InitPackage() {
|
func InitPackage() {
|
||||||
|
go func() {
|
||||||
conn, err := grpc.Dial("192.168.1.50:50006", grpc.WithInsecure())
|
conn, err := grpc.Dial("192.168.1.50:50006", grpc.WithInsecure())
|
||||||
if nil != err {
|
if nil != err {
|
||||||
logging.Logger().Panic(err)
|
logging.Logger().Panic(err)
|
||||||
}
|
}
|
||||||
grpcClient = oci.NewOverflowApiServerClient(conn)
|
grpcClient = oci.NewOverflowApiServerClient(conn)
|
||||||
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
46
external/kafka/kafka.go
vendored
Normal file
46
external/kafka/kafka.go
vendored
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
package kafka
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.loafle.net/commons/logging-go"
|
||||||
|
"github.com/segmentio/kafka-go"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
kafkaWriter *kafka.Writer
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitPackage() {
|
||||||
|
go func() {
|
||||||
|
kafkaWriter = kafka.NewWriter(kafka.WriterConfig{
|
||||||
|
Brokers: []string{"192.168.1.50:9092"},
|
||||||
|
Topic: "overflow-metric-topic",
|
||||||
|
Balancer: &kafka.LeastBytes{},
|
||||||
|
})
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DestroyPackage() {
|
||||||
|
go func() {
|
||||||
|
if err := kafkaWriter.Close(); nil != err {
|
||||||
|
logging.Logger().Errorf("%v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Write(key []byte, value []byte) error {
|
||||||
|
if nil == kafkaWriter {
|
||||||
|
return fmt.Errorf("Kafka client is not valid")
|
||||||
|
}
|
||||||
|
|
||||||
|
err := kafkaWriter.WriteMessages(context.Background(),
|
||||||
|
kafka.Message{
|
||||||
|
Key: key,
|
||||||
|
Value: value,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
26
external/redis/redis.go
vendored
Normal file
26
external/redis/redis.go
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/gomodule/redigo/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Pool *redis.Pool
|
||||||
|
|
||||||
|
func InitPackage() {
|
||||||
|
go func() {
|
||||||
|
Pool = &redis.Pool{
|
||||||
|
MaxIdle: 1,
|
||||||
|
MaxActive: 3,
|
||||||
|
IdleTimeout: 240,
|
||||||
|
Wait: true,
|
||||||
|
MaxConnLifetime: 1,
|
||||||
|
Dial: func() (redis.Conn, error) {
|
||||||
|
return redis.Dial("tcp", "192.168.1.50:6379")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func DestroyPackage() {
|
||||||
|
Pool.Close()
|
||||||
|
}
|
|
@ -4,3 +4,6 @@ import:
|
||||||
- package: git.loafle.net/commons/logging-go
|
- package: git.loafle.net/commons/logging-go
|
||||||
- package: google.golang.org/grpc
|
- package: google.golang.org/grpc
|
||||||
version: ^1.11.2
|
version: ^1.11.2
|
||||||
|
- package: github.com/gomodule/redigo
|
||||||
|
version: ^2.0.0
|
||||||
|
- package: github.com/segmentio/kafka-go
|
||||||
|
|
69
subscribe/message.go
Normal file
69
subscribe/message.go
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
package subscribe
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Message struct {
|
||||||
|
TargetType TargetType `json:"targetType"`
|
||||||
|
Targets []string `json:"targets"`
|
||||||
|
MessageRaw *json.RawMessage `json:"message"`
|
||||||
|
Message []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type MessageBody struct {
|
||||||
|
Version string `json:"jsonrpc"`
|
||||||
|
Method string `json:"method"`
|
||||||
|
Params interface{} `json:"params,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type TargetType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
MEMBER_SESSION TargetType = iota
|
||||||
|
MEMBER
|
||||||
|
PROBE
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
targetTypeID = map[TargetType]string{
|
||||||
|
MEMBER_SESSION: "MEMBER_SESSION",
|
||||||
|
MEMBER: "MEMBER",
|
||||||
|
PROBE: "PROBE",
|
||||||
|
}
|
||||||
|
|
||||||
|
targetTypeName = map[string]TargetType{
|
||||||
|
"MEMBER_SESSION": MEMBER_SESSION,
|
||||||
|
"MEMBER": MEMBER,
|
||||||
|
"PROBE": PROBE,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (st TargetType) String() string {
|
||||||
|
return targetTypeID[st]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st TargetType) MarshalJSON() ([]byte, error) {
|
||||||
|
value, ok := targetTypeID[st]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("Invalid EnumType[%s] value", st)
|
||||||
|
}
|
||||||
|
return json.Marshal(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (st TargetType) UnmarshalJSON(b []byte) error {
|
||||||
|
// unmarshal as string
|
||||||
|
var s string
|
||||||
|
err := json.Unmarshal(b, &s)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
value, ok := targetTypeName[s]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("Invalid EnumType[%s] value", s)
|
||||||
|
}
|
||||||
|
st = value
|
||||||
|
return nil
|
||||||
|
}
|
135
subscribe/redis/redis.go
Normal file
135
subscribe/redis/redis.go
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
logging "git.loafle.net/commons/logging-go"
|
||||||
|
"git.loafle.net/overflow/gateway/subscribe"
|
||||||
|
"github.com/gomodule/redigo/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
func New(conn redis.Conn) subscribe.Subscriber {
|
||||||
|
return &Subscribers{
|
||||||
|
Conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Subscribers struct {
|
||||||
|
Conn redis.Conn
|
||||||
|
pubSubConn *redis.PubSubConn
|
||||||
|
subscriptions map[string]chan *subscribe.Message
|
||||||
|
|
||||||
|
stopChan chan struct{}
|
||||||
|
stopWg sync.WaitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Subscribers) Start() error {
|
||||||
|
if s.stopChan != nil {
|
||||||
|
return fmt.Errorf("Subscriber: already running. Stop it before starting it again")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil == s.Conn {
|
||||||
|
return fmt.Errorf("Subscriber: Conn is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil == s.subscriptions {
|
||||||
|
s.subscriptions = make(map[string]chan *subscribe.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.pubSubConn = &redis.PubSubConn{Conn: s.Conn}
|
||||||
|
|
||||||
|
s.stopChan = make(chan struct{})
|
||||||
|
|
||||||
|
s.stopWg.Add(1)
|
||||||
|
go s.handleSubscriber()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Subscribers) Stop() error {
|
||||||
|
if s.stopChan == nil {
|
||||||
|
return fmt.Errorf("Subscriber: must be started before stopping it")
|
||||||
|
}
|
||||||
|
close(s.stopChan)
|
||||||
|
s.stopWg.Wait()
|
||||||
|
s.stopChan = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Subscribers) Subscribe(channel string) (chan<- *subscribe.Message, error) {
|
||||||
|
if _, ok := s.subscriptions[channel]; ok {
|
||||||
|
return nil, subscribe.ChannelExistError{Channel: channel}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.pubSubConn.Subscribe(channel); nil != err {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
msgChan := make(chan *subscribe.Message)
|
||||||
|
s.subscriptions[channel] = msgChan
|
||||||
|
|
||||||
|
return msgChan, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Subscribers) Unsubscribe(channel string) error {
|
||||||
|
msgChan, ok := s.subscriptions[channel]
|
||||||
|
if !ok {
|
||||||
|
return subscribe.ChannelIsNotExistError{Channel: channel}
|
||||||
|
}
|
||||||
|
delete(s.subscriptions, channel)
|
||||||
|
close(msgChan)
|
||||||
|
|
||||||
|
return s.pubSubConn.Unsubscribe(channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Subscribers) handleSubscriber() {
|
||||||
|
var (
|
||||||
|
receive interface{}
|
||||||
|
)
|
||||||
|
defer func() {
|
||||||
|
if nil != s.subscriptions {
|
||||||
|
for _, msgChan := range s.subscriptions {
|
||||||
|
close(msgChan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if nil != s.pubSubConn {
|
||||||
|
s.pubSubConn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
s.stopWg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
receiveChan := make(chan interface{})
|
||||||
|
|
||||||
|
for {
|
||||||
|
go func() {
|
||||||
|
receive = s.pubSubConn.Receive()
|
||||||
|
receiveChan <- receive
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case msg := <-receiveChan:
|
||||||
|
switch v := msg.(type) {
|
||||||
|
case redis.Message:
|
||||||
|
msgChan, ok := s.subscriptions[v.Channel]
|
||||||
|
if !ok {
|
||||||
|
logging.Logger().Warnf("Subscriber: Channel[%s] is not exist", v.Channel)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
message := &subscribe.Message{}
|
||||||
|
if err := json.Unmarshal(v.Data, message); nil != err {
|
||||||
|
logging.Logger().Errorf("Subscriber: Cannot unmarshal data[%s] of Channel[%s] %v", string(v.Data), v.Channel, err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
msgChan <- message
|
||||||
|
case redis.Subscription:
|
||||||
|
case error:
|
||||||
|
}
|
||||||
|
case <-s.stopChan:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
29
subscribe/subscriber.go
Normal file
29
subscribe/subscriber.go
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
package subscribe
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
type ChannelExistError struct {
|
||||||
|
Channel string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns the formatted configuration error.
|
||||||
|
func (cee ChannelExistError) Error() string {
|
||||||
|
return fmt.Sprintf("Subscriber: Channel[%q] is already subscribed.", cee.Channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ChannelIsNotExistError struct {
|
||||||
|
Channel string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error returns the formatted configuration error.
|
||||||
|
func (cinee ChannelIsNotExistError) Error() string {
|
||||||
|
return fmt.Sprintf("Subscriber: Channel[%q] is not subscribed.", cinee.Channel)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Subscriber interface {
|
||||||
|
Start() error
|
||||||
|
Stop() error
|
||||||
|
|
||||||
|
Subscribe(channel string) (chan<- *Message, error)
|
||||||
|
Unsubscribe(channel string) error
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user