github.com/clubpay/ronykit/kit@v0.14.4-0.20240515065620-d0dace45cbc7/bridge_north.go (about) 1 package kit 2 3 import ( 4 "context" 5 "sync" 6 7 "github.com/clubpay/ronykit/kit/errors" 8 ) 9 10 type WriteFunc func(conn Conn, e *Envelope) error 11 12 type GatewayStartConfig struct { 13 ReusePort bool 14 } 15 16 // Gateway is the main component of the EdgeServer. Without Gateway, the EdgeServer is not functional. You can use 17 // some standard bundles in std/bundle path. However, if you need special handling of communication 18 // between your server and clients, you are free to implement your own Gateway. 19 // If you are a bundle developer need to work with interface otherwise, you don't need to know 20 // much about this interface. 21 type Gateway interface { 22 // Start starts the gateway to accept connections. 23 Start(ctx context.Context, cfg GatewayStartConfig) error 24 // Shutdown shuts down the gateway gracefully. 25 Shutdown(ctx context.Context) error 26 // Register registers the route in the Bundle. This is how Bundle gets information 27 // about the services and their contracts. 28 Register( 29 serviceName, contractID string, enc Encoding, sel RouteSelector, input Message, 30 ) 31 // Subscribe will be called by the EdgeServer. These delegate functions 32 // must be called by the Gateway implementation. In other words, Gateway communicates 33 // with EdgeServer through the GatewayDelegate methods. 34 // 35 // NOTE: This func will be called only once and before calling Start function. 36 Subscribe(d GatewayDelegate) 37 // Dispatch receives the messages from external clients and runs the execFunc with appropriate 38 // arguments. The user of the Gateway does not need to implement this. If you are using some 39 // standard bundles like std/gateway/fasthttp or std/gateway/fastws, then all the implementation 40 // is taken care of. 41 Dispatch(ctx *Context, in []byte) (ExecuteArg, error) 42 } 43 44 // GatewayDelegate is the delegate that connects the Gateway to the rest of the system. 45 type GatewayDelegate interface { 46 ConnDelegate 47 // OnMessage must be called whenever a new message arrives. 48 OnMessage(c Conn, msg []byte) 49 } 50 51 type ConnDelegate interface { 52 // OnOpen must be called whenever a new connection is established. 53 OnOpen(c Conn) 54 // OnClose must be called whenever the connection is gone. 55 OnClose(connID uint64) 56 } 57 58 // northBridge is a container component that connects EdgeServer with a Gateway type Bundle. 59 type northBridge struct { 60 ctxPool 61 wg *sync.WaitGroup 62 eh ErrHandlerFunc 63 c map[string]Contract 64 gw Gateway 65 sb *southBridge 66 cd ConnDelegate 67 } 68 69 var _ GatewayDelegate = (*northBridge)(nil) 70 71 func (n *northBridge) OnOpen(c Conn) { 72 if n.cd == nil { 73 return 74 } 75 76 n.cd.OnOpen(c) 77 } 78 79 func (n *northBridge) OnClose(connID uint64) { 80 if n.cd == nil { 81 return 82 } 83 84 n.cd.OnClose(connID) 85 } 86 87 func (n *northBridge) OnMessage(conn Conn, msg []byte) { 88 n.wg.Add(1) 89 ctx := n.acquireCtx(conn) 90 ctx.sb = n.sb 91 ctx.rawData = msg 92 93 arg, err := n.gw.Dispatch(ctx, msg) 94 switch { 95 default: 96 n.eh(ctx, errors.Wrap(ErrDispatchFailed, err)) 97 case errors.Is(err, ErrPreflight): 98 // If this is a Preflight request, we ignore executing it. 99 // This is a workaround for CORS Preflight requests. 100 case err == nil: 101 ctx.execute(arg, n.c[arg.ContractID]) 102 } 103 104 n.releaseCtx(ctx) 105 n.wg.Done() 106 } 107 108 var ( 109 ErrNoHandler = errors.New("handler is not set for request") 110 ErrWriteToClosedConn = errors.New("write to closed connection") 111 ErrDecodeIncomingMessageFailed = errors.New("decoding the incoming message failed") 112 ErrEncodeOutgoingMessageFailed = errors.New("encoding the outgoing message failed") 113 ErrDecodeIncomingContainerFailed = errors.New("decoding the incoming container failed") 114 ErrDispatchFailed = errors.New("dispatch failed") 115 ErrPreflight = errors.New("preflight request") 116 ) 117 118 // These are just to silence the linter. 119 var ( 120 _ = ErrNoHandler 121 _ = ErrWriteToClosedConn 122 _ = ErrDecodeIncomingMessageFailed 123 _ = ErrEncodeOutgoingMessageFailed 124 _ = ErrDecodeIncomingContainerFailed 125 )