diff options
author | Chocobozzz <me@florianbigard.com> | 2023-05-15 11:09:16 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2023-05-15 11:09:16 +0200 |
commit | be3ec61a6669cd96cc797c7a7a53105179213f69 (patch) | |
tree | d1af93c972bb22ea6d071137f5d9bed15dbdd44c | |
parent | 65b2ec673d321bbbe4fc26b90720c4b2018048f8 (diff) | |
download | PeerTube-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.ts | 14 |
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 @@ | |||
1 | import { writeJson } from 'fs-extra' | 1 | import { move, writeJson } from 'fs-extra' |
2 | import PQueue from 'p-queue' | ||
2 | import { basename } from 'path' | 3 | import { basename } from 'path' |
3 | import { mapToJSON } from '@server/helpers/core-utils' | 4 | import { mapToJSON } from '@server/helpers/core-utils' |
4 | import { logger, loggerTagsFactory } from '@server/helpers/logger' | 5 | import { logger, loggerTagsFactory } from '@server/helpers/logger' |
5 | import { MStreamingPlaylistVideo } from '@server/types/models' | 6 | import { MStreamingPlaylistVideo } from '@server/types/models' |
6 | import { buildSha256Segment } from '../hls' | 7 | import { buildSha256Segment } from '../hls' |
7 | import { storeHLSFileFromPath } from '../object-storage' | 8 | import { storeHLSFileFromPath } from '../object-storage' |
8 | import PQueue from 'p-queue' | ||
9 | 9 | ||
10 | const lTags = loggerTagsFactory('live') | 10 | const 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) |