runMethod is called when a method is received from remote Kite.
(method *Method, args *dnode.Partial)
| 60 | |
| 61 | // runMethod is called when a method is received from remote Kite. |
| 62 | func (c *Client) runMethod(method *Method, args *dnode.Partial) { |
| 63 | var ( |
| 64 | callFunc func(interface{}, *Error) |
| 65 | request *Request |
| 66 | ) |
| 67 | |
| 68 | // Recover dnode argument errors and send them back. The caller can use |
| 69 | // functions like MustString(), MustSlice()... without the fear of panic. |
| 70 | defer func() { |
| 71 | if r := recover(); r != nil { |
| 72 | debug.PrintStack() |
| 73 | kiteErr := createError(request, r) |
| 74 | c.LocalKite.Log.Error(kiteErr.Error()) // let's log it too :) |
| 75 | callFunc(nil, kiteErr) |
| 76 | } |
| 77 | }() |
| 78 | |
| 79 | // The request that will be constructed from incoming dnode message. |
| 80 | request, callFunc = c.newRequest(method.name, args) |
| 81 | if method.authenticate { |
| 82 | if err := request.authenticate(); err != nil { |
| 83 | callFunc(nil, createError(request, err)) |
| 84 | return |
| 85 | } |
| 86 | } else { |
| 87 | // if not validated accept any username it sends, also useful for test |
| 88 | // cases. |
| 89 | request.Username = request.Client.Kite.Username |
| 90 | } |
| 91 | |
| 92 | method.mu.Lock() |
| 93 | if !method.initialized { |
| 94 | method.preHandlers = append(method.preHandlers, c.LocalKite.preHandlers...) |
| 95 | method.postHandlers = append(method.postHandlers, c.LocalKite.postHandlers...) |
| 96 | method.finalFuncs = append(method.finalFuncs, c.LocalKite.finalFuncs...) |
| 97 | method.initialized = true |
| 98 | } |
| 99 | method.mu.Unlock() |
| 100 | |
| 101 | // check if any throttling is enabled and then check token's available. |
| 102 | // Tokens are filled per frequency of the initial bucket, so every request |
| 103 | // is going to take one token from the bucket. If many requests come in (in |
| 104 | // span time larger than the bucket's frequency), there will be no token's |
| 105 | // available more so it will return a zero. |
| 106 | if method.bucket != nil && method.bucket.TakeAvailable(1) == 0 { |
| 107 | callFunc(nil, &Error{ |
| 108 | Type: "requestLimitError", |
| 109 | Message: "The maximum request rate is exceeded.", |
| 110 | RequestID: request.ID, |
| 111 | }) |
| 112 | return |
| 113 | } |
| 114 | |
| 115 | // Call the handler functions. |
| 116 | result, err := method.ServeKite(request) |
| 117 | |
| 118 | callFunc(result, createError(request, err)) |
| 119 | } |
no test coverage detected