Skip to content

Commit 356c8a8

Browse files
authored
Merge pull request #558 from TaloDev/develop
Release 0.80.6
2 parents 76e88ee + e24e3b4 commit 356c8a8

File tree

6 files changed

+64
-9
lines changed

6 files changed

+64
-9
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "game-services",
3-
"version": "0.80.5",
3+
"version": "0.80.6",
44
"description": "",
55
"main": "src/index.ts",
66
"scripts": {

src/entities/subscribers/player-group.subscriber.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Player from '../player'
44
import LeaderboardEntry from '../leaderboard-entry'
55
import PlayerGameStat from '../player-game-stat'
66
import { createRedisConnection } from '../../config/redis.config'
7+
import { captureException } from '@sentry/node'
78

89
const enableLogging = process.env.NODE_ENV !== 'test'
910

@@ -57,7 +58,8 @@ export default class PlayerGroupSubscriber implements EventSubscriber {
5758
console.info(`Group memberships lock created for ${player.id}`)
5859
}
5960

60-
if (await checkGroupMemberships(em, player)) {
61+
const shouldRefresh = await checkGroupMemberships(em, player)
62+
if (shouldRefresh) {
6163
const label = `Refreshing memberships for ${player.id}`
6264

6365
/* v8 ignore next 3 */
@@ -73,6 +75,9 @@ export default class PlayerGroupSubscriber implements EventSubscriber {
7375
}
7476
}
7577
}
78+
} catch (err) {
79+
console.error(`Failed checking memberships: ${(err as Error).message}`)
80+
captureException(err)
7681
} finally {
7782
if (lockCreated) {
7883
/* v8 ignore next 3 */

src/lib/groups/checkGroupMemberships.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class PlayerGroupMember {
2525
export default async function checkGroupMemberships(em: EntityManager, player: Player): Promise<boolean> {
2626
const groups = await em.repo(PlayerGroup).find({
2727
game: player.game
28-
}, getResultCacheOptions(`groups-for-memberships-${player.game}`))
28+
}, getResultCacheOptions(`groups-for-memberships-${player.game}`, 1000))
2929

3030
if (groups.length === 0) {
3131
return false
@@ -38,7 +38,7 @@ export default async function checkGroupMemberships(em: EntityManager, player: P
3838
console.time(label)
3939
}
4040

41-
let shouldFlush = false
41+
let shouldRefresh = false
4242

4343
for (const group of groups) {
4444
await group.members.init({ ref: true })
@@ -49,7 +49,7 @@ export default async function checkGroupMemberships(em: EntityManager, player: P
4949
const notEligibleButInGroup = !playerIsEligible && playerCurrentlyInGroup
5050

5151
if (eligibleButNotInGroup || notEligibleButInGroup) {
52-
shouldFlush = true
52+
shouldRefresh = true
5353
}
5454

5555
const groupMember = new PlayerGroupMember(player, group)
@@ -74,5 +74,5 @@ export default async function checkGroupMemberships(em: EntityManager, player: P
7474
console.timeEnd(label)
7575
}
7676

77-
return shouldFlush
77+
return shouldRefresh
7878
}

src/tasks/cleanupOnlinePlayers.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type CleanupStats = {
1818
newSessionDurationMinutes: number[]
1919
newSessionDurationLessThanOneMinute: number
2020
presenceUpdated: number
21+
presenceDeleted: number
2122
}
2223

2324
let cleanupStats: Record<number, CleanupStats>
@@ -31,7 +32,8 @@ function getOrCreateGameCleanupStats(gameId: number): CleanupStats {
3132
hadSessionSinceOriginal: 0,
3233
newSessionDurationMinutes: [],
3334
newSessionDurationLessThanOneMinute: 0,
34-
presenceUpdated: 0
35+
presenceUpdated: 0,
36+
presenceDeleted: 0
3537
}
3638
}
3739
return cleanupStats[gameId]
@@ -134,6 +136,12 @@ async function cleanupPresence(em: EntityManager, clickhouse: ClickHouseClient,
134136
}
135137
}
136138

139+
async function removeDisconnectedPresence(em: EntityManager, presence: PlayerPresence) {
140+
const gameStats = getOrCreateGameCleanupStats(presence.playerAlias.player.game.id)
141+
gameStats.presenceDeleted++
142+
await em.removeAndFlush(presence)
143+
}
144+
137145
export default async function cleanupOnlinePlayers() {
138146
const orm = await MikroORM.init(ormConfig)
139147
const em = orm.em.fork()
@@ -157,6 +165,17 @@ export default async function cleanupOnlinePlayers() {
157165
await cleanupSession(em, clickhouse, session)
158166
}
159167

168+
// todo, find out how this is happening
169+
const disconnectedPresence = await em.repo(PlayerPresence).find({
170+
player: null
171+
})
172+
173+
console.info(`Found ${disconnectedPresence.length} disconnected presence`)
174+
175+
for (const presence of disconnectedPresence) {
176+
await removeDisconnectedPresence(em, presence)
177+
}
178+
160179
const onlinePresence = await em.repo(PlayerPresence).find({
161180
online: true,
162181
updatedAt: {
@@ -167,6 +186,8 @@ export default async function cleanupOnlinePlayers() {
167186
populate: ['player']
168187
})
169188

189+
console.info(`Found ${onlinePresence.length} online presence`)
190+
170191
for (const presence of onlinePresence) {
171192
await cleanupPresence(em, clickhouse, presence)
172193
}

tests/tasks/cleanupOnlinePlayers.test.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { formatDateForClickHouse } from '../../src/lib/clickhouse/formatDateTime
77
import PlayerPresenceFactory from '../fixtures/PlayerPresenceFactory'
88
import assert from 'node:assert'
99
import PlayerPresence from '../../src/entities/player-presence'
10+
import Player from '../../src/entities/player'
1011

1112
describe('cleanupOnlinePlayers', () => {
1213
beforeEach(() => {
@@ -387,4 +388,32 @@ describe('cleanupOnlinePlayers', () => {
387388
expect(updatedPresence.online).toBe(true)
388389
expect(updatedPresence.updatedAt).toEqual(originalUpdatedAt)
389390
})
391+
392+
it('should delete presence that no longer has a player', async () => {
393+
vi.useRealTimers()
394+
395+
const [, game] = await createOrganisationAndGame()
396+
const player = await new PlayerFactory([game])
397+
.state(async (player) => ({
398+
presence: await new PlayerPresenceFactory(player.game)
399+
.online()
400+
.state(() => ({ updatedAt: subDays(new Date(), 2) }))
401+
.one()
402+
}))
403+
.one()
404+
await em.persistAndFlush(player)
405+
406+
assert(player.presence)
407+
const originalPresenceId = player.presence.id
408+
409+
await em.nativeDelete(Player, player.id)
410+
411+
const originalPresence = await em.repo(PlayerPresence).findOne(originalPresenceId)
412+
assert(originalPresence)
413+
414+
await cleanupOnlinePlayers()
415+
416+
const updatedPresence = await em.refresh(originalPresence)
417+
expect(updatedPresence).toBeNull()
418+
})
390419
})

0 commit comments

Comments
 (0)