Optimize router. (#144)
diff --git a/pkg/chain/callback.go b/pkg/chain/callback.go
index 74ea53a..efefc95 100644
--- a/pkg/chain/callback.go
+++ b/pkg/chain/callback.go
@@ -14,6 +14,7 @@
package chain
import (
+ "fmt"
"github.com/ServiceComb/service-center/pkg/util"
)
@@ -23,17 +24,28 @@
Args []interface{}
}
-type CallbackFunc func(r Result)
+func (r Result) String() string {
+ if r.OK {
+ return "OK"
+ }
+ return fmt.Sprintf("FAIL(error: %s)", r.Err)
+}
type Callback struct {
- Func CallbackFunc
+ Func func(r Result)
}
func (cb *Callback) Invoke(r Result) {
- go func() {
- defer util.RecoverAndReport()
- cb.Func(r)
- }()
+ go cb.syncInvoke(r)
+}
+
+func (cb *Callback) syncInvoke(r Result) {
+ defer util.RecoverAndReport()
+ if cb.Func == nil {
+ util.Logger().Errorf(nil, "Callback function is nil. result: %s,", r)
+ return
+ }
+ cb.Func(r)
}
func (cb *Callback) Fail(err error, args ...interface{}) {
@@ -50,9 +62,3 @@
Args: args,
})
}
-
-func NewCallback(f CallbackFunc) Callback {
- return Callback{
- Func: f,
- }
-}
diff --git a/pkg/chain/chain.go b/pkg/chain/chain.go
index 1db2de9..e958abf 100644
--- a/pkg/chain/chain.go
+++ b/pkg/chain/chain.go
@@ -14,25 +14,21 @@
package chain
import (
- "fmt"
+ errorsEx "github.com/ServiceComb/service-center/pkg/errors"
"github.com/ServiceComb/service-center/pkg/util"
- "sync"
)
-var handlersMap map[string][]Handler
-
type Chain struct {
name string
handlers []Handler
currentIndex int
- mux sync.Mutex
}
func (c *Chain) Init(chainName string, hs []Handler) {
c.name = chainName
c.currentIndex = -1
if len(hs) > 0 {
- c.handlers = make([]Handler, 0, len(hs))
+ c.handlers = make([]Handler, len(hs))
copy(c.handlers, hs)
}
}
@@ -41,17 +37,31 @@
return c.name
}
-func (c *Chain) doNext(i *Invocation) {
- defer util.RecoverAndReport()
+func (c *Chain) syncNext(i *Invocation) {
+ defer func() {
+ itf := recover()
+ if itf == nil {
+ return
+ }
+ util.Logger().Errorf(nil, "recover! %v", itf)
- if c.currentIndex >= len(c.handlers) {
- i.Fail(fmt.Errorf("Over end of chain '%s'", c.name))
+ i.Fail(errorsEx.RaiseError(itf))
+ }()
+
+ if c.currentIndex >= len(c.handlers)-1 {
+ i.Success()
return
}
c.currentIndex += 1
c.handlers[c.currentIndex].Handle(i)
}
-func (c *Chain) next(i *Invocation) {
- go c.doNext(i)
+func (c *Chain) Next(i *Invocation) {
+ go c.syncNext(i)
+}
+
+func NewChain(name string, handlers ...Handler) *Chain {
+ var ch Chain
+ ch.Init(name, handlers)
+ return &ch
}
diff --git a/pkg/chain/handler.go b/pkg/chain/handler.go
index f382848..3aba84d 100644
--- a/pkg/chain/handler.go
+++ b/pkg/chain/handler.go
@@ -13,6 +13,21 @@
//limitations under the License.
package chain
+var handlersMap map[string][]Handler = make(map[string][]Handler, CAP_SIZE)
+
type Handler interface {
Handle(i *Invocation)
}
+
+func RegisterHandler(catalog string, h Handler) {
+ handlers, ok := handlersMap[catalog]
+ if !ok {
+ handlers = make([]Handler, 0, CAP_SIZE)
+ }
+ handlers = append(handlers, h)
+ handlersMap[catalog] = handlers
+}
+
+func Handlers(catalog string) []Handler {
+ return handlersMap[catalog]
+}
diff --git a/pkg/chain/invocation.go b/pkg/chain/invocation.go
index b244b22..9365b40 100644
--- a/pkg/chain/invocation.go
+++ b/pkg/chain/invocation.go
@@ -17,7 +17,7 @@
"errors"
)
-const DEFAULT_MAP_SIZE = 10
+const CAP_SIZE = 10
type Invocation struct {
Callback
@@ -27,8 +27,8 @@
}
func (i *Invocation) Init(ch *Chain) {
- i.handlerContext = make(map[string]interface{}, DEFAULT_MAP_SIZE)
- i.context = make(map[string]interface{}, DEFAULT_MAP_SIZE)
+ i.handlerContext = make(map[string]interface{}, CAP_SIZE)
+ i.context = make(map[string]interface{}, CAP_SIZE)
i.chain = ch
}
@@ -50,11 +50,21 @@
return i
}
-func (i *Invocation) Next(f CallbackFunc) {
- i.Func = f
+func (i *Invocation) Next() {
if i.chain == nil {
i.Fail(errors.New("Can not find any chain for this invocation"))
return
}
- i.chain.next(i)
+ i.chain.Next(i)
+}
+
+func (i *Invocation) Invoke(f func(r Result)) {
+ i.Func = f
+ i.Next()
+}
+
+func NewInvocation(ch *Chain) *Invocation {
+ var inv Invocation
+ inv.Init(ch)
+ return &inv
}
diff --git a/pkg/errors/error.go b/pkg/errors/error.go
index 4b93625..1e35f79 100644
--- a/pkg/errors/error.go
+++ b/pkg/errors/error.go
@@ -13,8 +13,22 @@
//limitations under the License.
package errors
+import (
+ "fmt"
+)
+
type InternalError string
func (e InternalError) Error() string {
return string(e)
}
+
+func RaiseError(itf interface{}) InternalError {
+ if itf == nil {
+ return InternalError("panic: unknown")
+ }
+ if err, ok := itf.(error); ok {
+ return InternalError(err.Error())
+ }
+ return InternalError(fmt.Sprintf("%v", itf))
+}
diff --git a/pkg/rest/route.go b/pkg/rest/route.go
index 35a3eba..25959c7 100644
--- a/pkg/rest/route.go
+++ b/pkg/rest/route.go
@@ -18,7 +18,6 @@
"fmt"
"github.com/ServiceComb/service-center/pkg/util"
"net/http"
- "net/url"
"strings"
)
@@ -47,13 +46,13 @@
// 2. redirect not supported
type ROAServerHandler struct {
handlers map[string][]*urlPatternHandler
- filters []Filter
+ filters []Filter
}
func NewROAServerHander() *ROAServerHandler {
return &ROAServerHandler{
handlers: make(map[string][]*urlPatternHandler),
- filters: make([]Filter, 0, 5),
+ filters: make([]Filter, 0, 5),
}
}
@@ -76,7 +75,7 @@
for _, ph := range this.handlers[r.Method] {
if params, ok := ph.try(r.URL.Path); ok {
if len(params) > 0 {
- r.URL.RawQuery = url.Values(params).Encode() + "&" + r.URL.RawQuery
+ r.URL.RawQuery = util.UrlEncode(params) + "&" + r.URL.RawQuery
}
if err = this.doFilter(r); err != nil {
@@ -124,12 +123,13 @@
return nil
}
-func (this *urlPatternHandler) try(path string) (p map[string][]string, _ bool) {
+func (this *urlPatternHandler) try(path string) (p map[string]string, _ bool) {
var i, j int
- for i < len(path) {
+ l, sl := len(this.Path), len(path)
+ for i < sl {
switch {
- case j >= len(this.Path):
- if this.Path != "/" && len(this.Path) > 0 && this.Path[len(this.Path)-1] == '/' {
+ case j >= l:
+ if this.Path != "/" && l > 0 && this.Path[l-1] == '/' {
return p, true
}
return nil, false
@@ -141,9 +141,9 @@
val, _, i = match(path, matchParticial, nextc, i)
if p == nil {
- p = make(map[string][]string)
+ p = make(map[string]string, 5)
}
- p[this.Path[o:j]] = []string{val}
+ p[this.Path[o:j]] = val
case path[i] == this.Path[j]:
i++
j++
@@ -151,7 +151,7 @@
return nil, false
}
}
- if j != len(this.Path) {
+ if j != l {
return nil, false
}
return p, true
@@ -188,4 +188,4 @@
type Filter interface {
IsMatch(r *http.Request) bool
Do(r *http.Request) error
-}
\ No newline at end of file
+}
diff --git a/pkg/util/util.go b/pkg/util/util.go
index 015cc7c..6267c7e 100644
--- a/pkg/util/util.go
+++ b/pkg/util/util.go
@@ -209,10 +209,11 @@
}
}
-func RecoverAndReport() {
- if r := recover(); r != nil {
+func RecoverAndReport() (r interface{}) {
+ if r = recover(); r != nil {
Logger().Errorf(nil, "recover! %v", r)
}
+ return
}
func ParseEndpoint(ep string) (string, error) {
@@ -269,3 +270,15 @@
}
return
}
+
+func UrlEncode(keys map[string]string) string {
+ l := len(keys)
+ if l == 0 {
+ return ""
+ }
+ arr := make([]string, 0, l)
+ for k, v := range keys {
+ arr = append(arr, url.QueryEscape(k)+"="+url.QueryEscape(v))
+ }
+ return StringJoin(arr, "&")
+}