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  }