Merge branch 'nonblockingReindex' into 'master'
reindexing in background and gravity cleanup Closes #29 See merge request lukas/openmediacenter!20
This commit is contained in:
		| @@ -1,18 +0,0 @@ | ||||
| <?php | ||||
| $return = new stdClass(); | ||||
| if (file_exists("/tmp/output.log")) { | ||||
|     $out = file_get_contents("/tmp/output.log"); | ||||
|     // clear log file | ||||
|     file_put_contents("/tmp/output.log", ""); | ||||
|     $return->message = $out; | ||||
|     $return->contentAvailable = true; | ||||
|  | ||||
|     if (substr($out, -strlen("-42")) == "-42") { | ||||
|         unlink("/tmp/output.log"); | ||||
|     } | ||||
| } else { | ||||
|     $return->contentAvailable = false; | ||||
| } | ||||
|  | ||||
|  | ||||
| echo json_encode($return); | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| require_once './src/Database.php'; | ||||
| require_once './src/TMDBMovie.php'; | ||||
| require_once './src/SSettings.php'; | ||||
| require_once 'Database.php'; | ||||
| require_once 'TMDBMovie.php'; | ||||
| require_once 'SSettings.php'; | ||||
|  | ||||
| /** | ||||
|  * Class VideoParser | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <?php | ||||
| require_once 'src/Database.php'; | ||||
| require_once __DIR__.'/../Database.php'; | ||||
|  | ||||
| abstract class RequestBase { | ||||
|     protected $conn; | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| <?php | ||||
| require_once 'RequestBase.php'; | ||||
| require_once __DIR__ . '/../VideoParser.php'; | ||||
|  | ||||
| /** | ||||
|  * Class Settings | ||||
| @@ -9,6 +10,7 @@ class Settings extends RequestBase { | ||||
|     function initHandlers() { | ||||
|         $this->getFromDB(); | ||||
|         $this->saveToDB(); | ||||
|         $this->reIndexHandling(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -102,4 +104,57 @@ class Settings extends RequestBase { | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * methods for handling reindexing and cleanup of db gravity | ||||
|      */ | ||||
|     private function reIndexHandling() { | ||||
|         $this->addActionHandler("startReindex", function () { | ||||
|             $indexrunning = false; | ||||
|             if (file_exists("/tmp/output.log")) { | ||||
|  | ||||
|                 $out = file_get_contents("/tmp/output.log"); | ||||
|                 if (substr($out, -strlen("-42")) == "-42") { | ||||
|                     unlink("/tmp/output.log"); | ||||
|                 } else { | ||||
|                     $indexrunning = true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (!$indexrunning) { | ||||
|                 // start extraction of video previews in background | ||||
|  | ||||
|                 $cmd = 'php extractvideopreviews.php'; | ||||
|                 exec(sprintf("%s > %s 2>&1 & echo $! >> %s", $cmd, '/dev/zero', '/tmp/openmediacenterpid')); | ||||
|  | ||||
|                 $this->commitMessage('{"success": true}'); | ||||
|             } else { | ||||
|                 $this->commitMessage('{"success": false}'); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         $this->addActionHandler("cleanupGravity", function () { | ||||
|             $vp = new VideoParser(); | ||||
|             $vp->cleanUpGravity(); | ||||
|         }); | ||||
|  | ||||
|         $this->addActionHandler("getStatusMessage", function () { | ||||
|             $return = new stdClass(); | ||||
|             if (file_exists("/tmp/output.log")) { | ||||
|                 $out = file_get_contents("/tmp/output.log"); | ||||
|                 // clear log file | ||||
|                 file_put_contents("/tmp/output.log", ""); | ||||
|                 $return->message = $out; | ||||
|                 $return->contentAvailable = true; | ||||
|  | ||||
|                 if (substr($out, -strlen("-42")) == "-42") { | ||||
|                     unlink("/tmp/output.log"); | ||||
|                 } | ||||
|             } else { | ||||
|                 $return->contentAvailable = false; | ||||
|             } | ||||
|  | ||||
|             $this->commitMessage(json_encode($return)); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <?php | ||||
| require_once 'src/SSettings.php'; | ||||
| require_once __DIR__.'/../SSettings.php'; | ||||
| require_once 'RequestBase.php'; | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|   "scripts": { | ||||
|     "start": "react-scripts start", | ||||
|     "build": "react-scripts build", | ||||
|     "test": "react-scripts test --reporters=jest-junit --reporters=default", | ||||
|     "test": "react-scripts test --reporters=jest-junit --reporters=default --ci --silent", | ||||
|     "coverage": "react-scripts test --coverage --watchAll=false", | ||||
|     "eject": "react-scripts eject" | ||||
|   }, | ||||
|   | ||||
| @@ -16,9 +16,6 @@ class MovieSettings extends React.Component { | ||||
|     } | ||||
|  | ||||
|     componentDidMount() { | ||||
|         if (this.myinterval) { | ||||
|             clearInterval(this.myinterval); | ||||
|         } | ||||
|         this.myinterval = setInterval(this.updateStatus, 1000); | ||||
|     } | ||||
|  | ||||
| @@ -29,9 +26,12 @@ class MovieSettings extends React.Component { | ||||
|     render() { | ||||
|         return ( | ||||
|             <> | ||||
|                 <button disabled={this.state.startbtnDisabled} className='reindexbtn btn btn-success' onClick={() => { | ||||
|                     this.startReindex() | ||||
|                 }}>Reindex Movies | ||||
|                 <button disabled={this.state.startbtnDisabled} | ||||
|                         className='btn btn-success' | ||||
|                         onClick={() => {this.startReindex()}}>Reindex Movie | ||||
|                 </button> | ||||
|                 <button className='btn btn-warning' | ||||
|                         onClick={() => {this.cleanupGravity()}}>Cleanup Gravity | ||||
|                 </button> | ||||
|                 <div className={style.indextextarea}>{this.state.text.map(m => ( | ||||
|                     <div className='textarea-element'>{m}</div> | ||||
| @@ -50,13 +50,19 @@ class MovieSettings extends React.Component { | ||||
|         this.setState({startbtnDisabled: true}); | ||||
|  | ||||
|         console.log("starting"); | ||||
|         const updateRequest = new FormData(); | ||||
|         const request = new FormData(); | ||||
|         request.append("action", "startReindex"); | ||||
|         // fetch all videos available | ||||
|         fetch('/api/extractvideopreviews.php', {method: 'POST', body: updateRequest}) | ||||
|             .then((response) => response.text() | ||||
|         fetch('/api/settings.php', {method: 'POST', body: request}) | ||||
|             .then((response) => response.json() | ||||
|                 .then((result) => { | ||||
|                     // todo 2020-07-4: some kind of return finished handler | ||||
|                     console.log("returned"); | ||||
|                     console.log(result); | ||||
|                     if (result.success) { | ||||
|                         console.log("started successfully"); | ||||
|                     } else { | ||||
|                         console.log("error, reindex already running"); | ||||
|                         this.setState({startbtnDisabled: true}); | ||||
|                     } | ||||
|                 })) | ||||
|             .catch(() => { | ||||
|                 console.log("no connection to backend"); | ||||
| @@ -71,8 +77,10 @@ class MovieSettings extends React.Component { | ||||
|      * This interval function reloads the current status of reindexing from backend | ||||
|      */ | ||||
|     updateStatus = () => { | ||||
|         const updateRequest = new FormData(); | ||||
|         fetch('/api/extractionData.php', {method: 'POST', body: updateRequest}) | ||||
|         const request = new FormData(); | ||||
|         request.append("action", "getStatusMessage"); | ||||
|  | ||||
|         fetch('/api/settings.php', {method: 'POST', body: request}) | ||||
|             .then((response) => response.json() | ||||
|                 .then((result) => { | ||||
|                     if (result.contentAvailable === true) { | ||||
| @@ -94,6 +102,25 @@ class MovieSettings extends React.Component { | ||||
|                 console.log("no connection to backend"); | ||||
|             }); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * send request to cleanup db gravity | ||||
|      */ | ||||
|     cleanupGravity() { | ||||
|         const request = new FormData(); | ||||
|         request.append("action", "cleanupGravity"); | ||||
|  | ||||
|         fetch('/api/settings.php', {method: 'POST', body: request}) | ||||
|             .then((response) => response.text() | ||||
|                 .then((result) => { | ||||
|                     this.setState({ | ||||
|                         text: ['successfully cleaned up gravity!'] | ||||
|                     }); | ||||
|                 })) | ||||
|             .catch(() => { | ||||
|                 console.log("no connection to backend"); | ||||
|             }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default MovieSettings; | ||||
|   | ||||
| @@ -9,5 +9,5 @@ | ||||
|     overflow-x: auto; | ||||
|     overflow-y: scroll; | ||||
|     padding: 10px; | ||||
|     width: 50%; | ||||
|     width: 40%; | ||||
| } | ||||
|   | ||||
| @@ -22,15 +22,33 @@ describe('<MovieSettings/>', function () { | ||||
|     }); | ||||
|  | ||||
|     it('test simulate reindex', function () { | ||||
|         global.fetch = global.prepareFetchApi({}); | ||||
|         global.fetch = global.prepareFetchApi({success: true}); | ||||
|         const wrapper = shallow(<MovieSettings/>); | ||||
|  | ||||
|         wrapper.find(".reindexbtn").simulate("click"); | ||||
|         wrapper.find("button").findWhere(e => e.text() === "Reindex Movie" && e.type() === "button").simulate("click"); | ||||
|  | ||||
|         // initial send of reindex request to server | ||||
|         expect(global.fetch).toBeCalledTimes(1); | ||||
|     }); | ||||
|  | ||||
|     it('test failing reindex start', done => { | ||||
|         global.fetch = global.prepareFetchApi({success: false}); | ||||
|         const wrapper = shallow(<MovieSettings/>); | ||||
|  | ||||
|         wrapper.find("button").findWhere(e => e.text() === "Reindex Movie" && e.type() === "button").simulate("click"); | ||||
|  | ||||
|         // initial send of reindex request to server | ||||
|         expect(global.fetch).toBeCalledTimes(1); | ||||
|  | ||||
|         process.nextTick(() => { | ||||
|             // reindex already running --> so disable startbdn | ||||
|             expect(wrapper.state()).toMatchObject({startbtnDisabled: true}); | ||||
|  | ||||
|             global.fetch.mockClear(); | ||||
|             done(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('content available received and in state', done => { | ||||
|         global.fetch = global.prepareFetchApi({ | ||||
|             contentAvailable: true, | ||||
| @@ -51,4 +69,44 @@ describe('<MovieSettings/>', function () { | ||||
|             done(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('test reindex with no content available', done=> { | ||||
|         global.fetch = global.prepareFetchApi({ | ||||
|             contentAvailable: false | ||||
|         }); | ||||
|  | ||||
|         global.clearInterval = jest.fn(); | ||||
|  | ||||
|         const wrapper = shallow(<MovieSettings/>); | ||||
|         wrapper.instance().updateStatus(); | ||||
|  | ||||
|         process.nextTick(() => { | ||||
|             // expect the refresh interval to be cleared | ||||
|             expect(global.clearInterval).toBeCalledTimes(1); | ||||
|  | ||||
|             // expect startbtn to be reenabled | ||||
|             expect(wrapper.state()).toMatchObject({startbtnDisabled: false}); | ||||
|  | ||||
|             global.fetch.mockClear(); | ||||
|             done(); | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     it('test simulate gravity cleanup', done => { | ||||
|         global.fetch = global.prepareFetchApi("mmi"); | ||||
|         const wrapper = shallow(<MovieSettings/>); | ||||
|         wrapper.instance().setState = jest.fn(), | ||||
|  | ||||
|         wrapper.find("button").findWhere(e => e.text() === "Cleanup Gravity" && e.type() === "button").simulate("click"); | ||||
|  | ||||
|         // initial send of reindex request to server | ||||
|         expect(global.fetch).toBeCalledTimes(1); | ||||
|  | ||||
|         process.nextTick(() => { | ||||
|             expect(wrapper.instance().setState).toBeCalledTimes(1); | ||||
|  | ||||
|             global.fetch.mockClear(); | ||||
|             done(); | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
|   | ||||
| @@ -18,6 +18,7 @@ global.prepareFetchApi = (response) => { | ||||
|     const mockJsonPromise = Promise.resolve(response); | ||||
|     const mockFetchPromise = Promise.resolve({ | ||||
|         json: () => mockJsonPromise, | ||||
|         text: () => mockJsonPromise | ||||
|     }); | ||||
|     return (jest.fn().mockImplementation(() => mockFetchPromise)); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user