Skip to content

Commit c6806f1

Browse files
committed
make Ask to work inside handlers themselves without the need of a new goroutine
1 parent df0e783 commit c6806f1

File tree

3 files changed

+83
-5
lines changed

3 files changed

+83
-5
lines changed

conn.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ type Conn struct {
7474
// i.e `askConnect: myNamespace` blocks the `tryNamespace: myNamespace` until finish.
7575
processes *processes
7676

77+
isInsideHandler *uint32
78+
7779
// messages that this connection waits for a reply.
7880
waitingMessages map[string]chan Message
7981
waitingMessagesMutex sync.RWMutex
@@ -98,6 +100,7 @@ func newConn(socket Socket, namespaces Namespaces) *Conn {
98100
acknowledged: new(uint32),
99101
connectedNamespaces: make(map[string]*NSConn),
100102
processes: newProcesses(),
103+
isInsideHandler: new(uint32),
101104
waitingMessages: make(map[string]chan Message),
102105
allowNativeMessages: false,
103106
shouldHandleOnlyNativeMessages: false,
@@ -327,7 +330,9 @@ func (c *Conn) startReader() {
327330
continue
328331
}
329332

333+
atomic.StoreUint32(c.isInsideHandler, 1)
330334
c.HandlePayload(b)
335+
atomic.StoreUint32(c.isInsideHandler, 0)
331336
}
332337
}
333338

@@ -916,7 +921,8 @@ func (c *Conn) sendConfirmation(wait string) {
916921

917922
// Ask method sends a message to the remote side and blocks until a response or an error received from the specific `Message.Event`.
918923
func (c *Conn) Ask(ctx context.Context, msg Message) (Message, error) {
919-
return c.ask(ctx, msg, false)
924+
mustWaitOnlyTheNextMessage := atomic.LoadUint32(c.isInsideHandler) == 1
925+
return c.ask(ctx, msg, mustWaitOnlyTheNextMessage)
920926
}
921927

922928
func (c *Conn) ask(ctx context.Context, msg Message, mustWaitOnlyTheNextMessage bool) (Message, error) {
@@ -939,7 +945,7 @@ func (c *Conn) ask(ctx context.Context, msg Message, mustWaitOnlyTheNextMessage
939945
}
940946
}
941947

942-
ch := make(chan Message)
948+
ch := make(chan Message, 1)
943949
msg.wait = genWait(c.IsClient())
944950

945951
if mustWaitOnlyTheNextMessage {

conn_namespace.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func (ns *NSConn) askRoomJoin(ctx context.Context, roomName string) (*Room, erro
168168
IsLocal: true,
169169
}
170170

171-
_, err := ns.Conn.ask(ctx, joinMsg, true)
171+
_, err := ns.Conn.Ask(ctx, joinMsg)
172172
if err != nil {
173173
return nil, err
174174
}
@@ -231,7 +231,7 @@ func (ns *NSConn) askRoomLeave(ctx context.Context, msg Message, lock bool) erro
231231
return ErrBadRoom
232232
}
233233

234-
_, err := ns.Conn.ask(ctx, msg, true)
234+
_, err := ns.Conn.Ask(ctx, msg)
235235
if err != nil {
236236
return err
237237
}

conn_namespace_test.go

+73-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func TestJoinAndLeaveRoom(t *testing.T) {
3131
t.Fatalf("expected Message's room name to be: %s==%s but it's: %s", roomName, room.Name, msg.Room)
3232
}
3333

34-
go room.Leave(nil)
34+
room.Leave(nil)
3535

3636
wg.Done()
3737
} else {
@@ -90,3 +90,75 @@ func TestJoinAndLeaveRoom(t *testing.T) {
9090
t.Fatal(err)
9191
}
9292
}
93+
94+
func TestJoinAndLeaveRoomInsideHandler(t *testing.T) {
95+
var (
96+
wg sync.WaitGroup
97+
namespace = "default"
98+
roomName = "room1"
99+
body = []byte("data")
100+
events = neffos.Namespaces{
101+
namespace: neffos.Events{
102+
"event": func(c *neffos.NSConn, msg neffos.Message) error {
103+
if c.Conn.IsClient() {
104+
if !bytes.Equal(msg.Body, body) {
105+
t.Fatalf("expected event's incoming data to be: %s but got: %s", string(body), string(msg.Body))
106+
}
107+
108+
room := c.Room(roomName)
109+
if room == nil {
110+
t.Fatal("expected a non-nil room")
111+
}
112+
113+
if room.Name != msg.Room {
114+
t.Fatalf("expected Message's room name to be: %s==%s but it's: %s", roomName, room.Name, msg.Room)
115+
}
116+
117+
room.Leave(nil)
118+
119+
wg.Done()
120+
} else {
121+
room, err := c.JoinRoom(nil, roomName)
122+
if err != nil {
123+
return err
124+
}
125+
126+
room.Emit(msg.Event, msg.Body)
127+
}
128+
129+
return nil
130+
},
131+
neffos.OnRoomLeft: func(c *neffos.NSConn, msg neffos.Message) error {
132+
if c.Conn.IsClient() {
133+
if msg.Room != roomName {
134+
t.Fatalf("expected left room name to be %s but got %s", roomName, msg.Room)
135+
}
136+
wg.Done()
137+
}
138+
139+
return nil
140+
},
141+
},
142+
}
143+
)
144+
145+
teardownServer := runTestServer("localhost:8080", events)
146+
defer teardownServer()
147+
148+
err := runTestClient("localhost:8080", events,
149+
func(dialer string, client *neffos.Client) {
150+
c, err := client.Connect(nil, namespace)
151+
if err != nil {
152+
t.Fatal(err)
153+
}
154+
155+
// 1 -> to catch its own event and
156+
// 2 -> to notify about room leave inside the event itself for both clients ofc.
157+
wg.Add(2)
158+
c.Emit("event", body)
159+
wg.Wait()
160+
})()
161+
if err != nil {
162+
t.Fatal(err)
163+
}
164+
}

0 commit comments

Comments
 (0)