github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/api/pubsub/pubsub.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 // Package pubsub implements the API for streaming pubsub messages between api 5 // servers. 6 package pubsub 7 8 import ( 9 "github.com/juju/errors" 10 11 "github.com/juju/juju/api/base" 12 "github.com/juju/juju/apiserver/params" 13 ) 14 15 // MessageWriter is the interface that allows sending pub/sub messges to the 16 // server. 17 type MessageWriter interface { 18 // ForwardMessage forwards the given message to the server. 19 ForwardMessage(*params.PubSubMessage) error 20 Close() error 21 } 22 23 // API provides access to the pubsub API. 24 type API struct { 25 connector base.StreamConnector 26 } 27 28 // NewAPI creates a new client-side pubsub API. 29 func NewAPI(connector base.StreamConnector) *API { 30 return &API{connector: connector} 31 } 32 33 // OpenMessageWriter returns a new message writer interface value which must 34 // be closed when finished with. 35 func (api *API) OpenMessageWriter() (MessageWriter, error) { 36 conn, err := api.connector.ConnectStream("/pubsub", nil) 37 if err != nil { 38 return nil, errors.Annotatef(err, "cannot connect to /pubsub") 39 } 40 messageWriter := &writer{conn} 41 go messageWriter.readLoop() 42 return messageWriter, nil 43 } 44 45 type writer struct { 46 conn base.Stream 47 } 48 49 // readLoop is necessary for the client to process websocket control messages. 50 // Close() is safe to call concurrently. 51 func (w *writer) readLoop() { 52 for { 53 if _, _, err := w.conn.NextReader(); err != nil { 54 w.conn.Close() 55 break 56 } 57 } 58 } 59 60 func (w *writer) ForwardMessage(m *params.PubSubMessage) error { 61 // Note: due to the fire-and-forget nature of the 62 // pubsub API, it is possible that when the 63 // connection dies, any messages that were "in-flight" 64 // will not be received on the server side. 65 if err := w.conn.WriteJSON(m); err != nil { 66 return errors.Annotatef(err, "cannot send pubsub message") 67 } 68 return nil 69 } 70 71 func (w *writer) Close() error { 72 return w.conn.Close() 73 }