import { inject , injectable } from 'inversify' ; import * as apid from '../../../../api' ; import * as mapid from '../../../../node_modules/mirakurun/api' ; import Reserve from '../../../db/entities/Reserve' ; import IRecordedDB from '../../db/IRecordedDB' ; import IReserveDB from '../../db/IReserveDB' ; import IRecordingEvent from '../../event/IRecordingEvent' ; import { IReserveUpdateValues } from '../../event/IReserveEvent' ; import IConfigFile from '../../IConfigFile' ; import IConfiguration from '../../IConfiguration' ; import ILogger from '../../ILogger' ; import ILoggerModel from '../../ILoggerModel' ; import IRecorderModel , { RecorderModelProvider } from './IRecorderModel' ; import IRecordingManageModel from './IRecordingManageModel' ; import IRecordingStreamCreator from './IRecordingStreamCreator' ; import IRecordingUtilModel from './IRecordingUtilModel' ; interface RecordingIndex { [ key ] : IRecorderModel ; } @ injectable ( ) class RecordingManageModel implements IRecordingManageModel { private log : ILogger ; private config : IConfigFile ; private provider : RecorderModelProvider ; private streamCreator : IRecordingStreamCreator ; private recordedDB : IRecordedDB ; private reserveDB : IReserveDB ; private recordingUtil : IRecordingUtilModel ; private recordingEvent : IRecordingEvent ; private recordingIndex : RecordingIndex = { } ; constructor ( @ inject ( 'ILoggerModel' ) logger , @ inject ( 'IConfiguration' ) configuration , @ inject ( 'RecorderModelProvider' ) provider , @ inject ( 'IRecordingEvent' ) recordingEvent , @ inject ( 'IRecordingStreamCreator' ) streamCreator , @ inject ( 'IRecordedDB' ) recordedDB , @ inject ( 'IReserveDB' ) reserveDB , @ inject ( 'IRecordingUtilModel' ) recordingUtil ) { this . log = logger . getLogger ( ) ; this . config = configuration . getConfig ( ) ; this . provider = provider ; this . recordingEvent = recordingEvent ; this . streamCreator = streamCreator ; this . recordedDB = recordedDB ; this . reserveDB = reserveDB ; this . recordingUtil = recordingUtil ; this . setEvents ( ) ; } /**
     * 録画関連イベントに登録
     */ private setEvents ( ) { this . recordingEvent . setCancelPrepRecording ( reserve => { this . deleteRecording ( reserve ) ; } ) ; this . recordingEvent . setPrepRecordingFailed ( reserve => { this . deleteRecording ( reserve ) ; } ) ; this . recordingEvent . setRecordingFailed ( async ( reserve ) => { this . deleteRecording ( reserve ) ; const recordeds = await this . recordedDB . findReserveId ( reserve . id ) ; if ( recordeds . length < 3 ) { const recorder = await this . provider ( ) ; if ( recorder . setTimer ( reserve , false ) === true ) { this . log . system . info ( `readd recording: ${ reserve . id }` ) ; this . recordingIndex [ reserve . id ] = recorder ; } else { this . log . system . error ( `readd recording error: ${ reserve . id }` ) ; } } else { this . log . system . error ( `recording retry over: ${ reserve . id }` ) ; this . recordingEvent . emitRecordingRetryOver ( reserve ) ; } } ) ; this . recordingEvent . setFinishRecording ( reserve => { this . deleteRecording ( reserve ) ; } ) ; } param reserve private deleteRecording ( reserve ) { this . log . system . debug ( `delete recording index: ${ reserve . id }` ) ; delete this . recordingIndex [ reserve . id ] ; } param tuners public setTuner ( tuners ) { this . streamCreator . setTuner ( tuners ) ; } return public async cleanup ( ) { this . log . system . info ( 'start recordings cleanup ' ) ; const [ records ] = await this . recordedDB . findAll ( { isHalfWidth : false , isRecording : true , } , { isNeedVideoFiles : true , isNeedThumbnails : false , isNeedsDropLog : false , isNeedTags : false , } ) ; for ( const r of records ) { try { await this . recordedDB . removeRecording ( r . id ) ; } catch ( err ) { this . log . system . error ( `failed to remove recording: ${ r . id }` ) ; this . log . system . error ( err ) ; continue ; } if ( r . reserveId === null ) { this . log . system . warn ( `reserveId is null: ${ r . reserveId }` ) ; continue ; } const reserve = await this . reserveDB . findId ( r . reserveId ) . catch ( err => { this . log . system . error ( `get reserve error: ${ r . reserveId }` ) ; this . log . system . error ( err ) ; } ) ; if ( typeof reserve === 'undefined' || reserve === null ) { this . log . system . warn ( `reserveId is not found: ${ r . reserveId }` ) ; continue ; } if ( typeof r . videoFiles !== 'undefined' ) { for ( const videoFile of r . videoFiles ) { if ( videoFile . parentDirectoryName === 'tmp' && typeof this . config . recordedTmp !== 'undefined' ) { await this . recordingUtil . movingFromTmp ( reserve , videoFile . id ) . catch ( err => { this . log . system . fatal ( `movingFromTmp error: ${ videoFile . id }` ) ; this . log . system . fatal ( err ) ; } ) ; } await this . recordingUtil . updateVideoFileSize ( videoFile . id ) . catch ( err => { this . log . system . error ( `update file size error: ${ videoFile . id }` ) ; this . log . system . error ( err ) ; } ) ; } } const newRecorded = await this . recordedDB . findId ( r . id ) ; if ( newRecorded !== null ) { this . recordingEvent . emitFinishRecording ( reserve , newRecorded , true ) ; } } this . log . system . info ( 'finish recordings cleanup ' ) ; } param diff public async update ( diff ) { if ( typeof diff . insert !== 'undefined' ) { for ( const reserve of diff . insert ) { if ( reserve . isSkip === true || reserve . isOverlap === true ) { continue ; } const recorder = await this . provider ( ) ; if ( recorder . setTimer ( reserve , diff . isSuppressLog ) === true ) { this . log . system . debug ( `add recording: ${ reserve . id }` ) ; this . recordingIndex [ reserve . id ] = recorder ; } else { this . log . system . error ( `add recording error: ${ reserve . id }` ) ; } } } if ( typeof diff . update !== 'undefined' ) { for ( const reserve of diff . update ) { const recorder = this . recordingIndex [ reserve . id ] ; if ( typeof recorder === 'undefined' ) { this . log . system . debug ( `create new recorder: ${ reserve . id }` ) ; const newRecorder = await this . provider ( ) ; if ( newRecorder . setTimer ( reserve , diff . isSuppressLog ) === true ) { this . recordingIndex [ reserve . id ] = newRecorder ; } } else { this . log . system . debug ( `update recording: ${ reserve . id }` ) ; await recorder . update ( reserve , diff . isSuppressLog ) . catch ( err => { this . log . system . error ( `update recording error: ${ reserve . id }` ) ; this . log . system . error ( err ) ; } ) ; } } } if ( typeof diff . delete !== 'undefined' ) { for ( const reserve of diff . delete ) { const recorder = this . recordingIndex [ reserve . id ] ; if ( typeof recorder !== 'undefined' ) { this . log . system . debug ( `delete recording: ${ reserve . id }` ) ; await recorder . cancel ( false ) . catch ( err => { this . log . system . error ( `delete recording error: ${ reserve . id }` ) ; this . log . system . error ( err ) ; } ) ; } } } } param reserveId return public hasReserve ( reserveId ) { return typeof this . recordingIndex [ reserveId ] !== 'undefined' ; } param reserveId param isPlanToDelete return public async cancel ( reserveId , isPlanToDelete ) { if ( typeof this . recordingIndex [ reserveId ] === 'undefined' ) { return ; } this . log . system . info ( `cancel recording reserveId: ${ reserveId }, isPlanToDelete: ${ isPlanToDelete }` ) ; return this . recordingIndex [ reserveId ] . cancel ( isPlanToDelete ) ; } /**
     * タイマーを再設定する
     */ public resetTimer ( ) { this . log . system . info ( 'reset timer' ) ; for ( const key in this . recordingIndex ) { this . recordingIndex [ key ] . resetTimer ( ) ; } } } export default RecordingManageModel ;