diff options
-rw-r--r-- | server/initializers/constants.ts | 2 | ||||
-rw-r--r-- | server/initializers/migrations/0380-cleanup-timestamps.ts | 29 | ||||
-rw-r--r-- | server/lib/job-queue/handlers/video-views.ts | 11 | ||||
-rw-r--r-- | server/models/video/video-blacklist.ts | 66 |
4 files changed, 79 insertions, 29 deletions
diff --git a/server/initializers/constants.ts b/server/initializers/constants.ts index 8a11101ff..ec040b80e 100644 --- a/server/initializers/constants.ts +++ b/server/initializers/constants.ts | |||
@@ -14,7 +14,7 @@ import { CONFIG, registerConfigChangedHandler } from './config' | |||
14 | 14 | ||
15 | // --------------------------------------------------------------------------- | 15 | // --------------------------------------------------------------------------- |
16 | 16 | ||
17 | const LAST_MIGRATION_VERSION = 375 | 17 | const LAST_MIGRATION_VERSION = 380 |
18 | 18 | ||
19 | // --------------------------------------------------------------------------- | 19 | // --------------------------------------------------------------------------- |
20 | 20 | ||
diff --git a/server/initializers/migrations/0380-cleanup-timestamps.ts b/server/initializers/migrations/0380-cleanup-timestamps.ts new file mode 100644 index 000000000..2a9fd6f02 --- /dev/null +++ b/server/initializers/migrations/0380-cleanup-timestamps.ts | |||
@@ -0,0 +1,29 @@ | |||
1 | import * as Sequelize from 'sequelize' | ||
2 | |||
3 | async function up (utils: { | ||
4 | transaction: Sequelize.Transaction, | ||
5 | queryInterface: Sequelize.QueryInterface, | ||
6 | sequelize: Sequelize.Sequelize, | ||
7 | db: any | ||
8 | }): Promise<void> { | ||
9 | try { | ||
10 | await utils.queryInterface.removeColumn('application', 'createdAt') | ||
11 | } catch { /* the column could not exist */ } | ||
12 | |||
13 | try { | ||
14 | await utils.queryInterface.removeColumn('application', 'updatedAt') | ||
15 | } catch { /* the column could not exist */ } | ||
16 | |||
17 | try { | ||
18 | await utils.queryInterface.removeColumn('videoView', 'updatedAt') | ||
19 | } catch { /* the column could not exist */ } | ||
20 | } | ||
21 | |||
22 | function down (options) { | ||
23 | throw new Error('Not implemented.') | ||
24 | } | ||
25 | |||
26 | export { | ||
27 | up, | ||
28 | down | ||
29 | } | ||
diff --git a/server/lib/job-queue/handlers/video-views.ts b/server/lib/job-queue/handlers/video-views.ts index fa1fd13b3..73fa5ed04 100644 --- a/server/lib/job-queue/handlers/video-views.ts +++ b/server/lib/job-queue/handlers/video-views.ts | |||
@@ -27,6 +27,12 @@ async function processVideosViews () { | |||
27 | logger.debug('Adding %d views to video %d in hour %d.', views, videoId, hour) | 27 | logger.debug('Adding %d views to video %d in hour %d.', views, videoId, hour) |
28 | 28 | ||
29 | try { | 29 | try { |
30 | const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoId) | ||
31 | if (!video) { | ||
32 | logger.debug('Video %d does not exist anymore, skipping videos view addition.', videoId) | ||
33 | continue | ||
34 | } | ||
35 | |||
30 | await VideoViewModel.create({ | 36 | await VideoViewModel.create({ |
31 | startDate, | 37 | startDate, |
32 | endDate, | 38 | endDate, |
@@ -34,7 +40,6 @@ async function processVideosViews () { | |||
34 | videoId | 40 | videoId |
35 | }) | 41 | }) |
36 | 42 | ||
37 | const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoId) | ||
38 | if (video.isOwned()) { | 43 | if (video.isOwned()) { |
39 | // If this is a remote video, the origin instance will send us an update | 44 | // If this is a remote video, the origin instance will send us an update |
40 | await VideoModel.incrementViews(videoId, views) | 45 | await VideoModel.incrementViews(videoId, views) |
@@ -44,13 +49,13 @@ async function processVideosViews () { | |||
44 | await federateVideoIfNeeded(video, false) | 49 | await federateVideoIfNeeded(video, false) |
45 | } | 50 | } |
46 | } catch (err) { | 51 | } catch (err) { |
47 | logger.debug('Cannot create video views for video %d in hour %d. Maybe the video does not exist anymore?', videoId, hour) | 52 | logger.error('Cannot create video views for video %d in hour %d.', videoId, hour, { err }) |
48 | } | 53 | } |
49 | } | 54 | } |
50 | 55 | ||
51 | await Redis.Instance.deleteVideoViews(videoId, hour) | 56 | await Redis.Instance.deleteVideoViews(videoId, hour) |
52 | } catch (err) { | 57 | } catch (err) { |
53 | logger.error('Cannot update video views of video %d in hour %d.', videoId, hour) | 58 | logger.error('Cannot update video views of video %d in hour %d.', videoId, hour, { err }) |
54 | } | 59 | } |
55 | } | 60 | } |
56 | } | 61 | } |
diff --git a/server/models/video/video-blacklist.ts b/server/models/video/video-blacklist.ts index 3bd74460d..baef1d6ce 100644 --- a/server/models/video/video-blacklist.ts +++ b/server/models/video/video-blacklist.ts | |||
@@ -1,11 +1,12 @@ | |||
1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' | 1 | import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' |
2 | import { getSortOnModel, SortType, throwIfNotValid } from '../utils' | 2 | import { getSortOnModel, SortType, throwIfNotValid } from '../utils' |
3 | import { VideoModel, ScopeNames as VideoModelScopeNames } from './video' | 3 | import { ScopeNames as VideoModelScopeNames, VideoModel } from './video' |
4 | import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' | 4 | import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' |
5 | import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' | 5 | import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' |
6 | import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' | 6 | import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' |
7 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' | 7 | import { CONSTRAINTS_FIELDS } from '../../initializers/constants' |
8 | import { FindOptions } from 'sequelize' | 8 | import { FindOptions } from 'sequelize' |
9 | import { ThumbnailModel } from './thumbnail' | ||
9 | 10 | ||
10 | @Table({ | 11 | @Table({ |
11 | tableName: 'videoBlacklist', | 12 | tableName: 'videoBlacklist', |
@@ -52,35 +53,50 @@ export class VideoBlacklistModel extends Model<VideoBlacklistModel> { | |||
52 | Video: VideoModel | 53 | Video: VideoModel |
53 | 54 | ||
54 | static listForApi (start: number, count: number, sort: SortType, type?: VideoBlacklistType) { | 55 | static listForApi (start: number, count: number, sort: SortType, type?: VideoBlacklistType) { |
55 | const query: FindOptions = { | 56 | function buildBaseQuery (): FindOptions { |
56 | offset: start, | 57 | return { |
57 | limit: count, | 58 | offset: start, |
58 | order: getSortOnModel(sort.sortModel, sort.sortValue), | 59 | limit: count, |
59 | include: [ | 60 | order: getSortOnModel(sort.sortModel, sort.sortValue) |
60 | { | 61 | } |
61 | model: VideoModel.scope(VideoModelScopeNames.WITH_THUMBNAILS), | ||
62 | required: true, | ||
63 | include: [ | ||
64 | { | ||
65 | model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, true ] }), | ||
66 | required: true | ||
67 | } | ||
68 | ] | ||
69 | } | ||
70 | ] | ||
71 | } | 62 | } |
72 | 63 | ||
64 | const countQuery = buildBaseQuery() | ||
65 | |||
66 | const findQuery = buildBaseQuery() | ||
67 | findQuery.subQuery = false | ||
68 | findQuery.include = [ | ||
69 | { | ||
70 | model: VideoModel, | ||
71 | required: true, | ||
72 | include: [ | ||
73 | { | ||
74 | model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, true ] }), | ||
75 | required: true | ||
76 | }, | ||
77 | { | ||
78 | model: ThumbnailModel, | ||
79 | attributes: [ 'type', 'filename' ], | ||
80 | required: false | ||
81 | } | ||
82 | ] | ||
83 | } | ||
84 | ] | ||
85 | |||
73 | if (type) { | 86 | if (type) { |
74 | query.where = { type } | 87 | countQuery.where = { type } |
88 | findQuery.where = { type } | ||
75 | } | 89 | } |
76 | 90 | ||
77 | return VideoBlacklistModel.findAndCountAll(query) | 91 | return Promise.all([ |
78 | .then(({ rows, count }) => { | 92 | VideoBlacklistModel.count(countQuery), |
79 | return { | 93 | VideoBlacklistModel.findAll(findQuery) |
80 | data: rows, | 94 | ]).then(([ count, rows ]) => { |
81 | total: count | 95 | return { |
82 | } | 96 | data: rows, |
83 | }) | 97 | total: count |
98 | } | ||
99 | }) | ||
84 | } | 100 | } |
85 | 101 | ||
86 | static loadByVideoId (id: number) { | 102 | static loadByVideoId (id: number) { |