diff options
author | Chocobozzz <me@florianbigard.com> | 2023-05-22 15:52:59 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-05-22 15:52:59 +0200 |
commit | 3f0ceab06e5320f62f593c49daa30d963dbc36f9 (patch) | |
tree | c041455a11c55617251def4b7b35eff8d530a97a /server | |
parent | fa3da7a623fdb25be52ebff14e066a99ea9fb0cf (diff) | |
download | PeerTube-3f0ceab06e5320f62f593c49daa30d963dbc36f9.tar.gz PeerTube-3f0ceab06e5320f62f593c49daa30d963dbc36f9.tar.zst PeerTube-3f0ceab06e5320f62f593c49daa30d963dbc36f9.zip |
More robust quota check
Avoid concurrency issues with permanent lives
Diffstat (limited to 'server')
-rw-r--r-- | server/lib/live/live-manager.ts | 4 | ||||
-rw-r--r-- | server/lib/live/live-quota-store.ts | 14 | ||||
-rw-r--r-- | server/lib/live/shared/muxing-session.ts | 2 | ||||
-rw-r--r-- | server/tests/api/live/live-constraints.ts | 12 |
4 files changed, 19 insertions, 13 deletions
diff --git a/server/lib/live/live-manager.ts b/server/lib/live/live-manager.ts index f062e2fd3..5c6e69806 100644 --- a/server/lib/live/live-manager.ts +++ b/server/lib/live/live-manager.ts | |||
@@ -313,7 +313,7 @@ class LiveManager { | |||
313 | const liveSession = await this.saveStartingSession(videoLive) | 313 | const liveSession = await this.saveStartingSession(videoLive) |
314 | 314 | ||
315 | const user = await UserModel.loadByLiveId(videoLive.id) | 315 | const user = await UserModel.loadByLiveId(videoLive.id) |
316 | LiveQuotaStore.Instance.addNewLive(user.id, videoLive.id) | 316 | LiveQuotaStore.Instance.addNewLive(user.id, sessionId) |
317 | 317 | ||
318 | const muxingSession = new MuxingSession({ | 318 | const muxingSession = new MuxingSession({ |
319 | context: this.getContext(), | 319 | context: this.getContext(), |
@@ -359,7 +359,7 @@ class LiveManager { | |||
359 | muxingSession.on('after-cleanup', ({ videoUUID }) => { | 359 | muxingSession.on('after-cleanup', ({ videoUUID }) => { |
360 | this.muxingSessions.delete(sessionId) | 360 | this.muxingSessions.delete(sessionId) |
361 | 361 | ||
362 | LiveQuotaStore.Instance.removeLive(user.id, videoLive.id) | 362 | LiveQuotaStore.Instance.removeLive(user.id, sessionId) |
363 | 363 | ||
364 | muxingSession.destroy() | 364 | muxingSession.destroy() |
365 | 365 | ||
diff --git a/server/lib/live/live-quota-store.ts b/server/lib/live/live-quota-store.ts index 8ceccde98..44539faaa 100644 --- a/server/lib/live/live-quota-store.ts +++ b/server/lib/live/live-quota-store.ts | |||
@@ -2,31 +2,31 @@ class LiveQuotaStore { | |||
2 | 2 | ||
3 | private static instance: LiveQuotaStore | 3 | private static instance: LiveQuotaStore |
4 | 4 | ||
5 | private readonly livesPerUser = new Map<number, { liveId: number, size: number }[]>() | 5 | private readonly livesPerUser = new Map<number, { sessionId: string, size: number }[]>() |
6 | 6 | ||
7 | private constructor () { | 7 | private constructor () { |
8 | } | 8 | } |
9 | 9 | ||
10 | addNewLive (userId: number, liveId: number) { | 10 | addNewLive (userId: number, sessionId: string) { |
11 | if (!this.livesPerUser.has(userId)) { | 11 | if (!this.livesPerUser.has(userId)) { |
12 | this.livesPerUser.set(userId, []) | 12 | this.livesPerUser.set(userId, []) |
13 | } | 13 | } |
14 | 14 | ||
15 | const currentUserLive = { liveId, size: 0 } | 15 | const currentUserLive = { sessionId, size: 0 } |
16 | const livesOfUser = this.livesPerUser.get(userId) | 16 | const livesOfUser = this.livesPerUser.get(userId) |
17 | livesOfUser.push(currentUserLive) | 17 | livesOfUser.push(currentUserLive) |
18 | } | 18 | } |
19 | 19 | ||
20 | removeLive (userId: number, liveId: number) { | 20 | removeLive (userId: number, sessionId: string) { |
21 | const newLivesPerUser = this.livesPerUser.get(userId) | 21 | const newLivesPerUser = this.livesPerUser.get(userId) |
22 | .filter(o => o.liveId !== liveId) | 22 | .filter(o => o.sessionId !== sessionId) |
23 | 23 | ||
24 | this.livesPerUser.set(userId, newLivesPerUser) | 24 | this.livesPerUser.set(userId, newLivesPerUser) |
25 | } | 25 | } |
26 | 26 | ||
27 | addQuotaTo (userId: number, liveId: number, size: number) { | 27 | addQuotaTo (userId: number, sessionId: string, size: number) { |
28 | const lives = this.livesPerUser.get(userId) | 28 | const lives = this.livesPerUser.get(userId) |
29 | const live = lives.find(l => l.liveId === liveId) | 29 | const live = lives.find(l => l.sessionId === sessionId) |
30 | 30 | ||
31 | live.size += size | 31 | live.size += size |
32 | } | 32 | } |
diff --git a/server/lib/live/shared/muxing-session.ts b/server/lib/live/shared/muxing-session.ts index c672ec4d6..434b308e6 100644 --- a/server/lib/live/shared/muxing-session.ts +++ b/server/lib/live/shared/muxing-session.ts | |||
@@ -271,7 +271,7 @@ class MuxingSession extends EventEmitter { | |||
271 | try { | 271 | try { |
272 | const segmentStat = await stat(segmentPath) | 272 | const segmentStat = await stat(segmentPath) |
273 | 273 | ||
274 | LiveQuotaStore.Instance.addQuotaTo(this.user.id, this.videoLive.id, segmentStat.size) | 274 | LiveQuotaStore.Instance.addQuotaTo(this.user.id, this.sessionId, segmentStat.size) |
275 | 275 | ||
276 | const canUpload = await this.isAbleToUploadVideoWithCache(this.user.id) | 276 | const canUpload = await this.isAbleToUploadVideoWithCache(this.user.id) |
277 | 277 | ||
diff --git a/server/tests/api/live/live-constraints.ts b/server/tests/api/live/live-constraints.ts index 168241b79..7af6af193 100644 --- a/server/tests/api/live/live-constraints.ts +++ b/server/tests/api/live/live-constraints.ts | |||
@@ -2,7 +2,7 @@ | |||
2 | 2 | ||
3 | import { expect } from 'chai' | 3 | import { expect } from 'chai' |
4 | import { wait } from '@shared/core-utils' | 4 | import { wait } from '@shared/core-utils' |
5 | import { LiveVideoError, VideoPrivacy } from '@shared/models' | 5 | import { LiveVideoError, UserVideoQuota, VideoPrivacy } from '@shared/models' |
6 | import { | 6 | import { |
7 | cleanupTests, | 7 | cleanupTests, |
8 | ConfigCommand, | 8 | ConfigCommand, |
@@ -172,12 +172,18 @@ describe('Test live constraints', function () { | |||
172 | const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ token: userAccessToken, videoId: userVideoLiveoId }) | 172 | const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ token: userAccessToken, videoId: userVideoLiveoId }) |
173 | 173 | ||
174 | await servers[0].live.waitUntilPublished({ videoId: userVideoLiveoId }) | 174 | await servers[0].live.waitUntilPublished({ videoId: userVideoLiveoId }) |
175 | // Wait previous live cleanups | ||
176 | await wait(3000) | ||
175 | 177 | ||
176 | const baseQuota = await servers[0].users.getMyQuotaUsed({ token: userAccessToken }) | 178 | const baseQuota = await servers[0].users.getMyQuotaUsed({ token: userAccessToken }) |
177 | 179 | ||
178 | await wait(3000) | 180 | let quotaUser: UserVideoQuota |
181 | |||
182 | do { | ||
183 | await wait(500) | ||
179 | 184 | ||
180 | const quotaUser = await servers[0].users.getMyQuotaUsed({ token: userAccessToken }) | 185 | quotaUser = await servers[0].users.getMyQuotaUsed({ token: userAccessToken }) |
186 | } while (quotaUser.videoQuotaUsed < baseQuota.videoQuotaUsed) | ||
181 | 187 | ||
182 | const { data } = await servers[0].users.list() | 188 | const { data } = await servers[0].users.list() |
183 | const quotaAdmin = data.find(u => u.username === 'user1') | 189 | const quotaAdmin = data.find(u => u.username === 'user1') |