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  }