aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rwxr-xr-xscripts/prune-storage.ts37
-rw-r--r--server/models/redundancy/video-redundancy.ts32
2 files changed, 60 insertions, 9 deletions
diff --git a/scripts/prune-storage.ts b/scripts/prune-storage.ts
index b00f20934..4088fa700 100755
--- a/scripts/prune-storage.ts
+++ b/scripts/prune-storage.ts
@@ -4,6 +4,7 @@ import { CONFIG } from '../server/initializers/constants'
4import { VideoModel } from '../server/models/video/video' 4import { VideoModel } from '../server/models/video/video'
5import { initDatabaseModels } from '../server/initializers' 5import { initDatabaseModels } from '../server/initializers'
6import { remove, readdir } from 'fs-extra' 6import { remove, readdir } from 'fs-extra'
7import { VideoRedundancyModel } from '../server/models/redundancy/video-redundancy'
7 8
8run() 9run()
9 .then(() => process.exit(0)) 10 .then(() => process.exit(0))
@@ -15,16 +16,23 @@ run()
15async function run () { 16async function run () {
16 await initDatabaseModels(true) 17 await initDatabaseModels(true)
17 18
18 const storageToPrune = [ 19 const storageOnlyOwnedToPrune = [
19 CONFIG.STORAGE.VIDEOS_DIR, 20 CONFIG.STORAGE.VIDEOS_DIR,
20 CONFIG.STORAGE.PREVIEWS_DIR,
21 CONFIG.STORAGE.THUMBNAILS_DIR,
22 CONFIG.STORAGE.TORRENTS_DIR 21 CONFIG.STORAGE.TORRENTS_DIR
23 ] 22 ]
24 23
24 const storageForAllToPrune = [
25 CONFIG.STORAGE.PREVIEWS_DIR,
26 CONFIG.STORAGE.THUMBNAILS_DIR
27 ]
28
25 let toDelete: string[] = [] 29 let toDelete: string[] = []
26 for (const directory of storageToPrune) { 30 for (const directory of storageOnlyOwnedToPrune) {
27 toDelete = toDelete.concat(await pruneDirectory(directory)) 31 toDelete = toDelete.concat(await pruneDirectory(directory, true))
32 }
33
34 for (const directory of storageForAllToPrune) {
35 toDelete = toDelete.concat(await pruneDirectory(directory, false))
28 } 36 }
29 37
30 if (toDelete.length === 0) { 38 if (toDelete.length === 0) {
@@ -48,17 +56,27 @@ async function run () {
48 } 56 }
49} 57}
50 58
51async function pruneDirectory (directory: string) { 59async function pruneDirectory (directory: string, onlyOwned = false) {
52 const files = await readdir(directory) 60 const files = await readdir(directory)
53 61
54 const toDelete: string[] = [] 62 const toDelete: string[] = []
55 for (const file of files) { 63 for (const file of files) {
56 const uuid = getUUIDFromFilename(file) 64 const uuid = getUUIDFromFilename(file)
57 let video: VideoModel 65 let video: VideoModel
66 let localRedundancy: boolean
58 67
59 if (uuid) video = await VideoModel.loadByUUIDWithFile(uuid) 68 if (uuid) {
69 video = await VideoModel.loadByUUIDWithFile(uuid)
70 localRedundancy = await VideoRedundancyModel.isLocalByVideoUUIDExists(uuid)
71 }
60 72
61 if (!uuid || !video) toDelete.push(join(directory, file)) 73 if (
74 !uuid ||
75 !video ||
76 (onlyOwned === true && (video.isOwned() === false && localRedundancy === false))
77 ) {
78 toDelete.push(join(directory, file))
79 }
62 } 80 }
63 81
64 return toDelete 82 return toDelete
@@ -80,7 +98,8 @@ async function askConfirmation () {
80 properties: { 98 properties: {
81 confirm: { 99 confirm: {
82 type: 'string', 100 type: 'string',
83 description: 'Are you sure you want to delete these files? Please check carefully', 101 description: 'These following unused files can be deleted, but please check your backups first (bugs happen).' +
102 ' Can we delete these files?',
84 default: 'n', 103 default: 'n',
85 required: true 104 required: true
86 } 105 }
diff --git a/server/models/redundancy/video-redundancy.ts b/server/models/redundancy/video-redundancy.ts
index e67164802..791ba3137 100644
--- a/server/models/redundancy/video-redundancy.ts
+++ b/server/models/redundancy/video-redundancy.ts
@@ -146,6 +146,38 @@ export class VideoRedundancyModel extends Model<VideoRedundancyModel> {
146 return VideoRedundancyModel.findOne(query) 146 return VideoRedundancyModel.findOne(query)
147 } 147 }
148 148
149 static async isLocalByVideoUUIDExists (uuid: string) {
150 const actor = await getServerActor()
151
152 const query = {
153 raw: true,
154 attributes: [ 'id' ],
155 where: {
156 actorId: actor.id
157 },
158 include: [
159 {
160 attributes: [ ],
161 model: VideoFileModel,
162 required: true,
163 include: [
164 {
165 attributes: [ ],
166 model: VideoModel,
167 required: true,
168 where: {
169 uuid
170 }
171 }
172 ]
173 }
174 ]
175 }
176
177 return VideoRedundancyModel.findOne(query)
178 .then(r => !!r)
179 }
180
149 static async getVideoSample (p: Bluebird<VideoModel[]>) { 181 static async getVideoSample (p: Bluebird<VideoModel[]>) {
150 const rows = await p 182 const rows = await p
151 const ids = rows.map(r => r.id) 183 const ids = rows.map(r => r.id)