aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/initializers/database.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/initializers/database.ts')
-rw-r--r--server/initializers/database.ts186
1 files changed, 53 insertions, 133 deletions
diff --git a/server/initializers/database.ts b/server/initializers/database.ts
index bb95992e1..f9e24c6b8 100644
--- a/server/initializers/database.ts
+++ b/server/initializers/database.ts
@@ -1,72 +1,43 @@
1import { join } from 'path' 1import { Sequelize as SequelizeTypescript } from 'sequelize-typescript'
2import { flattenDepth } from 'lodash' 2import { isTestInstance } from '../helpers/core-utils'
3require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string 3import { logger } from '../helpers/logger'
4import * as Sequelize from 'sequelize'
5import { AvatarModel } from '../models/avatar'
6 4
5import { AccountModel } from '../models/account/account'
6import { AccountFollowModel } from '../models/account/account-follow'
7import { AccountVideoRateModel } from '../models/account/account-video-rate'
8import { UserModel } from '../models/account/user'
9import { ApplicationModel } from '../models/application/application'
10import { AvatarModel } from '../models/avatar/avatar'
11import { JobModel } from '../models/job/job'
12import { OAuthClientModel } from '../models/oauth/oauth-client'
13import { OAuthTokenModel } from '../models/oauth/oauth-token'
14import { ServerModel } from '../models/server/server'
15import { TagModel } from '../models/video/tag'
16import { VideoModel } from '../models/video/video'
17import { VideoAbuseModel } from '../models/video/video-abuse'
18import { VideoBlacklistModel } from '../models/video/video-blacklist'
19import { VideoChannelModel } from '../models/video/video-channel'
20import { VideoChannelShareModel } from '../models/video/video-channel-share'
21import { VideoFileModel } from '../models/video/video-file'
22import { VideoShareModel } from '../models/video/video-share'
23import { VideoTagModel } from '../models/video/video-tag'
7import { CONFIG } from './constants' 24import { CONFIG } from './constants'
8// Do not use barrel, we need to load database first
9import { logger } from '../helpers/logger'
10import { isTestInstance, readdirPromise } from '../helpers/core-utils'
11 25
12import { VideoModel } from './../models/video/video-interface' 26require('pg').defaults.parseInt8 = true // Avoid BIGINT to be converted to string
13import { VideoTagModel } from './../models/video/video-tag-interface'
14import { BlacklistedVideoModel } from './../models/video/video-blacklist-interface'
15import { VideoFileModel } from './../models/video/video-file-interface'
16import { VideoAbuseModel } from './../models/video/video-abuse-interface'
17import { VideoChannelModel } from './../models/video/video-channel-interface'
18import { UserModel } from '../models/account/user-interface'
19import { AccountVideoRateModel } from '../models/account/account-video-rate-interface'
20import { AccountFollowModel } from '../models/account/account-follow-interface'
21import { TagModel } from './../models/video/tag-interface'
22import { ServerModel } from '../models/server/server-interface'
23import { OAuthTokenModel } from './../models/oauth/oauth-token-interface'
24import { OAuthClientModel } from './../models/oauth/oauth-client-interface'
25import { JobModel } from './../models/job/job-interface'
26import { AccountModel } from './../models/account/account-interface'
27import { ApplicationModel } from './../models/application/application-interface'
28import { VideoChannelShareModel } from '../models/video/video-channel-share-interface'
29import { VideoShareModel } from '../models/video/video-share-interface'
30 27
31const dbname = CONFIG.DATABASE.DBNAME 28const dbname = CONFIG.DATABASE.DBNAME
32const username = CONFIG.DATABASE.USERNAME 29const username = CONFIG.DATABASE.USERNAME
33const password = CONFIG.DATABASE.PASSWORD 30const password = CONFIG.DATABASE.PASSWORD
34 31
35export type PeerTubeDatabase = { 32const sequelizeTypescript = new SequelizeTypescript({
36 sequelize?: Sequelize.Sequelize, 33 database: dbname,
37 init?: (silent: boolean) => Promise<void>,
38
39 Application?: ApplicationModel,
40 Avatar?: AvatarModel,
41 Account?: AccountModel,
42 Job?: JobModel,
43 OAuthClient?: OAuthClientModel,
44 OAuthToken?: OAuthTokenModel,
45 Server?: ServerModel,
46 Tag?: TagModel,
47 AccountVideoRate?: AccountVideoRateModel,
48 AccountFollow?: AccountFollowModel,
49 User?: UserModel,
50 VideoAbuse?: VideoAbuseModel,
51 VideoChannel?: VideoChannelModel,
52 VideoChannelShare?: VideoChannelShareModel,
53 VideoShare?: VideoShareModel,
54 VideoFile?: VideoFileModel,
55 BlacklistedVideo?: BlacklistedVideoModel,
56 VideoTag?: VideoTagModel,
57 Video?: VideoModel
58}
59
60const database: PeerTubeDatabase = {}
61
62const sequelize = new Sequelize(dbname, username, password, {
63 dialect: 'postgres', 34 dialect: 'postgres',
64 host: CONFIG.DATABASE.HOSTNAME, 35 username,
65 port: CONFIG.DATABASE.PORT, 36 password,
37 modelPaths: [__dirname + '/models'],
66 benchmark: isTestInstance(), 38 benchmark: isTestInstance(),
67 isolationLevel: Sequelize.Transaction.ISOLATION_LEVELS.SERIALIZABLE, 39 isolationLevel: SequelizeTypescript.Transaction.ISOLATION_LEVELS.SERIALIZABLE,
68 operatorsAliases: false, 40 operatorsAliases: false,
69
70 logging: (message: string, benchmark: number) => { 41 logging: (message: string, benchmark: number) => {
71 if (process.env.NODE_DB_LOG === 'false') return 42 if (process.env.NODE_DB_LOG === 'false') return
72 43
@@ -79,34 +50,28 @@ const sequelize = new Sequelize(dbname, username, password, {
79 } 50 }
80}) 51})
81 52
82database.sequelize = sequelize 53async function initDatabase (silent: boolean) {
83 54 sequelizeTypescript.addModels([
84database.init = async (silent: boolean) => { 55 ApplicationModel,
85 const modelDirectory = join(__dirname, '..', 'models') 56 AvatarModel,
86 57 AccountModel,
87 const filePaths = await getModelFiles(modelDirectory) 58 JobModel,
88 59 OAuthClientModel,
89 for (const filePath of filePaths) { 60 OAuthTokenModel,
90 try { 61 ServerModel,
91 const model = sequelize.import(filePath) 62 TagModel,
92 63 AccountVideoRateModel,
93 database[model['name']] = model 64 AccountFollowModel,
94 } catch (err) { 65 UserModel,
95 logger.error('Cannot import database model %s.', filePath, err) 66 VideoAbuseModel,
96 process.exit(0) 67 VideoChannelModel,
97 } 68 VideoChannelShareModel,
98 } 69 VideoShareModel,
99 70 VideoFileModel,
100 for (const modelName of Object.keys(database)) { 71 VideoBlacklistModel,
101 if ('associate' in database[modelName]) { 72 VideoTagModel,
102 try { 73 VideoModel
103 database[modelName].associate(database) 74 ])
104 } catch (err) {
105 logger.error('Cannot associate model %s.', modelName, err)
106 process.exit(0)
107 }
108 }
109 }
110 75
111 if (!silent) logger.info('Database %s is ready.', dbname) 76 if (!silent) logger.info('Database %s is ready.', dbname)
112 77
@@ -116,51 +81,6 @@ database.init = async (silent: boolean) => {
116// --------------------------------------------------------------------------- 81// ---------------------------------------------------------------------------
117 82
118export { 83export {
119 database 84 initDatabase,
120} 85 sequelizeTypescript
121
122// ---------------------------------------------------------------------------
123
124async function getModelFiles (modelDirectory: string) {
125 const files = await readdirPromise(modelDirectory)
126 const directories = files.filter(directory => {
127 // Find directories
128 if (
129 directory.endsWith('.js.map') ||
130 directory === 'index.js' || directory === 'index.ts' ||
131 directory === 'utils.js' || directory === 'utils.ts'
132 ) return false
133
134 return true
135 })
136
137 const tasks: Promise<any>[] = []
138
139 // For each directory we read it and append model in the modelFilePaths array
140 for (const directory of directories) {
141 const modelDirectoryPath = join(modelDirectory, directory)
142
143 const promise = readdirPromise(modelDirectoryPath)
144 .then(files => {
145 const filteredFiles = files
146 .filter(file => {
147 if (
148 file === 'index.js' || file === 'index.ts' ||
149 file === 'utils.js' || file === 'utils.ts' ||
150 file.endsWith('-interface.js') || file.endsWith('-interface.ts') ||
151 file.endsWith('.js.map')
152 ) return false
153
154 return true
155 })
156 .map(file => join(modelDirectoryPath, file))
157
158 return filteredFiles
159 })
160
161 tasks.push(promise)
162 }
163
164 const filteredFilesArray: string[][] = await Promise.all(tasks)
165 return flattenDepth<string>(filteredFilesArray, 1)
166} 86}