github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/rpc/observers.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package rpc 5 6 import "sync" 7 8 // Observer can be implemented to find out about requests occurring in 9 // an RPC conn, for example to print requests for logging 10 // purposes. The calls should not block or interact with the Conn 11 // object as that can cause delays to the RPC server or deadlock. 12 type Observer interface { 13 14 // ServerRequest informs the Observer of a request made 15 // to the Conn. If the request was not recognized or there was 16 // an error reading the body, body will be nil. 17 // 18 // ServerRequest is called just before the server method 19 // is invoked. 20 ServerRequest(hdr *Header, body interface{}) 21 22 // ServerReply informs the RequestNotifier of a reply sent to a 23 // server request. The given Request gives details of the call 24 // that was made; the given Header and body are the header and 25 // body sent as reply. 26 // 27 // ServerReply is called just before the reply is written. 28 ServerReply(req Request, hdr *Header, body interface{}) 29 } 30 31 // ObserverFactory is a type which can construct a new Observer. 32 type ObserverFactory interface { 33 // RPCObserver will return a new Observer usually constructed 34 // from the state previously built up in the Observer. The 35 // returned instance will be utilized per RPC request. 36 RPCObserver() Observer 37 } 38 39 // NewObserverMultiplexer returns a new ObserverMultiplexer 40 // with the provided RequestNotifiers. 41 func NewObserverMultiplexer(rpcObservers ...Observer) *ObserverMultiplexer { 42 return &ObserverMultiplexer{ 43 rpcObservers: rpcObservers, 44 } 45 } 46 47 // ObserverMultiplexer multiplexes calls to an arbitrary number of 48 // Observers. 49 type ObserverMultiplexer struct { 50 rpcObservers []Observer 51 } 52 53 // ServerReply implements Observer. 54 func (m *ObserverMultiplexer) ServerReply(req Request, hdr *Header, body interface{}) { 55 mapConcurrent(func(n Observer) { n.ServerReply(req, hdr, body) }, m.rpcObservers) 56 } 57 58 // ServerRequest implements Observer. 59 func (m *ObserverMultiplexer) ServerRequest(hdr *Header, body interface{}) { 60 mapConcurrent(func(n Observer) { n.ServerRequest(hdr, body) }, m.rpcObservers) 61 } 62 63 // mapConcurrent calls fn on all observers concurrently and then waits 64 // for all calls to exit before returning. 65 func mapConcurrent(fn func(Observer), requestNotifiers []Observer) { 66 var wg sync.WaitGroup 67 wg.Add(len(requestNotifiers)) 68 defer wg.Wait() 69 70 for _, n := range requestNotifiers { 71 go func(notifier Observer) { 72 defer wg.Done() 73 fn(notifier) 74 }(n) 75 } 76 }