Don't stuck state when move transcoding job failed
This commit is contained in:
parent
482b26231b
commit
dbd9fb44dd
|
@ -2,6 +2,10 @@
|
||||||
Transcoding failed, this video may not work properly.
|
Transcoding failed, this video may not work properly.
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div i18n class="alert alert-warning" *ngIf="isVideoMoveToObjectStorageFailed()">
|
||||||
|
Move to external storage failed, this video may not work properly.
|
||||||
|
</div>
|
||||||
|
|
||||||
<div i18n class="alert alert-warning" *ngIf="isVideoToImport()">
|
<div i18n class="alert alert-warning" *ngIf="isVideoToImport()">
|
||||||
The video is being imported, it will be available when the import is finished.
|
The video is being imported, it will be available when the import is finished.
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,6 +18,10 @@ export class VideoAlertComponent {
|
||||||
return this.video && this.video.state.id === VideoState.TRANSCODING_FAILED
|
return this.video && this.video.state.id === VideoState.TRANSCODING_FAILED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isVideoMoveToObjectStorageFailed () {
|
||||||
|
return this.video && this.video.state.id === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE_FAILED
|
||||||
|
}
|
||||||
|
|
||||||
isVideoToImport () {
|
isVideoToImport () {
|
||||||
return this.video && this.video.state.id === VideoState.TO_IMPORT
|
return this.video && this.video.state.id === VideoState.TO_IMPORT
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,10 @@ export class VideoMiniatureComponent implements OnInit {
|
||||||
return $localize`Transcoding failed`
|
return $localize`Transcoding failed`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (video.state.id === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE_FAILED) {
|
||||||
|
return $localize`Move to external storage failed`
|
||||||
|
}
|
||||||
|
|
||||||
if (video.state.id === VideoState.TO_TRANSCODE && video.waitTranscoding === true) {
|
if (video.state.id === VideoState.TO_TRANSCODE && video.waitTranscoding === true) {
|
||||||
return $localize`Waiting transcoding`
|
return $localize`Waiting transcoding`
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ registerTSPaths()
|
||||||
import { program } from 'commander'
|
import { program } from 'commander'
|
||||||
import { VideoModel } from '@server/models/video/video'
|
import { VideoModel } from '@server/models/video/video'
|
||||||
import { initDatabaseModels } from '@server/initializers/database'
|
import { initDatabaseModels } from '@server/initializers/database'
|
||||||
import { VideoStorage } from '@shared/models'
|
import { VideoState, VideoStorage } from '@shared/models'
|
||||||
import { moveToExternalStorageState } from '@server/lib/video-state'
|
import { moveToExternalStorageState } from '@server/lib/video-state'
|
||||||
import { JobQueue } from '@server/lib/job-queue'
|
import { JobQueue } from '@server/lib/job-queue'
|
||||||
import { CONFIG } from '@server/initializers/config'
|
import { CONFIG } from '@server/initializers/config'
|
||||||
|
@ -62,6 +62,11 @@ async function run () {
|
||||||
process.exit(-1)
|
process.exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (video.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE) {
|
||||||
|
console.error('This video is already being moved to external storage')
|
||||||
|
process.exit(-1)
|
||||||
|
}
|
||||||
|
|
||||||
ids.push(video.id)
|
ids.push(video.id)
|
||||||
} else {
|
} else {
|
||||||
ids = await VideoModel.listLocalIds()
|
ids = await VideoModel.listLocalIds()
|
||||||
|
|
|
@ -427,7 +427,8 @@ const VIDEO_STATES: { [ id in VideoState ]: string } = {
|
||||||
[VideoState.WAITING_FOR_LIVE]: 'Waiting for livestream',
|
[VideoState.WAITING_FOR_LIVE]: 'Waiting for livestream',
|
||||||
[VideoState.LIVE_ENDED]: 'Livestream ended',
|
[VideoState.LIVE_ENDED]: 'Livestream ended',
|
||||||
[VideoState.TO_MOVE_TO_EXTERNAL_STORAGE]: 'To move to an external storage',
|
[VideoState.TO_MOVE_TO_EXTERNAL_STORAGE]: 'To move to an external storage',
|
||||||
[VideoState.TRANSCODING_FAILED]: 'Transcoding failed'
|
[VideoState.TRANSCODING_FAILED]: 'Transcoding failed',
|
||||||
|
[VideoState.TO_MOVE_TO_EXTERNAL_STORAGE_FAILED]: 'External storage move failed'
|
||||||
}
|
}
|
||||||
|
|
||||||
const VIDEO_IMPORT_STATES: { [ id in VideoImportState ]: string } = {
|
const VIDEO_IMPORT_STATES: { [ id in VideoImportState ]: string } = {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { CONFIG } from '@server/initializers/config'
|
||||||
import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants'
|
import { P2P_MEDIA_LOADER_PEER_VERSION } from '@server/initializers/constants'
|
||||||
import { storeHLSFile, storeWebTorrentFile } from '@server/lib/object-storage'
|
import { storeHLSFile, storeWebTorrentFile } from '@server/lib/object-storage'
|
||||||
import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths'
|
import { getHLSDirectory, getHlsResolutionPlaylistFilename } from '@server/lib/paths'
|
||||||
import { moveToNextState } from '@server/lib/video-state'
|
import { moveToFailedMoveToObjectStorageState, moveToNextState } from '@server/lib/video-state'
|
||||||
import { VideoModel } from '@server/models/video/video'
|
import { VideoModel } from '@server/models/video/video'
|
||||||
import { VideoJobInfoModel } from '@server/models/video/video-job-info'
|
import { VideoJobInfoModel } from '@server/models/video/video-job-info'
|
||||||
import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoWithAllFiles } from '@server/types/models'
|
import { MStreamingPlaylistVideo, MVideo, MVideoFile, MVideoWithAllFiles } from '@server/types/models'
|
||||||
|
@ -24,18 +24,25 @@ export async function processMoveToObjectStorage (job: Job) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video.VideoFiles) {
|
try {
|
||||||
await moveWebTorrentFiles(video)
|
if (video.VideoFiles) {
|
||||||
}
|
await moveWebTorrentFiles(video)
|
||||||
|
}
|
||||||
|
|
||||||
if (video.VideoStreamingPlaylists) {
|
if (video.VideoStreamingPlaylists) {
|
||||||
await moveHLSFiles(video)
|
await moveHLSFiles(video)
|
||||||
}
|
}
|
||||||
|
|
||||||
const pendingMove = await VideoJobInfoModel.decrease(video.uuid, 'pendingMove')
|
const pendingMove = await VideoJobInfoModel.decrease(video.uuid, 'pendingMove')
|
||||||
if (pendingMove === 0) {
|
if (pendingMove === 0) {
|
||||||
logger.info('Running cleanup after moving files to object storage (video %s in job %d)', video.uuid, job.id)
|
logger.info('Running cleanup after moving files to object storage (video %s in job %d)', video.uuid, job.id)
|
||||||
await doAfterLastJob(video, payload.isNewVideo)
|
await doAfterLastJob(video, payload.isNewVideo)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
logger.error('Cannot move video %s to object storage.', video.url, { err })
|
||||||
|
|
||||||
|
await moveToFailedMoveToObjectStorageState(video)
|
||||||
|
await VideoJobInfoModel.abortAllTasks(video.uuid, 'pendingMove')
|
||||||
}
|
}
|
||||||
|
|
||||||
return payload.videoUUID
|
return payload.videoUUID
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { CONFIG } from '@server/initializers/config'
|
||||||
import { sequelizeTypescript } from '@server/initializers/database'
|
import { sequelizeTypescript } from '@server/initializers/database'
|
||||||
import { VideoModel } from '@server/models/video/video'
|
import { VideoModel } from '@server/models/video/video'
|
||||||
import { VideoJobInfoModel } from '@server/models/video/video-job-info'
|
import { VideoJobInfoModel } from '@server/models/video/video-job-info'
|
||||||
import { MVideoFullLight, MVideoUUID } from '@server/types/models'
|
import { MVideo, MVideoFullLight, MVideoUUID } from '@server/types/models'
|
||||||
import { VideoState } from '@shared/models'
|
import { VideoState } from '@shared/models'
|
||||||
import { federateVideoIfNeeded } from './activitypub/videos'
|
import { federateVideoIfNeeded } from './activitypub/videos'
|
||||||
import { Notifier } from './notifier'
|
import { Notifier } from './notifier'
|
||||||
|
@ -79,18 +79,25 @@ async function moveToExternalStorageState (video: MVideoFullLight, isNewVideo: b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveToFailedTranscodingState (video: MVideoFullLight) {
|
function moveToFailedTranscodingState (video: MVideo) {
|
||||||
if (video.state === VideoState.TRANSCODING_FAILED) return
|
if (video.state === VideoState.TRANSCODING_FAILED) return
|
||||||
|
|
||||||
return video.setNewState(VideoState.TRANSCODING_FAILED, false, undefined)
|
return video.setNewState(VideoState.TRANSCODING_FAILED, false, undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function moveToFailedMoveToObjectStorageState (video: MVideo) {
|
||||||
|
if (video.state === VideoState.TO_MOVE_TO_EXTERNAL_STORAGE_FAILED) return
|
||||||
|
|
||||||
|
return video.setNewState(VideoState.TO_MOVE_TO_EXTERNAL_STORAGE_FAILED, false, undefined)
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export {
|
export {
|
||||||
buildNextVideoState,
|
buildNextVideoState,
|
||||||
moveToExternalStorageState,
|
moveToExternalStorageState,
|
||||||
moveToFailedTranscodingState,
|
moveToFailedTranscodingState,
|
||||||
|
moveToFailedMoveToObjectStorageState,
|
||||||
moveToNextState
|
moveToNextState
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -99,4 +99,19 @@ export class VideoJobInfoModel extends Model<Partial<AttributesOnly<VideoJobInfo
|
||||||
|
|
||||||
return pendingMove
|
return pendingMove
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async abortAllTasks (videoUUID: string, column: VideoJobInfoColumnType): Promise<void> {
|
||||||
|
const options = { type: QueryTypes.UPDATE as QueryTypes.UPDATE, bind: { videoUUID } }
|
||||||
|
|
||||||
|
await VideoJobInfoModel.sequelize.query(`
|
||||||
|
UPDATE
|
||||||
|
"videoJobInfo"
|
||||||
|
SET
|
||||||
|
"${column}" = 0,
|
||||||
|
"updatedAt" = NOW()
|
||||||
|
FROM "video"
|
||||||
|
WHERE
|
||||||
|
"video"."id" = "videoJobInfo"."videoId" AND "video"."uuid" = $videoUUID
|
||||||
|
`, options)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,5 +5,6 @@ export const enum VideoState {
|
||||||
WAITING_FOR_LIVE = 4,
|
WAITING_FOR_LIVE = 4,
|
||||||
LIVE_ENDED = 5,
|
LIVE_ENDED = 5,
|
||||||
TO_MOVE_TO_EXTERNAL_STORAGE = 6,
|
TO_MOVE_TO_EXTERNAL_STORAGE = 6,
|
||||||
TRANSCODING_FAILED = 7
|
TRANSCODING_FAILED = 7,
|
||||||
|
TO_MOVE_TO_EXTERNAL_STORAGE_FAILED = 8
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue