]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
More robust quota check
authorChocobozzz <me@florianbigard.com>
Mon, 22 May 2023 13:52:59 +0000 (15:52 +0200)
committerChocobozzz <me@florianbigard.com>
Mon, 22 May 2023 13:52:59 +0000 (15:52 +0200)
Avoid concurrency issues with permanent lives

server/lib/live/live-manager.ts
server/lib/live/live-quota-store.ts
server/lib/live/shared/muxing-session.ts
server/tests/api/live/live-constraints.ts

index f062e2fd3219059bebe405814fa42178ed5ee8f0..5c6e69806b77532d8ee05751b8d72d065b4a4f80 100644 (file)
@@ -313,7 +313,7 @@ class LiveManager {
     const liveSession = await this.saveStartingSession(videoLive)
 
     const user = await UserModel.loadByLiveId(videoLive.id)
-    LiveQuotaStore.Instance.addNewLive(user.id, videoLive.id)
+    LiveQuotaStore.Instance.addNewLive(user.id, sessionId)
 
     const muxingSession = new MuxingSession({
       context: this.getContext(),
@@ -359,7 +359,7 @@ class LiveManager {
     muxingSession.on('after-cleanup', ({ videoUUID }) => {
       this.muxingSessions.delete(sessionId)
 
-      LiveQuotaStore.Instance.removeLive(user.id, videoLive.id)
+      LiveQuotaStore.Instance.removeLive(user.id, sessionId)
 
       muxingSession.destroy()
 
index 8ceccde98be9fd4f67b966150b6639c19218aa9f..44539faaa39066301b519f458e10d9ec8f54f660 100644 (file)
@@ -2,31 +2,31 @@ class LiveQuotaStore {
 
   private static instance: LiveQuotaStore
 
-  private readonly livesPerUser = new Map<number, { liveId: number, size: number }[]>()
+  private readonly livesPerUser = new Map<number, { sessionId: string, size: number }[]>()
 
   private constructor () {
   }
 
-  addNewLive (userId: number, liveId: number) {
+  addNewLive (userId: number, sessionId: string) {
     if (!this.livesPerUser.has(userId)) {
       this.livesPerUser.set(userId, [])
     }
 
-    const currentUserLive = { liveId, size: 0 }
+    const currentUserLive = { sessionId, size: 0 }
     const livesOfUser = this.livesPerUser.get(userId)
     livesOfUser.push(currentUserLive)
   }
 
-  removeLive (userId: number, liveId: number) {
+  removeLive (userId: number, sessionId: string) {
     const newLivesPerUser = this.livesPerUser.get(userId)
-                                             .filter(o => o.liveId !== liveId)
+                                             .filter(o => o.sessionId !== sessionId)
 
     this.livesPerUser.set(userId, newLivesPerUser)
   }
 
-  addQuotaTo (userId: number, liveId: number, size: number) {
+  addQuotaTo (userId: number, sessionId: string, size: number) {
     const lives = this.livesPerUser.get(userId)
-    const live = lives.find(l => l.liveId === liveId)
+    const live = lives.find(l => l.sessionId === sessionId)
 
     live.size += size
   }
index c672ec4d6c28db87bfe39f3cbd2a15422f1abcc4..434b308e6133eacf8860f3b3db3fd64d0e2ed3e8 100644 (file)
@@ -271,7 +271,7 @@ class MuxingSession extends EventEmitter {
     try {
       const segmentStat = await stat(segmentPath)
 
-      LiveQuotaStore.Instance.addQuotaTo(this.user.id, this.videoLive.id, segmentStat.size)
+      LiveQuotaStore.Instance.addQuotaTo(this.user.id, this.sessionId, segmentStat.size)
 
       const canUpload = await this.isAbleToUploadVideoWithCache(this.user.id)
 
index 168241b797b87d20c586ec38a623eb0694c01ce4..7af6af193352c47b6006a39f0fbc0b580f05293b 100644 (file)
@@ -2,7 +2,7 @@
 
 import { expect } from 'chai'
 import { wait } from '@shared/core-utils'
-import { LiveVideoError, VideoPrivacy } from '@shared/models'
+import { LiveVideoError, UserVideoQuota, VideoPrivacy } from '@shared/models'
 import {
   cleanupTests,
   ConfigCommand,
@@ -172,12 +172,18 @@ describe('Test live constraints', function () {
     const ffmpegCommand = await servers[0].live.sendRTMPStreamInVideo({ token: userAccessToken, videoId: userVideoLiveoId })
 
     await servers[0].live.waitUntilPublished({ videoId: userVideoLiveoId })
+    // Wait previous live cleanups
+    await wait(3000)
 
     const baseQuota = await servers[0].users.getMyQuotaUsed({ token: userAccessToken })
 
-    await wait(3000)
+    let quotaUser: UserVideoQuota
+
+    do {
+      await wait(500)
 
-    const quotaUser = await servers[0].users.getMyQuotaUsed({ token: userAccessToken })
+      quotaUser = await servers[0].users.getMyQuotaUsed({ token: userAccessToken })
+    } while (quotaUser.videoQuotaUsed < baseQuota.videoQuotaUsed)
 
     const { data } = await servers[0].users.list()
     const quotaAdmin = data.find(u => u.username === 'user1')