github.com/anycable/anycable-go@v1.5.1/cli/embed.go (about) 1 package cli 2 3 import ( 4 "context" 5 "fmt" 6 "net/http" 7 8 "github.com/anycable/anycable-go/broadcast" 9 "github.com/anycable/anycable-go/node" 10 "github.com/anycable/anycable-go/utils" 11 "github.com/anycable/anycable-go/version" 12 ) 13 14 // A minimal interface to the underlying Runner for embedding AnyCable into your own Go HTTP application. 15 type Embedded struct { 16 n *node.Node 17 r *Runner 18 } 19 20 // WebSocketHandler returns an HTTP handler to serve WebSocket connections via AnyCable. 21 func (e *Embedded) WebSocketHandler() (http.Handler, error) { 22 wsHandler, err := e.r.websocketHandlerFactory(e.n, e.r.config, e.r.log) 23 24 if err != nil { 25 return nil, err 26 } 27 28 return wsHandler, nil 29 } 30 31 // SSEHandler returns an HTTP handler to serve SSE connections via AnyCable. 32 // Please, provide your HTTP server's shutdown context to terminate SSE connections gracefully 33 // on server shutdown. 34 func (e *Embedded) SSEHandler(ctx context.Context) (http.Handler, error) { 35 sseHandler, err := e.r.defaultSSEHandler(e.n, ctx, e.r.config) 36 37 if err != nil { 38 return nil, err 39 } 40 41 return sseHandler, nil 42 } 43 44 // HTTPBroadcastHandler returns an HTTP handler to process broadcasting requests 45 func (e *Embedded) HTTPBroadcastHandler() (http.Handler, error) { 46 broadcaster := broadcast.NewHTTPBroadcaster(e.n, &e.r.config.HTTPBroadcast, e.r.log) 47 48 err := broadcaster.Prepare() 49 50 if err != nil { 51 return nil, err 52 } 53 54 return http.HandlerFunc(broadcaster.Handler), nil 55 } 56 57 // Shutdown stops the AnyCable node gracefully. 58 func (e *Embedded) Shutdown(ctx context.Context) error { 59 for _, shutdownable := range e.r.shutdownables { 60 if err := shutdownable.Shutdown(ctx); err != nil { 61 return err 62 } 63 } 64 65 return nil 66 } 67 68 // Embed starts the application without setting up HTTP handlers, signalts, etc. 69 // You can use it to embed AnyCable into your own Go HTTP application. 70 func (r *Runner) Embed() (*Embedded, error) { 71 r.announceDebugMode() 72 mrubySupport := r.initMRuby() 73 74 r.log.Info(fmt.Sprintf("Starting embedded %s %s%s (open file limit: %s)", r.name, version.Version(), mrubySupport, utils.OpenFileLimit())) 75 76 appNode, err := r.runNode() 77 if err != nil { 78 return nil, err 79 } 80 81 embed := &Embedded{n: appNode, r: r} 82 83 go r.startMetrics(r.metrics) 84 85 return embed, nil 86 }