]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/initializers/database.ts
Add option to not transcode original resolution
[github/Chocobozzz/PeerTube.git] / server / initializers / database.ts
CommitLineData
d95d1559 1import { QueryTypes, Transaction } from 'sequelize'
3fd3ab2d 2import { Sequelize as SequelizeTypescript } from 'sequelize-typescript'
b2111066 3import { ActorCustomPageModel } from '@server/models/account/actor-custom-page'
f4796856
C
4import { TrackerModel } from '@server/models/server/tracker'
5import { VideoTrackerModel } from '@server/models/server/video-tracker'
7d9ba5c0
C
6import { UserModel } from '@server/models/user/user'
7import { UserNotificationModel } from '@server/models/user/user-notification'
8import { UserVideoHistoryModel } from '@server/models/user/user-video-history'
b2111066 9import { VideoJobInfoModel } from '@server/models/video/video-job-info'
26e3e98f 10import { VideoLiveSessionModel } from '@server/models/video/video-live-session'
9452d4fd 11import { VideoSourceModel } from '@server/models/video/video-source'
b2111066
C
12import { LocalVideoViewerModel } from '@server/models/view/local-video-viewer'
13import { LocalVideoViewerWatchSectionModel } from '@server/models/view/local-video-viewer-watch-section'
9452d4fd 14import { isTestOrDevInstance } from '../helpers/core-utils'
3fd3ab2d 15import { logger } from '../helpers/logger'
c6c0fa6c
C
16import { AbuseModel } from '../models/abuse/abuse'
17import { AbuseMessageModel } from '../models/abuse/abuse-message'
18import { VideoAbuseModel } from '../models/abuse/video-abuse'
19import { VideoCommentAbuseModel } from '../models/abuse/video-comment-abuse'
3fd3ab2d 20import { AccountModel } from '../models/account/account'
d95d1559 21import { AccountBlocklistModel } from '../models/account/account-blocklist'
3fd3ab2d 22import { AccountVideoRateModel } from '../models/account/account-video-rate'
7d9ba5c0
C
23import { ActorModel } from '../models/actor/actor'
24import { ActorFollowModel } from '../models/actor/actor-follow'
25import { ActorImageModel } from '../models/actor/actor-image'
3fd3ab2d 26import { ApplicationModel } from '../models/application/application'
3fd3ab2d
C
27import { OAuthClientModel } from '../models/oauth/oauth-client'
28import { OAuthTokenModel } from '../models/oauth/oauth-token'
d95d1559
C
29import { VideoRedundancyModel } from '../models/redundancy/video-redundancy'
30import { PluginModel } from '../models/server/plugin'
3fd3ab2d 31import { ServerModel } from '../models/server/server'
d95d1559 32import { ServerBlocklistModel } from '../models/server/server-blocklist'
7d9ba5c0 33import { UserNotificationSettingModel } from '../models/user/user-notification-setting'
d95d1559 34import { ScheduleVideoUpdateModel } from '../models/video/schedule-video-update'
3fd3ab2d 35import { TagModel } from '../models/video/tag'
d95d1559 36import { ThumbnailModel } from '../models/video/thumbnail'
3fd3ab2d 37import { VideoModel } from '../models/video/video'
3fd3ab2d 38import { VideoBlacklistModel } from '../models/video/video-blacklist'
d95d1559
C
39import { VideoCaptionModel } from '../models/video/video-caption'
40import { VideoChangeOwnershipModel } from '../models/video/video-change-ownership'
3fd3ab2d 41import { VideoChannelModel } from '../models/video/video-channel'
6d852470 42import { VideoCommentModel } from '../models/video/video-comment'
3fd3ab2d 43import { VideoFileModel } from '../models/video/video-file'
fbad87b0 44import { VideoImportModel } from '../models/video/video-import'
c6c0fa6c 45import { VideoLiveModel } from '../models/video/video-live'
418d092a
C
46import { VideoPlaylistModel } from '../models/video/video-playlist'
47import { VideoPlaylistElementModel } from '../models/video/video-playlist-element'
d95d1559
C
48import { VideoShareModel } from '../models/video/video-share'
49import { VideoStreamingPlaylistModel } from '../models/video/video-streaming-playlist'
50import { VideoTagModel } from '../models/video/video-tag'
b2111066 51import { VideoViewModel } from '../models/view/video-view'
d95d1559 52import { CONFIG } from './config'
fdbda9e3 53
3fd3ab2d 54require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string
8c308c2b 55
65fcc311
C
56const dbname = CONFIG.DATABASE.DBNAME
57const username = CONFIG.DATABASE.USERNAME
58const password = CONFIG.DATABASE.PASSWORD
228077ef
C
59const host = CONFIG.DATABASE.HOSTNAME
60const port = CONFIG.DATABASE.PORT
1c3386e8 61const poolMax = CONFIG.DATABASE.POOL.MAX
8c308c2b 62
6bc672da
C
63let dialectOptions: any = {}
64
65if (CONFIG.DATABASE.SSL) {
66 dialectOptions = {
67 ssl: {
68 rejectUnauthorized: false
69 }
70 }
71}
72
3fd3ab2d
C
73const sequelizeTypescript = new SequelizeTypescript({
74 database: dbname,
feb4bdfd 75 dialect: 'postgres',
6bc672da 76 dialectOptions,
228077ef
C
77 host,
78 port,
3fd3ab2d
C
79 username,
80 password,
1c3386e8
RK
81 pool: {
82 max: poolMax
83 },
9452d4fd 84 benchmark: isTestOrDevInstance(),
1735c825 85 isolationLevel: Transaction.ISOLATION_LEVELS.SERIALIZABLE,
075f16ca 86 logging: (message: string, benchmark: number) => {
165cdc75
C
87 if (process.env.NODE_DB_LOG === 'false') return
88
2a6cf69c 89 let newMessage = 'Executed SQL request'
9452d4fd 90 if (isTestOrDevInstance() === true && benchmark !== undefined) {
2a6cf69c 91 newMessage += ' in ' + benchmark + 'ms'
7920c273
C
92 }
93
452b3bea 94 logger.debug(newMessage, { sql: message, tags: [ 'sql' ] })
7920c273 95 }
feb4bdfd
C
96})
97
74055dc8
C
98function checkDatabaseConnectionOrDie () {
99 sequelizeTypescript.authenticate()
100 .then(() => logger.debug('Connection to PostgreSQL has been established successfully.'))
101 .catch(err => {
102
103 logger.error('Unable to connect to PostgreSQL database.', { err })
104 process.exit(-1)
105 })
106}
4f24f16e 107
91fea9fc 108async function initDatabaseModels (silent: boolean) {
3fd3ab2d
C
109 sequelizeTypescript.addModels([
110 ApplicationModel,
50d6de9c
C
111 ActorModel,
112 ActorFollowModel,
f4796856 113 ActorImageModel,
3fd3ab2d 114 AccountModel,
3fd3ab2d
C
115 OAuthClientModel,
116 OAuthTokenModel,
117 ServerModel,
118 TagModel,
119 AccountVideoRateModel,
3fd3ab2d 120 UserModel,
edbc9325 121 AbuseMessageModel,
d95d1559
C
122 AbuseModel,
123 VideoCommentAbuseModel,
3fd3ab2d 124 VideoAbuseModel,
b876eaf1 125 VideoModel,
74d63469 126 VideoChangeOwnershipModel,
3fd3ab2d 127 VideoChannelModel,
3fd3ab2d
C
128 VideoShareModel,
129 VideoFileModel,
2e401e85 130 VideoSourceModel,
40e87e9e 131 VideoCaptionModel,
3fd3ab2d
C
132 VideoBlacklistModel,
133 VideoTagModel,
2baea0c7 134 VideoCommentModel,
fbad87b0 135 ScheduleVideoUpdateModel,
6b616860 136 VideoImportModel,
c48e82b5 137 VideoViewModel,
6e46de09 138 VideoRedundancyModel,
7ad9b984 139 UserVideoHistoryModel,
c6c0fa6c 140 VideoLiveModel,
26e3e98f 141 VideoLiveSessionModel,
7ad9b984 142 AccountBlocklistModel,
cef534ed
C
143 ServerBlocklistModel,
144 UserNotificationModel,
09209296 145 UserNotificationSettingModel,
418d092a
C
146 VideoStreamingPlaylistModel,
147 VideoPlaylistModel,
e8bafea3 148 VideoPlaylistElementModel,
b2111066
C
149 LocalVideoViewerModel,
150 LocalVideoViewerWatchSectionModel,
f023a19c 151 ThumbnailModel,
d9a2a031
C
152 TrackerModel,
153 VideoTrackerModel,
2539932e 154 PluginModel,
0305db28
JB
155 ActorCustomPageModel,
156 VideoJobInfoModel
3fd3ab2d 157 ])
b769007f 158
57c36b27
C
159 // Check extensions exist in the database
160 await checkPostgresExtensions()
161
162 // Create custom PostgreSQL functions
163 await createFunctions()
164
f5028693 165 if (!silent) logger.info('Database %s is ready.', dbname)
b769007f 166}
65fcc311
C
167
168// ---------------------------------------------------------------------------
169
e02643f3 170export {
91fea9fc 171 initDatabaseModels,
74055dc8 172 checkDatabaseConnectionOrDie,
3fd3ab2d 173 sequelizeTypescript
74889a71 174}
57c36b27
C
175
176// ---------------------------------------------------------------------------
177
178async function checkPostgresExtensions () {
0b2f03d3
C
179 const promises = [
180 checkPostgresExtension('pg_trgm'),
181 checkPostgresExtension('unaccent')
57c36b27
C
182 ]
183
0b2f03d3
C
184 return Promise.all(promises)
185}
186
187async function checkPostgresExtension (extension: string) {
3acc5084 188 const query = `SELECT 1 FROM pg_available_extensions WHERE name = '${extension}' AND installed_version IS NOT NULL;`
1735c825
C
189 const options = {
190 type: QueryTypes.SELECT as QueryTypes.SELECT,
191 raw: true
192 }
193
3acc5084 194 const res = await sequelizeTypescript.query<object>(query, options)
57c36b27 195
3acc5084 196 if (!res || res.length === 0) {
1735c825 197 // Try to create the extension ourselves
0b2f03d3
C
198 try {
199 await sequelizeTypescript.query(`CREATE EXTENSION ${extension};`, { raw: true })
57c36b27 200
0b2f03d3
C
201 } catch {
202 const errorMessage = `You need to enable ${extension} extension in PostgreSQL. ` +
203 `You can do so by running 'CREATE EXTENSION ${extension};' as a PostgreSQL super user in ${CONFIG.DATABASE.DBNAME} database.`
204 throw new Error(errorMessage)
57c36b27
C
205 }
206 }
207}
208
f0ad4710 209function createFunctions () {
2cebd797
C
210 const query = `CREATE OR REPLACE FUNCTION immutable_unaccent(text)
211 RETURNS text AS
212$func$
213SELECT public.unaccent('public.unaccent', $1::text)
214$func$ LANGUAGE sql IMMUTABLE;`
57c36b27
C
215
216 return sequelizeTypescript.query(query, { raw: true })
217}