From 27d3c8d682d06cdd3157c834b0b5768d6c743fef Mon Sep 17 00:00:00 2001 From: luoyy Date: Tue, 4 Jun 2024 16:31:33 +0800 Subject: [PATCH] (refactor): NamespaceInterface renamed to Namespace. --- go.mod | 2 +- go.sum | 4 +- socket/adapter-type.go | 14 +++- socket/adapter.go | 10 +-- socket/client.go | 2 +- socket/namespace-type.go | 25 +++++-- socket/namespace.go | 110 +++++++++++++++-------------- socket/parent-broadcast-adapter.go | 18 +++-- socket/parent-namespace.go | 47 ++++++------ socket/server.go | 32 ++++----- socket/session-aware-adapter.go | 8 +-- socket/socket.go | 10 +-- 12 files changed, 162 insertions(+), 120 deletions(-) diff --git a/go.mod b/go.mod index 4ab4423..2304e48 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/andybalholm/brotli v1.1.0 github.com/mitchellh/mapstructure v1.5.0 github.com/zishang520/engine.io-go-parser v1.2.5 - github.com/zishang520/engine.io/v2 v2.1.0 + github.com/zishang520/engine.io/v2 v2.1.1 github.com/zishang520/socket.io-go-parser/v2 v2.1.0 ) diff --git a/go.sum b/go.sum index 94d6eef..92c85f9 100644 --- a/go.sum +++ b/go.sum @@ -45,8 +45,8 @@ github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHg github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/zishang520/engine.io-go-parser v1.2.5 h1:Disf4rvNQzDsgoC+3yuwuFx5A7JNWlPp+QLUW32WDtc= github.com/zishang520/engine.io-go-parser v1.2.5/go.mod h1:G1DciRIGH4/S7x01DIdZQaXrk09ZeRgEw5e/Z9ms4Is= -github.com/zishang520/engine.io/v2 v2.1.0 h1:dh3O7OcAfqfhg7AhqlqPRM/6pfdAcoRlEmNbe2wv8qE= -github.com/zishang520/engine.io/v2 v2.1.0/go.mod h1:FnXtT+k/6g2uOb9MpqY71DhV7COwlCH5DCbczn6Q3K8= +github.com/zishang520/engine.io/v2 v2.1.1 h1:PZYi3/XW6jJh6yzVoF19JifgmMVggbLskSDNpXtaOFk= +github.com/zishang520/engine.io/v2 v2.1.1/go.mod h1:FnXtT+k/6g2uOb9MpqY71DhV7COwlCH5DCbczn6Q3K8= github.com/zishang520/socket.io-go-parser/v2 v2.1.0 h1:YaTul861UxdTtq/v7XKmF52gWmDOqwugKBlFyiifKCE= github.com/zishang520/socket.io-go-parser/v2 v2.1.0/go.mod h1:zmToGML+lCjSjyGZMuVtnvgnFOnDuAxJZKwfDDDHiqI= go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= diff --git a/socket/adapter-type.go b/socket/adapter-type.go index 626c3eb..92bfe1e 100644 --- a/socket/adapter-type.go +++ b/socket/adapter-type.go @@ -81,10 +81,10 @@ type ( Rooms() *types.Map[Room, *types.Set[SocketId]] Sids() *types.Map[SocketId, *types.Set[Room]] - Nsp() NamespaceInterface + Nsp() Namespace // Construct() should be called after calling Prototype() - Construct(NamespaceInterface) + Construct(Namespace) // To be overridden Init() @@ -148,7 +148,15 @@ type ( RestoreSession(PrivateSessionId, string) (*Session, error) } + SessionAwareAdapter interface { + Adapter + } + + ParentBroadcastAdapter interface { + Adapter + } + AdapterConstructor interface { - New(NamespaceInterface) Adapter + New(Namespace) Adapter } ) diff --git a/socket/adapter.go b/socket/adapter.go index a391645..528d08d 100644 --- a/socket/adapter.go +++ b/socket/adapter.go @@ -21,14 +21,14 @@ type ( // Prototype interface, used to implement interface method rewriting _proto_ Adapter - nsp NamespaceInterface + nsp Namespace rooms *types.Map[Room, *types.Set[SocketId]] sids *types.Map[SocketId, *types.Set[Room]] encoder parser.Encoder } ) -func (*AdapterBuilder) New(nsp NamespaceInterface) Adapter { +func (*AdapterBuilder) New(nsp Namespace) Adapter { return NewAdapterNew(nsp) } @@ -45,7 +45,7 @@ func MakeAdapter() Adapter { return a } -func NewAdapterNew(nsp NamespaceInterface) Adapter { +func NewAdapterNew(nsp Namespace) Adapter { n := MakeAdapter() n.Construct(nsp) @@ -69,11 +69,11 @@ func (a *adapter) Sids() *types.Map[SocketId, *types.Set[Room]] { return a.sids } -func (a *adapter) Nsp() NamespaceInterface { +func (a *adapter) Nsp() Namespace { return a.nsp } -func (a *adapter) Construct(nsp NamespaceInterface) { +func (a *adapter) Construct(nsp Namespace) { a.nsp = nsp a.encoder = nsp.Server().Encoder() } diff --git a/socket/client.go b/socket/client.go index f80b42e..0a284f1 100644 --- a/socket/client.go +++ b/socket/client.go @@ -94,7 +94,7 @@ func (c *Client) connect(name string, auth any) { c.doConnect(name, auth) return } - c.server._checkNamespace(name, auth, func(dynamicNspName *Namespace) { + c.server._checkNamespace(name, auth, func(dynamicNspName Namespace) { if dynamicNspName != nil { c.doConnect(name, auth) } else { diff --git a/socket/namespace-type.go b/socket/namespace-type.go index 5596978..c16b69b 100644 --- a/socket/namespace-type.go +++ b/socket/namespace-type.go @@ -56,7 +56,7 @@ import ( // userNamespace.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) { // // ensure the socket has access to the "users" namespace // }) -type NamespaceInterface interface { +type Namespace interface { On(string, ...events.Listener) error Once(string, ...events.Listener) error EmitReserved(string, ...any) @@ -65,8 +65,8 @@ type NamespaceInterface interface { // #prototype - Prototype(NamespaceInterface) - Proto() NamespaceInterface + Prototype(Namespace) + Proto() Namespace // #getters @@ -76,6 +76,7 @@ type NamespaceInterface interface { Adapter() Adapter Name() string Ids() uint64 + Fns() *types.Slice[func(*Socket, func(*ExtendedError))] // Construct() should be called after calling Prototype() Construct(*Server, string) @@ -87,8 +88,11 @@ type NamespaceInterface interface { // in addition to the constructor. InitAdapter() + // Whether to remove child namespaces that have no sockets connected to them + Cleanup(func()) + // Sets up namespace middleware. - Use(func(*Socket, func(*ExtendedError))) NamespaceInterface + Use(func(*Socket, func(*ExtendedError))) Namespace // Targets a room when emitting. To(...Room) *BroadcastOperator @@ -106,10 +110,10 @@ type NamespaceInterface interface { Emit(string, ...any) error // Sends a `message` event to all clients. - Send(...any) NamespaceInterface + Send(...any) Namespace // Sends a `message` event to all clients. - Write(...any) NamespaceInterface + Write(...any) Namespace // Emit a packet to other Socket.IO servers ServerSideEmit(string, ...any) error @@ -152,6 +156,15 @@ type NamespaceInterface interface { // Makes the matching socket instances disconnect DisconnectSockets(bool) + + // Removes a client. Called by each [Socket]. + Remove(*Socket) +} + +type ParentNamespace interface { + Namespace + + CreateChild(string) Namespace } type ExtendedError struct { diff --git a/socket/namespace.go b/socket/namespace.go index f7ef847..e7600b6 100644 --- a/socket/namespace.go +++ b/socket/namespace.go @@ -66,13 +66,11 @@ var ( // userNamespace.Use(func(socket *socket.Socket, next func(*socket.ExtendedError)) { // // ensure the socket has access to the "users" namespace // }) -type Namespace struct { - _ids atomic.Uint64 - +type namespace struct { *StrictEventEmitter // Prototype interface, used to implement interface method rewriting - _proto_ NamespaceInterface + _proto_ Namespace // #readonly // @public @@ -83,29 +81,30 @@ type Namespace struct { adapter Adapter // @private + _ids atomic.Uint64 server *Server _fns *types.Slice[func(*Socket, func(*ExtendedError))] - _remove func(socket *Socket) + _cleanup func() } -func MakeNamespace() *Namespace { - n := &Namespace{ +func MakeNamespace() Namespace { + n := &namespace{ StrictEventEmitter: NewStrictEventEmitter(), - sockets: &types.Map[SocketId, *Socket]{}, - _fns: types.NewSlice[func(*Socket, func(*ExtendedError))](), + sockets: &types.Map[SocketId, *Socket]{}, + _fns: types.NewSlice[func(*Socket, func(*ExtendedError))](), + _cleanup: nil, } - n._remove = n.namespace_remove n.Prototype(n) return n } -func NewNamespace(server *Server, name string) *Namespace { +func NewNamespace(server *Server, name string) Namespace { n := MakeNamespace() n.Construct(server, name) @@ -113,39 +112,43 @@ func NewNamespace(server *Server, name string) *Namespace { return n } -func (n *Namespace) Prototype(_n NamespaceInterface) { +func (n *namespace) Prototype(_n Namespace) { n._proto_ = _n } -func (n *Namespace) Proto() NamespaceInterface { +func (n *namespace) Proto() Namespace { return n._proto_ } -func (n *Namespace) EventEmitter() *StrictEventEmitter { +func (n *namespace) EventEmitter() *StrictEventEmitter { return n.StrictEventEmitter } -func (n *Namespace) Sockets() *types.Map[SocketId, *Socket] { +func (n *namespace) Sockets() *types.Map[SocketId, *Socket] { return n.sockets } -func (n *Namespace) Server() *Server { +func (n *namespace) Server() *Server { return n.server } -func (n *Namespace) Adapter() Adapter { +func (n *namespace) Adapter() Adapter { return n.adapter } -func (n *Namespace) Name() string { +func (n *namespace) Name() string { return n.name } -func (n *Namespace) Ids() uint64 { +func (n *namespace) Ids() uint64 { return n._ids.Add(1) } -func (n *Namespace) Construct(server *Server, name string) { +func (n *namespace) Fns() *types.Slice[func(*Socket, func(*ExtendedError))] { + return n._fns +} + +func (n *namespace) Construct(server *Server, name string) { n.server = server n.name = name n.Proto().InitAdapter() @@ -154,9 +157,9 @@ func (n *Namespace) Construct(server *Server, name string) { // @protected // // Initializes the `Adapter` for n nsp. -// Run upon changing adapter by `Server.Adapter` +// Run upon changing adapter by [Server.Adapter] // in addition to the constructor. -func (n *Namespace) InitAdapter() { +func (n *namespace) InitAdapter() { n.adapter = n.server.Adapter().New(n) } @@ -170,7 +173,7 @@ func (n *Namespace) InitAdapter() { // }) // // Param: func(*ExtendedError) - the middleware function -func (n *Namespace) Use(fn func(*Socket, func(*ExtendedError))) NamespaceInterface { +func (n *namespace) Use(fn func(*Socket, func(*ExtendedError))) Namespace { n._fns.Push(fn) return n } @@ -180,7 +183,7 @@ func (n *Namespace) Use(fn func(*Socket, func(*ExtendedError))) NamespaceInterfa // Param: socket - the socket that will get added // // Param: fn - last fn call in the middleware -func (n *Namespace) run(socket *Socket, fn func(err *ExtendedError)) { +func (n *namespace) run(socket *Socket, fn func(err *ExtendedError)) { fns := n._fns.All() if length := len(fns); length > 0 { var run func(i int) @@ -223,7 +226,7 @@ func (n *Namespace) run(socket *Socket, fn func(err *ExtendedError)) { // Param: Room - a `Room`, or a `Room` slice to expand // // Return: a new [BroadcastOperator] instance for chaining -func (n *Namespace) To(room ...Room) *BroadcastOperator { +func (n *namespace) To(room ...Room) *BroadcastOperator { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).To(room...) } @@ -237,7 +240,7 @@ func (n *Namespace) To(room ...Room) *BroadcastOperator { // Param: Room - a `Room`, or a `Room` slice to expand // // Return: a new [BroadcastOperator] instance for chaining -func (n *Namespace) In(room ...Room) *BroadcastOperator { +func (n *namespace) In(room ...Room) *BroadcastOperator { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).In(room...) } @@ -258,12 +261,12 @@ func (n *Namespace) In(room ...Room) *BroadcastOperator { // Param: Room - a `Room`, or a `Room` slice to expand // // Return: a new [BroadcastOperator] instance for chaining -func (n *Namespace) Except(room ...Room) *BroadcastOperator { +func (n *namespace) Except(room ...Room) *BroadcastOperator { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).Except(room...) } // Adds a new client. -func (n *Namespace) Add(client *Client, auth any, fn func(*Socket)) { +func (n *namespace) Add(client *Client, auth any, fn func(*Socket)) { namespace_log.Debug("adding socket to nsp %s", n.name) socket := n._createSocket(client, auth) if n.server.Opts().ConnectionStateRecovery().SkipMiddlewares() && socket.Recovered() && client.Conn().ReadyState() == "open" { @@ -302,7 +305,7 @@ func (n *Namespace) Add(client *Client, auth any, fn func(*Socket)) { }) } -func (n *Namespace) _createSocket(client *Client, auth any) *Socket { +func (n *namespace) _createSocket(client *Client, auth any) *Socket { var _auth *SeesionData if mapstructure.Decode(auth, &_auth) == nil { sessionId, has_sessionId := _auth.GetPid() @@ -320,7 +323,7 @@ func (n *Namespace) _createSocket(client *Client, auth any) *Socket { return NewSocket(n, client, auth, nil) } -func (n *Namespace) _doConnect(socket *Socket, fn func(*Socket)) { +func (n *namespace) _doConnect(socket *Socket, fn func(*Socket)) { // track socket n.sockets.Store(socket.Id(), socket) @@ -338,18 +341,21 @@ func (n *Namespace) _doConnect(socket *Socket, fn func(*Socket)) { n.EmitReserved("connection", socket) } -// @private -// -// Removes a client. Called by each `Socket`. -func (n *Namespace) remove(socket *Socket) { - n._remove(socket) +// Whether to remove child namespaces that have no sockets connected to them +func (n *namespace) Cleanup(cleanup func()) { + n._cleanup = cleanup } -// Removes a client. Called by each `Socket`. -func (n *Namespace) namespace_remove(socket *Socket) { +// @private +// +// Removes a client. Called by each [Socket]. +func (n *namespace) Remove(socket *Socket) { if _, ok := n.sockets.LoadAndDelete(socket.Id()); !ok { namespace_log.Debug("ignoring remove for %s", socket.Id()) } + if n._cleanup != nil { + n._cleanup() + } } // Emits to all clients. @@ -372,7 +378,7 @@ func (n *Namespace) namespace_remove(socket *Socket) { // }) // // Return: Always nil -func (n *Namespace) Emit(ev string, args ...any) error { +func (n *namespace) Emit(ev string, args ...any) error { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).Emit(ev, args...) } @@ -388,7 +394,7 @@ func (n *Namespace) Emit(ev string, args ...any) error { // // // this is equivalent to // myNamespace.Emit("message", "hello") -func (n *Namespace) Send(args ...any) NamespaceInterface { +func (n *namespace) Send(args ...any) Namespace { // This type-cast is needed because EmitEvents likely doesn't have `message` as a key. // if you specify the EmitEvents, the type of args will be never. n.Emit("message", args...) @@ -396,7 +402,7 @@ func (n *Namespace) Send(args ...any) NamespaceInterface { } // Sends a `message` event to all clients. Sends a `message` event. Alias of [Send]. -func (n *Namespace) Write(args ...any) NamespaceInterface { +func (n *namespace) Write(args ...any) Namespace { // This type-cast is needed because EmitEvents likely doesn't have `message` as a key. // if you specify the EmitEvents, the type of args will be never. n.Emit("message", args...) @@ -429,7 +435,7 @@ func (n *Namespace) Write(args ...any) NamespaceInterface { // Param: ev - the event name // // Param: args - an slice of arguments, which may include an acknowledgement callback at the end -func (n *Namespace) ServerSideEmit(ev string, args ...any) error { +func (n *namespace) ServerSideEmit(ev string, args ...any) error { if NAMESPACE_RESERVED_EVENTS.Has(ev) { return errors.New(fmt.Sprintf(`"%s" is a reserved event name`, ev)) } @@ -452,21 +458,21 @@ func (n *Namespace) ServerSideEmit(ev string, args ...any) error { // }) // // Return: a `func(func([]any, error))` that will be fulfilled when all servers have acknowledged the event -func (n *Namespace) ServerSideEmitWithAck(ev string, args ...any) func(func([]any, error)) { +func (n *namespace) ServerSideEmitWithAck(ev string, args ...any) func(func([]any, error)) { return func(ack func([]any, error)) { n.ServerSideEmit(ev, append(args, ack)...) } } // Called when a packet is received from another Socket.IO server -func (n *Namespace) OnServerSideEmit(ev string, args ...any) { +func (n *namespace) OnServerSideEmit(ev string, args ...any) { n.EmitUntyped(ev, args...) } // Gets a list of socket ids. // // Deprecated: this method will be removed in the next major release, please use [Namespace#ServerSideEmit] or [Namespace#FetchSockets] instead. -func (n *Namespace) AllSockets() (*types.Set[SocketId], error) { +func (n *namespace) AllSockets() (*types.Set[SocketId], error) { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).AllSockets() } @@ -477,7 +483,7 @@ func (n *Namespace) AllSockets() (*types.Set[SocketId], error) { // Param: bool - if `true`, compresses the sending data // // Return: a new [BroadcastOperator] instance for chaining -func (n *Namespace) Compress(compress bool) *BroadcastOperator { +func (n *namespace) Compress(compress bool) *BroadcastOperator { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).Compress(compress) } @@ -488,7 +494,7 @@ func (n *Namespace) Compress(compress bool) *BroadcastOperator { // myNamespace := io.Of("/my-namespace") // // myNamespace.Volatile().Emit("hello") // the clients may or may not receive it -func (n *Namespace) Volatile() *BroadcastOperator { +func (n *namespace) Volatile() *BroadcastOperator { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).Volatile() } @@ -500,7 +506,7 @@ func (n *Namespace) Volatile() *BroadcastOperator { // myNamespace.Local().Emit("foo", "bar") // // Return: a new [BroadcastOperator] instance for chaining -func (n *Namespace) Local() *BroadcastOperator { +func (n *namespace) Local() *BroadcastOperator { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).Local() } @@ -513,7 +519,7 @@ func (n *Namespace) Local() *BroadcastOperator { // fmt.Println(args) // one response per client // } // }) -func (n *Namespace) Timeout(timeout time.Duration) *BroadcastOperator { +func (n *namespace) Timeout(timeout time.Duration) *BroadcastOperator { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).Timeout(timeout) } @@ -541,7 +547,7 @@ func (n *Namespace) Timeout(timeout time.Duration) *BroadcastOperator { // } // // }) -func (n *Namespace) FetchSockets() func(func([]*RemoteSocket, error)) { +func (n *namespace) FetchSockets() func(func([]*RemoteSocket, error)) { return NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).FetchSockets() } @@ -556,7 +562,7 @@ func (n *Namespace) FetchSockets() func(func([]*RemoteSocket, error)) { // io.In("room1").SocketsJoin([]Room{"room2", "room3"}...) // // Param: Room - a `Room`, or a `Room` slice to expand -func (n *Namespace) SocketsJoin(room ...Room) { +func (n *namespace) SocketsJoin(room ...Room) { NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).SocketsJoin(room...) } @@ -571,7 +577,7 @@ func (n *Namespace) SocketsJoin(room ...Room) { // io.In("room1").SocketsLeave([]Room{"room2", "room3"}...) // // Param: Room - a `Room`, or a `Room` slice to expand -func (n *Namespace) SocketsLeave(room ...Room) { +func (n *namespace) SocketsLeave(room ...Room) { NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).SocketsLeave(room...) } @@ -586,6 +592,6 @@ func (n *Namespace) SocketsLeave(room ...Room) { // io.In("room1").DisconnectSockets(true) // // Param: close - whether to close the underlying connection -func (n *Namespace) DisconnectSockets(status bool) { +func (n *namespace) DisconnectSockets(status bool) { NewBroadcastOperator(n.Proto().Adapter(), nil, nil, nil).DisconnectSockets(status) } diff --git a/socket/parent-broadcast-adapter.go b/socket/parent-broadcast-adapter.go index df62e62..6a64469 100644 --- a/socket/parent-broadcast-adapter.go +++ b/socket/parent-broadcast-adapter.go @@ -6,15 +6,25 @@ import ( ) type ( + ParentBroadcastAdapterBuilder struct { + AdapterConstructor + + Children *types.Set[Namespace] + } + // A dummy adapter that only supports broadcasting to child (concrete) namespaces. parentBroadcastAdapter struct { Adapter - children *types.Set[*Namespace] + children *types.Set[Namespace] } ) -func MakeParentBroadcastAdapter(children *types.Set[*Namespace]) Adapter { +func (b *ParentBroadcastAdapterBuilder) New(nsp Namespace) Adapter { + return NewParentBroadcastAdapter(nsp, b.Children) +} + +func MakeParentBroadcastAdapter(children *types.Set[Namespace]) ParentBroadcastAdapter { s := &parentBroadcastAdapter{ Adapter: MakeAdapter(), @@ -26,7 +36,7 @@ func MakeParentBroadcastAdapter(children *types.Set[*Namespace]) Adapter { return s } -func NewParentBroadcastAdapter(nsp NamespaceInterface, children *types.Set[*Namespace]) Adapter { +func NewParentBroadcastAdapter(nsp Namespace, children *types.Set[Namespace]) ParentBroadcastAdapter { s := MakeParentBroadcastAdapter(children) s.Construct(nsp) @@ -34,7 +44,7 @@ func NewParentBroadcastAdapter(nsp NamespaceInterface, children *types.Set[*Name return s } -func (s *parentBroadcastAdapter) Construct(nsp NamespaceInterface) { +func (s *parentBroadcastAdapter) Construct(nsp Namespace) { s.Adapter.Construct(nsp) } diff --git a/socket/parent-namespace.go b/socket/parent-namespace.go index 3841a72..cb1b640 100644 --- a/socket/parent-namespace.go +++ b/socket/parent-namespace.go @@ -28,16 +28,18 @@ var ( // // will reach all the clients that are in one of the child namespaces, like "/dynamic-101" // // parentNamespace.Emit("hello", "world") -type ParentNamespace struct { - *Namespace +type parentNamespace struct { + Namespace - children *types.Set[*Namespace] + adapter Adapter + children *types.Set[Namespace] } -func MakeParentNamespace() *ParentNamespace { - n := &ParentNamespace{ +func MakeParentNamespace() ParentNamespace { + n := &parentNamespace{ Namespace: MakeNamespace(), - children: types.NewSet[*Namespace](), + + children: types.NewSet[Namespace](), } n.Prototype(n) @@ -45,7 +47,7 @@ func MakeParentNamespace() *ParentNamespace { return n } -func NewParentNamespace(server *Server) *ParentNamespace { +func NewParentNamespace(server *Server) ParentNamespace { n := MakeParentNamespace() n.Construct(server, "/_"+strconv.FormatUint(count.Add(1)-1, 10)) @@ -53,37 +55,40 @@ func NewParentNamespace(server *Server) *ParentNamespace { return n } -func (p *ParentNamespace) InitAdapter() { +func (p *parentNamespace) Adapter() Adapter { + return p.adapter +} + +func (p *parentNamespace) InitAdapter() { p.adapter = NewParentBroadcastAdapter(p, p.children) } -func (p *ParentNamespace) Emit(ev string, args ...any) error { +func (p *parentNamespace) Emit(ev string, args ...any) error { for _, nsp := range p.children.Keys() { nsp.Emit(ev, args...) } return nil } -func (p *ParentNamespace) CreateChild(name string) *Namespace { +func (p *parentNamespace) CreateChild(name string) Namespace { parent_namespace_log.Debug("creating child namespace %s", name) namespace := NewNamespace(p.Server(), name) - namespace._fns.Replace(p._fns.All()) + namespace.Fns().Replace(p.Fns().All()) - namespace.AddListener("connect", p.Listeners("connect")...) - namespace.AddListener("connection", p.Listeners("connection")...) + namespace.On("connect", p.Listeners("connect")...) + namespace.On("connection", p.Listeners("connection")...) p.children.Add(namespace) - if p.server.Opts().CleanupEmptyChildNamespaces() { - namespace._remove = func(socket *Socket) { - namespace.namespace_remove(socket) - if namespace.sockets.Len() == 0 { + if p.Server().Opts().CleanupEmptyChildNamespaces() { + namespace.Cleanup(func() { + if namespace.Sockets().Len() == 0 { parent_namespace_log.Debug("closing child namespace %s", name) - namespace.adapter.Close() - p.server._nsps.Delete(namespace.name) + namespace.Adapter().Close() + p.Server()._nsps.Delete(namespace.Name()) p.children.Delete(namespace) } - } + }) } p.Server()._nsps.Store(name, namespace) @@ -92,7 +97,7 @@ func (p *ParentNamespace) CreateChild(name string) *Namespace { return namespace } -func (p *ParentNamespace) FetchSockets() func(func([]*RemoteSocket, error)) { +func (p *parentNamespace) FetchSockets() func(func([]*RemoteSocket, error)) { return func(callback func([]*RemoteSocket, error)) { // note: we could make the FetchSockets() method work for dynamic namespaces created with a regex (by sending the // regex to the other Socket.IO servers, and returning the sockets of each matching namespace for example), but diff --git a/socket/server.go b/socket/server.go index 09578ec..4af2579 100644 --- a/socket/server.go +++ b/socket/server.go @@ -62,7 +62,7 @@ type ( *StrictEventEmitter // #readonly - sockets NamespaceInterface + sockets Namespace // A reference to the underlying Engine.IO server. // // clientsCount := io.Engine().ClientsCount() @@ -72,14 +72,14 @@ type ( // @private encoder parser.Encoder // @private - _nsps *types.Map[string, *Namespace] + _nsps *types.Map[string, Namespace] // @private - parentNsps *types.Map[ParentNspNameMatchFn, *ParentNamespace] + parentNsps *types.Map[ParentNspNameMatchFn, ParentNamespace] // @private // // A subset of the {parentNsps} map, only containing {ParentNamespace} which are based on a regular // expression. - parentNamespacesFromRegExp *types.Map[*regexp.Regexp, *ParentNamespace] + parentNamespacesFromRegExp *types.Map[*regexp.Regexp, ParentNamespace] _adapter AdapterConstructor _serveClient bool // @private @@ -97,9 +97,9 @@ type ( func MakeServer() *Server { s := &Server{ - _nsps: &types.Map[string, *Namespace]{}, - parentNsps: &types.Map[ParentNspNameMatchFn, *ParentNamespace]{}, - parentNamespacesFromRegExp: &types.Map[*regexp.Regexp, *ParentNamespace]{}, + _nsps: &types.Map[string, Namespace]{}, + parentNsps: &types.Map[ParentNspNameMatchFn, ParentNamespace]{}, + parentNamespacesFromRegExp: &types.Map[*regexp.Regexp, ParentNamespace]{}, } return s } @@ -112,7 +112,7 @@ func NewServer(srv any, opts *ServerOptions) *Server { return s } -func (s *Server) Sockets() NamespaceInterface { +func (s *Server) Sockets() Namespace { return s.sockets } @@ -185,9 +185,9 @@ func (s *Server) ServeClient() bool { // Param: auth - the auth parameters // // Param: fn - callback -func (s *Server) _checkNamespace(name string, auth any, fn func(nsp *Namespace)) { +func (s *Server) _checkNamespace(name string, auth any, fn func(nsp Namespace)) { end := true - s.parentNsps.Range(func(nextFn ParentNspNameMatchFn, pnsp *ParentNamespace) bool { + s.parentNsps.Range(func(nextFn ParentNspNameMatchFn, pnsp ParentNamespace) bool { status := false (*nextFn)(name, auth, func(err error, allow bool) { if err != nil || !allow { @@ -244,7 +244,7 @@ func (s *Server) ConnectTimeout() time.Duration { // Param: v AdapterConstructor interface func (s *Server) SetAdapter(v AdapterConstructor) *Server { s._adapter = v - s._nsps.Range(func(_ string, nsp *Namespace) bool { + s._nsps.Range(func(_ string, nsp Namespace) bool { nsp.InitAdapter() return true }) @@ -341,7 +341,7 @@ func (s *Server) ServeHandler(opts *ServerOptions) http.Handler { // Param: opts - options passed to engine.io func (s *Server) initEngine(srv *types.HttpServer, opts *ServerOptions) { // initialize engine - server_log.Debug("creating engine.io instance with opts %v", opts) + server_log.Debug("creating engine.io instance with opts %+v", opts) s.eio = engine.Attach(srv, any(opts)) // attach static file serving @@ -512,7 +512,7 @@ func (s *Server) onconnection(conns ...any) { // Param: string | *regexp.Regexp | ParentNspNameMatchFn - nsp name // // Param: func(...any) - nsp `connection` ev handler -func (s *Server) Of(name any, fn func(...any)) NamespaceInterface { +func (s *Server) Of(name any, fn func(...any)) Namespace { switch n := name.(type) { case ParentNspNameMatchFn: parentNsp := NewParentNamespace(s) @@ -553,12 +553,12 @@ func (s *Server) Of(name any, fn func(...any)) NamespaceInterface { n = "/" } - var namespace *Namespace + var namespace Namespace if nsp, ok := s._nsps.Load(n); ok { namespace = nsp } else { - s.parentNamespacesFromRegExp.Range(func(regex *regexp.Regexp, parentNamespace *ParentNamespace) bool { + s.parentNamespacesFromRegExp.Range(func(regex *regexp.Regexp, parentNamespace ParentNamespace) bool { if regex.MatchString(n) { server_log.Debug("attaching namespace %s to parent namespace %s", n, regex.String()) namespace = parentNamespace.CreateChild(n) @@ -589,7 +589,7 @@ func (s *Server) Of(name any, fn func(...any)) NamespaceInterface { // // Param: [fn] optional, called as `fn(error)` on error OR all conns closed func (s *Server) Close(fn func(error)) { - s._nsps.Range(func(_ string, nsp *Namespace) bool { + s._nsps.Range(func(_ string, nsp Namespace) bool { nsp.Sockets().Range(func(_ SocketId, socket *Socket) bool { socket._onclose("server shutting down") return true diff --git a/socket/session-aware-adapter.go b/socket/session-aware-adapter.go index 2510317..82d76fb 100644 --- a/socket/session-aware-adapter.go +++ b/socket/session-aware-adapter.go @@ -23,11 +23,11 @@ type ( } ) -func (*SessionAwareAdapterBuilder) New(nsp NamespaceInterface) Adapter { +func (*SessionAwareAdapterBuilder) New(nsp Namespace) Adapter { return NewSessionAwareAdapter(nsp) } -func MakeSessionAwareAdapter() Adapter { +func MakeSessionAwareAdapter() SessionAwareAdapter { s := &sessionAwareAdapter{ Adapter: MakeAdapter(), @@ -40,7 +40,7 @@ func MakeSessionAwareAdapter() Adapter { return s } -func NewSessionAwareAdapter(nsp NamespaceInterface) Adapter { +func NewSessionAwareAdapter(nsp Namespace) SessionAwareAdapter { s := MakeSessionAwareAdapter() s.Construct(nsp) @@ -48,7 +48,7 @@ func NewSessionAwareAdapter(nsp NamespaceInterface) Adapter { return s } -func (s *sessionAwareAdapter) Construct(nsp NamespaceInterface) { +func (s *sessionAwareAdapter) Construct(nsp Namespace) { s.Adapter.Construct(nsp) s.maxDisconnectionDuration = nsp.Server().Opts().ConnectionStateRecovery().MaxDisconnectionDuration() diff --git a/socket/socket.go b/socket/socket.go index adab04d..349a8ae 100644 --- a/socket/socket.go +++ b/socket/socket.go @@ -82,7 +82,7 @@ type ( Socket struct { *StrictEventEmitter - nsp *Namespace + nsp Namespace client *Client // An unique identifier for the session. @@ -142,7 +142,7 @@ func MakeSocket() *Socket { return s } -func NewSocket(nsp *Namespace, client *Client, auth any, previousSession *Session) *Socket { +func NewSocket(nsp Namespace, client *Client, auth any, previousSession *Session) *Socket { s := MakeSocket() s.Construct(nsp, client, auth, previousSession) @@ -197,7 +197,7 @@ func (s *Socket) Acks() *types.Map[uint64, func([]any, error)] { return s.acks } -func (s *Socket) Nsp() *Namespace { +func (s *Socket) Nsp() Namespace { return s.nsp } @@ -205,7 +205,7 @@ func (s *Socket) Client() *Client { return s.client } -func (s *Socket) Construct(nsp *Namespace, client *Client, auth any, previousSession *Session) { +func (s *Socket) Construct(nsp Namespace, client *Client, auth any, previousSession *Session) { s.nsp = nsp s.client = client @@ -640,7 +640,7 @@ func (s *Socket) _onclose(args ...any) *Socket { // Makes the socket leave all the rooms it was part of and prevents it from joining any other room func (s *Socket) _cleanup() { s.leaveAll() - s.nsp.remove(s) + s.nsp.Remove(s) s.canJoin.Store(false) }