Skip to content

Commit b9112ab

Browse files
committed
kite: add FinalFunc
1 parent 6c61c2b commit b9112ab

File tree

4 files changed

+78
-14
lines changed

4 files changed

+78
-14
lines changed

kite.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ type Kite struct {
7171
handlers map[string]*Method // method map for exported methods
7272
preHandlers []Handler // a list of handlers that are executed before any handler
7373
postHandlers []Handler // a list of handlers that are executed after any handler
74+
finalFuncs []FinalFunc // a list of funcs executed after any handler regardless of the error
7475

7576
// MethodHandling defines how the kite is returning the response for
7677
// multiple handlers

kite_test.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package kite
33
import (
44
"errors"
55
"fmt"
6+
"math"
67
"math/rand"
78
"os"
89
"strconv"
@@ -311,6 +312,18 @@ func TestKite(t *testing.T) {
311312
mathKite.HandleFunc("square", Square)
312313
mathKite.HandleFunc("squareCB", SquareCB)
313314
mathKite.HandleFunc("sleep", Sleep)
315+
mathKite.HandleFunc("sqrt", Sqrt)
316+
mathKite.FinalFunc(func(r *Request, resp interface{}, err error) (interface{}, error) {
317+
if r.Method != "sqrt" || err != ErrNegative {
318+
return resp, err
319+
}
320+
321+
a := r.Args.One().MustFloat64()
322+
323+
// JSON does not marshal complex128,
324+
// for test purpose we use just string
325+
return fmt.Sprintf("%di", int(math.Sqrt(-a)+0.5)), nil
326+
})
314327
go mathKite.Run()
315328
<-mathKite.ServerReadyNotify()
316329
defer mathKite.Close()
@@ -333,7 +346,16 @@ func TestKite(t *testing.T) {
333346
}
334347
defer remote.Close()
335348

336-
result, err := remote.TellWithTimeout("square", 4*time.Second, 2)
349+
result, err := remote.TellWithTimeout("sqrt", 4*time.Second, -4)
350+
if err != nil {
351+
t.Fatal(err)
352+
}
353+
354+
if s, err := result.String(); err != nil || s != "2i" {
355+
t.Fatalf("want 2i, got %v (%v)", result, err)
356+
}
357+
358+
result, err = remote.TellWithTimeout("square", 4*time.Second, 2)
337359
if err != nil {
338360
t.Fatal(err)
339361
}
@@ -410,6 +432,18 @@ func Square(r *Request) (interface{}, error) {
410432
return result, nil
411433
}
412434

435+
var ErrNegative = errors.New("negative argument")
436+
437+
func Sqrt(r *Request) (interface{}, error) {
438+
a := r.Args.One().MustFloat64()
439+
440+
if a < 0 {
441+
return nil, ErrNegative
442+
}
443+
444+
return math.Sqrt(a), nil
445+
}
446+
413447
// Calls the callback with the result. For testing requests with Callback.
414448
func SquareCB(r *Request) (interface{}, error) {
415449
args := r.Args.MustSliceOfLength(2)

method.go

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,22 @@ func (h HandlerFunc) ServeKite(r *Request) (interface{}, error) {
4040
return h(r)
4141
}
4242

43+
// FinalFunc represents a proxy function that is called last
44+
// in the method call chain, regardless whether whole call
45+
// chained succeeded with non-nil error or not.
46+
type FinalFunc func(r *Request, resp interface{}, err error) (interface{}, error)
47+
4348
// Method defines a method and the Handler it is bind to. By default
4449
// "ReturnMethod" handling is used.
4550
type Method struct {
4651
// name is the method name. Unnamed methods can exist
4752
name string
4853

4954
// handler contains the related Handler for the given method
50-
handler Handler // handler is the base handler, the response of it is returned as the final
51-
preHandlers []Handler // a list of handlers that are executed before the main handler
52-
postHandlers []Handler // a list of handlers that are executed after the main handler
55+
handler Handler // handler is the base handler, the response of it is returned as the final
56+
preHandlers []Handler // a list of handlers that are executed before the main handler
57+
postHandlers []Handler // a list of handlers that are executed after the main handler
58+
finalFuncs []FinalFunc // a list of final funcs executed upon returning from ServeKite
5359

5460
// authenticate defines if a given authenticator function is enabled for
5561
// the given auth type in the request.
@@ -78,8 +84,6 @@ func (k *Kite) addHandle(method string, handler Handler) *Method {
7884
m := &Method{
7985
name: method,
8086
handler: handler,
81-
preHandlers: make([]Handler, 0),
82-
postHandlers: make([]Handler, 0),
8387
authenticate: authenticate,
8488
handling: k.MethodHandling,
8589
}
@@ -142,6 +146,16 @@ func (m *Method) PostHandleFunc(handler HandlerFunc) *Method {
142146
return m.PostHandle(handler)
143147
}
144148

149+
// FinalFunc registers a funtion that is always called as a last one
150+
// after pre-, handler and post- functions for the given method.
151+
//
152+
// It receives a result and an error from last handler that
153+
// got executed prior to calling final func.
154+
func (m *Method) FinalFunc(f FinalFunc) *Method {
155+
m.finalFuncs = append(m.finalFuncs, f)
156+
return m
157+
}
158+
145159
// Handle registers the handler for the given method. The handler is called
146160
// when a method call is received from a Kite.
147161
func (k *Kite) Handle(method string, handler Handler) *Method {
@@ -181,6 +195,15 @@ func (k *Kite) PostHandleFunc(handler HandlerFunc) {
181195
k.PostHandle(handler)
182196
}
183197

198+
// FinalFunc registers a funtion that is always called as a last one
199+
// after pre-, handler and post- functions.
200+
//
201+
// It receives a result and an error from last handler that
202+
// got executed prior to calling final func.
203+
func (k *Kite) FinalFunc(f FinalFunc) {
204+
k.finalFuncs = append(k.finalFuncs, f)
205+
}
206+
184207
func (m *Method) ServeKite(r *Request) (interface{}, error) {
185208
var firstResp interface{}
186209
var resp interface{}
@@ -199,7 +222,7 @@ func (m *Method) ServeKite(r *Request) (interface{}, error) {
199222
for _, handler := range preHandlers {
200223
resp, err = handler.ServeKite(r)
201224
if err != nil {
202-
return nil, err
225+
return m.final(r, nil, err)
203226
}
204227

205228
if m.handling == ReturnFirst && resp != nil && firstResp == nil {
@@ -212,7 +235,7 @@ func (m *Method) ServeKite(r *Request) (interface{}, error) {
212235
// now call our base handler
213236
resp, err = m.handler.ServeKite(r)
214237
if err != nil {
215-
return nil, err
238+
return m.final(r, nil, err)
216239
}
217240

218241
// also save it dependent on the handling mechanism
@@ -233,7 +256,7 @@ func (m *Method) ServeKite(r *Request) (interface{}, error) {
233256
for _, handler := range postHandlers {
234257
resp, err = handler.ServeKite(r)
235258
if err != nil {
236-
return nil, err
259+
return m.final(r, nil, err)
237260
}
238261

239262
if m.handling == ReturnFirst && resp != nil && firstResp == nil {
@@ -245,12 +268,17 @@ func (m *Method) ServeKite(r *Request) (interface{}, error) {
245268

246269
switch m.handling {
247270
case ReturnMethod:
248-
return methodResp, nil
271+
resp = methodResp
249272
case ReturnFirst:
250-
return firstResp, nil
251-
case ReturnLatest:
252-
return resp, nil
273+
resp = firstResp
253274
}
254275

255-
return resp, nil
276+
return m.final(r, resp, nil)
277+
}
278+
279+
func (m *Method) final(r *Request, resp interface{}, err error) (interface{}, error) {
280+
for _, f := range m.finalFuncs {
281+
resp, err = f(r, resp, err)
282+
}
283+
return resp, err
256284
}

request.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func (c *Client) runMethod(method *Method, args *dnode.Partial) {
8989
if !method.initialized {
9090
method.preHandlers = append(method.preHandlers, c.LocalKite.preHandlers...)
9191
method.postHandlers = append(method.postHandlers, c.LocalKite.postHandlers...)
92+
method.finalFuncs = append(method.finalFuncs, c.LocalKite.finalFuncs...)
9293
method.initialized = true
9394
}
9495
method.mu.Unlock()

0 commit comments

Comments
 (0)