]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/models/video/video-job-info.ts
Implement remote runner jobs in server
[github/Chocobozzz/PeerTube.git] / server / models / video / video-job-info.ts
CommitLineData
0305db28
JB
1import { Op, QueryTypes, Transaction } from 'sequelize'
2import { AllowNull, BelongsTo, Column, CreatedAt, Default, ForeignKey, IsInt, Model, Table, Unique, UpdatedAt } from 'sequelize-typescript'
0c9668f7 3import { forceNumber } from '@shared/core-utils'
6b5f72be 4import { AttributesOnly } from '@shared/typescript-utils'
0305db28
JB
5import { VideoModel } from './video'
6
025d858e
C
7export type VideoJobInfoColumnType = 'pendingMove' | 'pendingTranscode'
8
0305db28
JB
9@Table({
10 tableName: 'videoJobInfo',
11 indexes: [
12 {
13 fields: [ 'videoId' ],
14 where: {
15 videoId: {
16 [Op.ne]: null
17 }
18 }
19 }
20 ]
21})
22
23export class VideoJobInfoModel extends Model<Partial<AttributesOnly<VideoJobInfoModel>>> {
24 @CreatedAt
25 createdAt: Date
26
27 @UpdatedAt
28 updatedAt: Date
29
30 @AllowNull(false)
31 @Default(0)
32 @IsInt
33 @Column
34 pendingMove: number
35
36 @AllowNull(false)
37 @Default(0)
38 @IsInt
39 @Column
40 pendingTranscode: number
41
42 @ForeignKey(() => VideoModel)
43 @Unique
44 @Column
45 videoId: number
46
47 @BelongsTo(() => VideoModel, {
48 foreignKey: {
49 allowNull: false
50 },
51 onDelete: 'cascade'
52 })
53 Video: VideoModel
54
ad5db104 55 static load (videoId: number, transaction?: Transaction) {
0305db28
JB
56 const where = {
57 videoId
58 }
59
60 return VideoJobInfoModel.findOne({ where, transaction })
61 }
62
0c9668f7 63 static async increaseOrCreate (videoUUID: string, column: VideoJobInfoColumnType, amountArg = 1): Promise<number> {
0305db28 64 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } }
0c9668f7 65 const amount = forceNumber(amountArg)
0305db28 66
0c9668f7 67 const [ result ] = await VideoJobInfoModel.sequelize.query<{ pendingMove: number }>(`
0305db28
JB
68 INSERT INTO "videoJobInfo" ("videoId", "${column}", "createdAt", "updatedAt")
69 SELECT
0c9668f7 70 "video"."id" AS "videoId", ${amount}, NOW(), NOW()
0305db28
JB
71 FROM
72 "video"
73 WHERE
74 "video"."uuid" = $videoUUID
75 ON CONFLICT ("videoId") DO UPDATE
76 SET
0c9668f7 77 "${column}" = "videoJobInfo"."${column}" + ${amount},
0305db28
JB
78 "updatedAt" = NOW()
79 RETURNING
80 "${column}"
81 `, options)
82
0c9668f7 83 return result[column]
0305db28
JB
84 }
85
025d858e 86 static async decrease (videoUUID: string, column: VideoJobInfoColumnType): Promise<number> {
0305db28
JB
87 const options = { type: QueryTypes.SELECT as QueryTypes.SELECT, bind: { videoUUID } }
88
0c9668f7 89 const result = await VideoJobInfoModel.sequelize.query(`
0305db28
JB
90 UPDATE
91 "videoJobInfo"
92 SET
93 "${column}" = "videoJobInfo"."${column}" - 1,
94 "updatedAt" = NOW()
95 FROM "video"
96 WHERE
97 "video"."id" = "videoJobInfo"."videoId" AND "video"."uuid" = $videoUUID
98 RETURNING
99 "${column}";
100 `, options)
101
52d6c2e0
C
102 if (result.length === 0) return undefined
103
0c9668f7 104 return result[0][column]
0305db28 105 }
dbd9fb44
C
106
107 static async abortAllTasks (videoUUID: string, column: VideoJobInfoColumnType): Promise<void> {
108 const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE, bind: { videoUUID } }
109
110 await VideoJobInfoModel.sequelize.query(`
111 UPDATE
112 "videoJobInfo"
113 SET
114 "${column}" = 0,
115 "updatedAt" = NOW()
116 FROM "video"
117 WHERE
118 "video"."id" = "videoJobInfo"."videoId" AND "video"."uuid" = $videoUUID
119 `, options)
120 }
0305db28 121}