Skip to content

Commit e51c4da

Browse files
Add sort and limit support to listing lobbies (#282)
Allows sorting the list() result on any property and adds support to limit how many lobbies should be returned.
1 parent cffef54 commit e51c4da

File tree

13 files changed

+101
-38
lines changed

13 files changed

+101
-38
lines changed

features/custom-data.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ Feature: customData on lobbies can be used for filtering and extra information
8585
"""
8686
And "yellow" receives the network event "lobby" with the argument "19yrzmetd2bn7"
8787

88-
When "blue" requests lobbies with this filter:
88+
When "blue" requests lobbies with:
8989
"""json
9090
{
9191
"status": "open"
@@ -104,7 +104,7 @@ Feature: customData on lobbies can be used for filtering and extra information
104104
}
105105
"""
106106

107-
When "blue" requests lobbies with this filter:
107+
When "blue" requests lobbies with:
108108
"""json
109109
{
110110
"status": "open"

features/lobbies.feature

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,21 @@ Feature: Lobby Discovery
66

77
Scenario: List empty lobby set
88
Given "green" is connected as "1u8fw4aph5ypt" and ready for game "f666036d-d9e1-4d70-b0c3-4a68b24a9884"
9-
When "green" requests all lobbies
9+
When "green" requests lobbies with:
10+
"""json
11+
{}
12+
"""
1013
Then "green" should receive 0 lobbies
1114

1215
Scenario: Don't list lobbies from a different game
1316
Given "green" creates a network for game "f666036d-d9e1-4d70-b0c3-4a68b24a9884"
1417
And "blue" is connected as "h5yzwyizlwao" and ready for game "4307bd86-e1df-41b8-b9df-e22afcf084bd"
1518
And "yellow" is connected as "19yrzmetd2bn7" and ready for game "4307bd86-e1df-41b8-b9df-e22afcf084bd"
1619
And "blue,yellow" are joined in a lobby
17-
When "green" requests all lobbies
20+
When "green" requests lobbies with:
21+
"""json
22+
{}
23+
"""
1824
Then "green" should receive 0 lobbies
1925

2026
Scenario: List lobbies that exist
@@ -29,7 +35,10 @@ Feature: Lobby Discovery
2935
"""
3036
And "blue" receives the network event "lobby" with the argument "19yrzmetd2bn7"
3137

32-
When "green" requests all lobbies
38+
When "green" requests lobbies with:
39+
"""json
40+
{}
41+
"""
3342
Then "green" should have received only these lobbies:
3443
| code | playerCount |
3544
| 19yrzmetd2bn7 | 1 |
@@ -54,7 +63,10 @@ Feature: Lobby Discovery
5463
"""
5564
And "yellow" receives the network event "lobby" with the argument "prb67ouj837u"
5665

57-
When "green" requests all lobbies
66+
When "green" requests lobbies with:
67+
"""json
68+
{}
69+
"""
5870
Then "green" should have received only these lobbies:
5971
| code | playerCount | public |
6072
| 3t3cfgcqup9e | 1 | true |
@@ -74,7 +86,7 @@ Feature: Lobby Discovery
7486
| 8qva9vyurwbbl | 54fa57d5-b4bd-401d-981d-2c13de99be27 | 9 | true |
7587
| 9qva9vyurwbbl | f666036d-d9e1-4d70-b0c3-4a68b24a9884 | 10 | true |
7688

77-
When "green" requests lobbies with this filter:
89+
When "green" requests lobbies with:
7890
"""json
7991
{
8092
"playerCount": {
@@ -97,7 +109,7 @@ Feature: Lobby Discovery
97109
| 1qva9vyurwbbl | f666036d-d9e1-4d70-b0c3-4a68b24a9884 | 1 | {"map": "de_dust"} | true | 2020-01-02 |
98110
| 2qva9vyurwbbl | f666036d-d9e1-4d70-b0c3-4a68b24a9884 | 1 | {"map": "de_nuke"} | true | 2020-01-03 |
99111

100-
When "green" requests lobbies with this filter:
112+
When "green" requests lobbies with:
101113
"""json
102114
{
103115
"map": "de_nuke",
@@ -126,7 +138,10 @@ Feature: Lobby Discovery
126138
When "blue" disconnects
127139
Then "blue" receives the network event "close"
128140

129-
When "green" requests all lobbies
141+
When "green" requests lobbies with:
142+
"""json
143+
{}
144+
"""
130145
Then "green" should have received only these lobbies:
131146
| code | playerCount |
132147
| HC6Y | 0 |
@@ -152,7 +167,7 @@ Feature: Lobby Discovery
152167
"""
153168
And "green" receives the network event "lobby" with the argument "19yrzmetd2bn7"
154169

155-
When "blue" requests lobbies with this filter:
170+
When "blue" requests lobbies with:
156171
"""json
157172
{
158173
"map": "de_nuke"
@@ -162,3 +177,20 @@ Feature: Lobby Discovery
162177
| code |
163178
| 19yrzmetd2bn7 |
164179
| 3qva9vyurwbb |
180+
181+
Scenario: Sort lobbies with a custom order
182+
Given "green" is connected as "1u8fw4aph5ypt" and ready for game "f666036d-d9e1-4d70-b0c3-4a68b24a9884"
183+
And these lobbies exist:
184+
| code | game | playerCount | public | created_at |
185+
| 1qva9vyurwbb | f666036d-d9e1-4d70-b0c3-4a68b24a9884 | 1 | true | 2020-01-03 |
186+
| 2qva9vyurwbb | f666036d-d9e1-4d70-b0c3-4a68b24a9884 | 3 | true | 2020-01-02 |
187+
| 3qva9vyurwbb | f666036d-d9e1-4d70-b0c3-4a68b24a9884 | 5 | true | 2020-01-01 |
188+
189+
When "green" requests lobbies with:
190+
| filter | {} |
191+
| sort | { "playerCount": -1 } |
192+
| limit | 2 |
193+
Then "green" should have received only these lobbies:
194+
| code | playerCount |
195+
| 3qva9vyurwbb | 5 |
196+
| 2qva9vyurwbb | 3 |

features/maxPlayers.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Feature: Lobbies can have a maximum number of players
4343
"""
4444
And "yellow" receives the network event "lobby" with the argument "h5yzwyizlwao"
4545

46-
When "yellow" requests lobbies with this filter:
46+
When "yellow" requests lobbies with:
4747
"""json
4848
{}
4949
"""
@@ -58,7 +58,7 @@ Feature: Lobbies can have a maximum number of players
5858
}
5959
"""
6060

61-
When "yellow" requests lobbies with this filter:
61+
When "yellow" requests lobbies with:
6262
"""json
6363
{}
6464
"""

features/password.feature

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Feature: Lobbies can be password protected
6262
"""
6363
And "yellow" receives the network event "lobby" with the argument "h5yzwyizlwao"
6464

65-
When "yellow" requests lobbies with this filter:
65+
When "yellow" requests lobbies with:
6666
"""json
6767
{}
6868
"""
@@ -76,7 +76,7 @@ Feature: Lobbies can be password protected
7676
"password": ""
7777
}
7878
"""
79-
And "yellow" requests lobbies with this filter:
79+
And "yellow" requests lobbies with:
8080
"""json
8181
{}
8282
"""

features/support/steps/network.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -210,21 +210,25 @@ When('{string} leaves the lobby', async function (this: World, playerName: strin
210210
await player.network.leave()
211211
})
212212

213-
When('{string} requests all lobbies', async function (this: World, playerName: string) {
213+
When('{string} requests lobbies with:', async function (this: World, playerName: string, payload: string | DataTable) {
214214
const player = this.players.get(playerName)
215215
if (player == null) {
216216
throw new Error('no such player')
217217
}
218-
const lobbies = await player.network.list()
219-
player.lastReceivedLobbies = lobbies
220-
})
218+
let filter: any
219+
let sort: Record<string, 1 | -1> | undefined
220+
let limit: number | undefined
221221

222-
When('{string} requests lobbies with this filter:', async function (this: World, playerName: string, filter: string) {
223-
const player = this.players.get(playerName)
224-
if (player == null) {
225-
throw new Error('no such player')
222+
if (typeof payload !== 'string') {
223+
const argsHash = payload.rowsHash()
224+
filter = argsHash.filter != null ? JSON.parse(argsHash.filter) : undefined
225+
sort = argsHash.sort != null ? JSON.parse(argsHash.sort) : undefined
226+
limit = argsHash.limit != null ? parseInt(argsHash.limit, 10) : undefined
227+
} else {
228+
filter = JSON.parse(payload)
226229
}
227-
const lobbies = await player.network.list(JSON.parse(filter))
230+
231+
const lobbies = await player.network.list(filter, sort, limit)
228232
player.lastReceivedLobbies = lobbies
229233
})
230234

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ require (
88
github.com/jackc/pgx/v5 v5.7.6
99
github.com/koenbollen/logging v0.0.0-20230520102501-e01d64214504
1010
github.com/ory/dockertest/v3 v3.12.0
11-
github.com/poki/mongodb-filter-to-postgres v1.0.6
11+
github.com/poki/mongodb-filter-to-postgres v1.0.7
1212
github.com/rs/cors v1.11.1
1313
github.com/rs/xid v1.6.0
1414
go.uber.org/zap v1.27.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
9898
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
9999
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
100100
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
101-
github.com/poki/mongodb-filter-to-postgres v1.0.6 h1:K33b8bng07GewuyTipTzVY5qjLVC3q+cURDmklzSLdc=
102-
github.com/poki/mongodb-filter-to-postgres v1.0.6/go.mod h1:AccQTAURp16s/pIp9pTuVqY64kyDJ5Dre4fNA1efO6A=
101+
github.com/poki/mongodb-filter-to-postgres v1.0.7 h1:PH6zGVAEptv0nH/eo4Q+ZRLqc/51M3Giihmmq/hY7wE=
102+
github.com/poki/mongodb-filter-to-postgres v1.0.7/go.mod h1:AccQTAURp16s/pIp9pTuVqY64kyDJ5Dre4fNA1efO6A=
103103
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
104104
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
105105
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=

internal/signaling/peer.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ func (p *Peer) HandleListPacket(ctx context.Context, packet ListPacket) error {
352352
if p.ID == "" {
353353
return fmt.Errorf("peer not connected")
354354
}
355-
lobbies, err := p.store.ListLobbies(ctx, p.Game, packet.Filter)
355+
lobbies, err := p.store.ListLobbies(ctx, p.Game, packet.Filter, packet.Sort, packet.Limit)
356356
if err != nil {
357357
return err
358358
}
@@ -462,13 +462,14 @@ func (p *Peer) HandleJoinPacket(ctx context.Context, packet JoinPacket) error {
462462

463463
err := p.store.JoinLobby(ctx, p.Game, packet.Lobby, p.ID, packet.Password)
464464
if err != nil {
465-
if err == stores.ErrNotFound {
465+
switch err {
466+
case stores.ErrNotFound:
466467
util.ReplyError(ctx, p.conn, util.ErrorWithCode(err, "lobby-not-found"))
467468
return nil
468-
} else if err == stores.ErrInvalidPassword {
469+
case stores.ErrInvalidPassword:
469470
util.ReplyError(ctx, p.conn, util.ErrorWithCode(err, "invalid-password"))
470471
return nil
471-
} else if err == stores.ErrLobbyIsFull {
472+
case stores.ErrLobbyIsFull:
472473
util.ReplyError(ctx, p.conn, util.ErrorWithCode(err, "lobby-is-full"))
473474
return nil
474475
}

internal/signaling/stores/postgres.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,19 +312,38 @@ func (s *PostgresStore) GetLobby(ctx context.Context, game, lobbyCode string) (L
312312
return lobby, nil
313313
}
314314

315-
func (s *PostgresStore) ListLobbies(ctx context.Context, game, filter string) ([]Lobby, error) {
315+
func (s *PostgresStore) ListLobbies(ctx context.Context, game, filter, sort string, limit int) ([]Lobby, error) {
316316
// TODO: Remove this.
317317
if filter == "" {
318318
filter = "{}"
319319
}
320320

321-
where, values, err := s.filterConverter.Convert([]byte(filter), 2)
321+
where, values, err := s.filterConverter.Convert([]byte(filter), 3)
322322
if err != nil {
323323
logger := logging.GetLogger(ctx)
324324
logger.Warn("failed to convert filter", zap.String("filter", filter), zap.Error(err))
325325
return nil, fmt.Errorf("invalid filter: %w", err)
326326
}
327327

328+
var order string
329+
if sort != "" {
330+
order, err = s.filterConverter.ConvertOrderBy([]byte(sort))
331+
if err != nil {
332+
logger := logging.GetLogger(ctx)
333+
logger.Warn("failed to convert order", zap.String("sort", sort), zap.Error(err))
334+
return nil, fmt.Errorf("invalid order: %w", err)
335+
}
336+
}
337+
if order == "" {
338+
order = `"createdAt" DESC, "code" ASC`
339+
} else {
340+
order += `, "createdAt" DESC, "code" ASC`
341+
}
342+
343+
if limit <= 0 {
344+
limit = 50
345+
}
346+
328347
var lobbies []Lobby
329348
rows, err := s.DB.Query(ctx, `
330349
WITH lobbies AS (
@@ -348,9 +367,9 @@ func (s *PostgresStore) ListLobbies(ctx context.Context, game, filter string) ([
348367
SELECT *
349368
FROM lobbies
350369
WHERE `+where+`
351-
ORDER BY "createdAt" DESC
352-
LIMIT 50
353-
`, append([]any{game}, values...)...)
370+
ORDER BY `+order+`
371+
LIMIT $2
372+
`, append([]any{game, limit}, values...)...)
354373
if err != nil {
355374
return nil, err
356375
}

internal/signaling/stores/shared.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ type Store interface {
2929
JoinLobby(ctx context.Context, game, lobby, id, password string) error
3030
LeaveLobby(ctx context.Context, game, lobby, id string) error
3131
GetLobby(ctx context.Context, game, lobby string) (Lobby, error)
32-
ListLobbies(ctx context.Context, game, filter string) ([]Lobby, error)
32+
ListLobbies(ctx context.Context, game, filter, sort string, limit int) ([]Lobby, error)
3333

3434
Subscribe(ctx context.Context, callback SubscriptionCallback, game, lobby, peerID string)
3535
Publish(ctx context.Context, topic string, data []byte) error

0 commit comments

Comments
 (0)