-
Notifications
You must be signed in to change notification settings - Fork 470
/
handler_chain.go
executable file
·137 lines (118 loc) · 3.11 KB
/
handler_chain.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package handler
import (
"errors"
"fmt"
"strings"
"github.com/go-chassis/go-chassis/core/common"
"github.com/go-chassis/go-chassis/core/invocation"
"github.com/go-chassis/go-chassis/core/lager"
)
var errEmptyChain = errors.New("chain can not be empty")
// ChainMap just concurrent read
var ChainMap = make(map[string]*Chain)
// Chain struct for service and handlers
type Chain struct {
ServiceType string
Name string
Handlers []Handler
HandlerIndex int
}
// AddHandler chain can add a handler
func (c *Chain) AddHandler(h Handler) {
c.Handlers = append(c.Handlers, h)
}
// Next is for to handle next handler in the chain
func (c *Chain) Next(i *invocation.Invocation, f invocation.ResponseCallBack) {
index := c.HandlerIndex
if index >= len(c.Handlers) {
r := &invocation.Response{
Err: nil,
}
f(r)
return
}
c.HandlerIndex++
c.Handlers[index].Handle(c, i, f)
}
// Reset for to reset the handler index
func (c *Chain) Reset() {
c.HandlerIndex = 0
}
// ChainOptions chain options
type ChainOptions struct {
Name string
}
// ChainOption is a function name
type ChainOption func(*ChainOptions)
// WithChainName returns the name of the chain option
func WithChainName(name string) ChainOption {
return func(c *ChainOptions) {
c.Name = name
}
}
// parseHandlers for parsing the handlers
func parseHandlers(handlerStr string) []string {
formatNames := strings.Replace(strings.TrimSpace(handlerStr), " ", "", -1)
handlerNames := strings.Split(formatNames, ",")
var s []string
//delete empty string
for _, v := range handlerNames {
if v != "" {
s = append(s, v)
}
}
return s
}
// CreateChains is for to create the chains
func CreateChains(chainType string, handlerNameMap map[string]string) error {
for chainName := range handlerNameMap {
handlerNames := parseHandlers(handlerNameMap[chainName])
c, err := CreateChain(chainType, chainName, handlerNames...)
if err != nil {
return fmt.Errorf("err create chain %s.%s:%s %s", chainType, chainName, handlerNames, err.Error())
}
ChainMap[chainType+chainName] = c
}
return nil
}
//CreateChain create consumer or provider's chain,the final handler is different
func CreateChain(serviceType string, chainName string, handlerNames ...string) (*Chain, error) {
c := &Chain{
ServiceType: serviceType,
Name: chainName,
}
lager.Logger.Debugf("add [%d] handlers for chain [%s]", len(handlerNames), chainName)
for _, name := range handlerNames {
err := addHandler(c, name)
if err != nil {
return nil, err
}
}
if len(c.Handlers) == 0 {
lager.Logger.Warnf("Chain "+chainName+" is Empty", errEmptyChain)
return c, nil
}
return c, nil
}
// addHandler add handler
func addHandler(c *Chain, name string) error {
handler, err := CreateHandler(name)
if err != nil {
return err
}
c.AddHandler(handler)
return nil
}
// GetChain is to get chain
func GetChain(serviceType string, name string) (*Chain, error) {
if name == "" {
name = common.DefaultChainName
}
c := &Chain{}
origin, ok := ChainMap[serviceType+name]
if !ok {
return nil, fmt.Errorf("get chain [%s] failed", serviceType+name)
}
*c = *origin
return c, nil
}