github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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  // NewObserverMultiplexer returns a new ObserverMultiplexer
    32  // with the provided RequestNotifiers.
    33  func NewObserverMultiplexer(rpcObservers ...Observer) *ObserverMultiplexer {
    34  	return &ObserverMultiplexer{
    35  		rpcObservers: rpcObservers,
    36  	}
    37  }
    38  
    39  // ObserverMultiplexer multiplexes calls to an arbitrary number of
    40  // Observers.
    41  type ObserverMultiplexer struct {
    42  	rpcObservers []Observer
    43  }
    44  
    45  // ServerReply implements Observer.
    46  func (m *ObserverMultiplexer) ServerReply(req Request, hdr *Header, body interface{}) {
    47  	mapConcurrent(func(n Observer) { n.ServerReply(req, hdr, body) }, m.rpcObservers)
    48  }
    49  
    50  // ServerRequest implements Observer.
    51  func (m *ObserverMultiplexer) ServerRequest(hdr *Header, body interface{}) {
    52  	mapConcurrent(func(n Observer) { n.ServerRequest(hdr, body) }, m.rpcObservers)
    53  }
    54  
    55  // mapConcurrent calls fn on all observers concurrently and then waits
    56  // for all calls to exit before returning.
    57  func mapConcurrent(fn func(Observer), requestNotifiers []Observer) {
    58  	var wg sync.WaitGroup
    59  	wg.Add(len(requestNotifiers))
    60  	defer wg.Wait()
    61  
    62  	for _, n := range requestNotifiers {
    63  		go func(notifier Observer) {
    64  			defer wg.Done()
    65  			fn(notifier)
    66  		}(n)
    67  	}
    68  }