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' // --------------------------------------------------------------------------- -const LAST_MIGRATION_VERSION = 375 +const LAST_MIGRATION_VERSION = 380 // --------------------------------------------------------------------------- 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 @@ +import * as Sequelize from 'sequelize' + +async function up (utils: { + transaction: Sequelize.Transaction, + queryInterface: Sequelize.QueryInterface, + sequelize: Sequelize.Sequelize, + db: any +}): Promise { + try { + await utils.queryInterface.removeColumn('application', 'createdAt') + } catch { /* the column could not exist */ } + + try { + await utils.queryInterface.removeColumn('application', 'updatedAt') + } catch { /* the column could not exist */ } + + try { + await utils.queryInterface.removeColumn('videoView', 'updatedAt') + } catch { /* the column could not exist */ } +} + +function down (options) { + throw new Error('Not implemented.') +} + +export { + up, + down +} 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 () { logger.debug('Adding %d views to video %d in hour %d.', views, videoId, hour) try { + const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoId) + if (!video) { + logger.debug('Video %d does not exist anymore, skipping videos view addition.', videoId) + continue + } + await VideoViewModel.create({ startDate, endDate, @@ -34,7 +40,6 @@ async function processVideosViews () { videoId }) - const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(videoId) if (video.isOwned()) { // If this is a remote video, the origin instance will send us an update await VideoModel.incrementViews(videoId, views) @@ -44,13 +49,13 @@ async function processVideosViews () { await federateVideoIfNeeded(video, false) } } catch (err) { - logger.debug('Cannot create video views for video %d in hour %d. Maybe the video does not exist anymore?', videoId, hour) + logger.error('Cannot create video views for video %d in hour %d.', videoId, hour, { err }) } } await Redis.Instance.deleteVideoViews(videoId, hour) } catch (err) { - logger.error('Cannot update video views of video %d in hour %d.', videoId, hour) + logger.error('Cannot update video views of video %d in hour %d.', videoId, hour, { err }) } } } 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 @@ import { AllowNull, BelongsTo, Column, CreatedAt, DataType, Default, ForeignKey, Is, Model, Table, UpdatedAt } from 'sequelize-typescript' import { getSortOnModel, SortType, throwIfNotValid } from '../utils' -import { VideoModel, ScopeNames as VideoModelScopeNames } from './video' +import { ScopeNames as VideoModelScopeNames, VideoModel } from './video' import { ScopeNames as VideoChannelScopeNames, VideoChannelModel } from './video-channel' import { isVideoBlacklistReasonValid, isVideoBlacklistTypeValid } from '../../helpers/custom-validators/video-blacklist' import { VideoBlacklist, VideoBlacklistType } from '../../../shared/models/videos' import { CONSTRAINTS_FIELDS } from '../../initializers/constants' import { FindOptions } from 'sequelize' +import { ThumbnailModel } from './thumbnail' @Table({ tableName: 'videoBlacklist', @@ -52,35 +53,50 @@ export class VideoBlacklistModel extends Model { Video: VideoModel static listForApi (start: number, count: number, sort: SortType, type?: VideoBlacklistType) { - const query: FindOptions = { - offset: start, - limit: count, - order: getSortOnModel(sort.sortModel, sort.sortValue), - include: [ - { - model: VideoModel.scope(VideoModelScopeNames.WITH_THUMBNAILS), - required: true, - include: [ - { - model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, true ] }), - required: true - } - ] - } - ] + function buildBaseQuery (): FindOptions { + return { + offset: start, + limit: count, + order: getSortOnModel(sort.sortModel, sort.sortValue) + } } + const countQuery = buildBaseQuery() + + const findQuery = buildBaseQuery() + findQuery.subQuery = false + findQuery.include = [ + { + model: VideoModel, + required: true, + include: [ + { + model: VideoChannelModel.scope({ method: [ VideoChannelScopeNames.SUMMARY, true ] }), + required: true + }, + { + model: ThumbnailModel, + attributes: [ 'type', 'filename' ], + required: false + } + ] + } + ] + if (type) { - query.where = { type } + countQuery.where = { type } + findQuery.where = { type } } - return VideoBlacklistModel.findAndCountAll(query) - .then(({ rows, count }) => { - return { - data: rows, - total: count - } - }) + return Promise.all([ + VideoBlacklistModel.count(countQuery), + VideoBlacklistModel.findAll(findQuery) + ]).then(([ count, rows ]) => { + return { + data: rows, + total: count + } + }) } static loadByVideoId (id: number) {