aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2023-05-15 11:09:16 +0200
committerChocobozzz <me@florianbigard.com>2023-05-15 11:09:16 +0200
commitbe3ec61a6669cd96cc797c7a7a53105179213f69 (patch)
treed1af93c972bb22ea6d071137f5d9bed15dbdd44c
parent65b2ec673d321bbbe4fc26b90720c4b2018048f8 (diff)
downloadPeerTube-be3ec61a6669cd96cc797c7a7a53105179213f69.tar.gz
PeerTube-be3ec61a6669cd96cc797c7a7a53105179213f69.tar.zst
PeerTube-be3ec61a6669cd96cc797c7a7a53105179213f69.zip
Atomic live segment file write
-rw-r--r--server/lib/live/live-segment-sha-store.ts14
1 files changed, 11 insertions, 3 deletions
diff --git a/server/lib/live/live-segment-sha-store.ts b/server/lib/live/live-segment-sha-store.ts
index 251301141..17e0c6a82 100644
--- a/server/lib/live/live-segment-sha-store.ts
+++ b/server/lib/live/live-segment-sha-store.ts
@@ -1,11 +1,11 @@
1import { writeJson } from 'fs-extra' 1import { move, writeJson } from 'fs-extra'
2import PQueue from 'p-queue'
2import { basename } from 'path' 3import { basename } from 'path'
3import { mapToJSON } from '@server/helpers/core-utils' 4import { mapToJSON } from '@server/helpers/core-utils'
4import { logger, loggerTagsFactory } from '@server/helpers/logger' 5import { logger, loggerTagsFactory } from '@server/helpers/logger'
5import { MStreamingPlaylistVideo } from '@server/types/models' 6import { MStreamingPlaylistVideo } from '@server/types/models'
6import { buildSha256Segment } from '../hls' 7import { buildSha256Segment } from '../hls'
7import { storeHLSFileFromPath } from '../object-storage' 8import { storeHLSFileFromPath } from '../object-storage'
8import PQueue from 'p-queue'
9 9
10const lTags = loggerTagsFactory('live') 10const lTags = loggerTagsFactory('live')
11 11
@@ -14,7 +14,10 @@ class LiveSegmentShaStore {
14 private readonly segmentsSha256 = new Map<string, string>() 14 private readonly segmentsSha256 = new Map<string, string>()
15 15
16 private readonly videoUUID: string 16 private readonly videoUUID: string
17
17 private readonly sha256Path: string 18 private readonly sha256Path: string
19 private readonly sha256PathTMP: string
20
18 private readonly streamingPlaylist: MStreamingPlaylistVideo 21 private readonly streamingPlaylist: MStreamingPlaylistVideo
19 private readonly sendToObjectStorage: boolean 22 private readonly sendToObjectStorage: boolean
20 private readonly writeQueue = new PQueue({ concurrency: 1 }) 23 private readonly writeQueue = new PQueue({ concurrency: 1 })
@@ -26,7 +29,10 @@ class LiveSegmentShaStore {
26 sendToObjectStorage: boolean 29 sendToObjectStorage: boolean
27 }) { 30 }) {
28 this.videoUUID = options.videoUUID 31 this.videoUUID = options.videoUUID
32
29 this.sha256Path = options.sha256Path 33 this.sha256Path = options.sha256Path
34 this.sha256PathTMP = options.sha256Path + '.tmp'
35
30 this.streamingPlaylist = options.streamingPlaylist 36 this.streamingPlaylist = options.streamingPlaylist
31 this.sendToObjectStorage = options.sendToObjectStorage 37 this.sendToObjectStorage = options.sendToObjectStorage
32 } 38 }
@@ -66,7 +72,9 @@ class LiveSegmentShaStore {
66 72
67 private writeToDisk () { 73 private writeToDisk () {
68 return this.writeQueue.add(async () => { 74 return this.writeQueue.add(async () => {
69 await writeJson(this.sha256Path, mapToJSON(this.segmentsSha256)) 75 // Atomic write
76 await writeJson(this.sha256PathTMP, mapToJSON(this.segmentsSha256))
77 await move(this.sha256PathTMP, this.sha256Path, { overwrite: true })
70 78
71 if (this.sendToObjectStorage) { 79 if (this.sendToObjectStorage) {
72 const url = await storeHLSFileFromPath(this.streamingPlaylist, this.sha256Path) 80 const url = await storeHLSFileFromPath(this.streamingPlaylist, this.sha256Path)