From 0e02c1e5fec32bc6fd18f9637f579cc718b575be Mon Sep 17 00:00:00 2001 From: Louis Jeckel Date: Mon, 21 Sep 2020 17:07:15 +0200 Subject: [PATCH] error handling on process pdf file + timeout longer --- app/Events/FileProcessingUpdate.php | 6 ++-- app/Jobs/ProcessPdfFile.php | 24 ++++++++++++-- app/PdfFile.php | 10 ++++++ config/horizon.php | 3 +- config/queue.php | 2 +- public/admin/js/admin.js | 32 ++++++++++++++++++- public/js/app.js | 32 ++++++++++++++++++- .../js/components/Publish/Step1UploadFile.vue | 19 +++++++++-- routes/channels.php | 7 ++++ 9 files changed, 124 insertions(+), 11 deletions(-) diff --git a/app/Events/FileProcessingUpdate.php b/app/Events/FileProcessingUpdate.php index 7cc2d03..7f05e16 100644 --- a/app/Events/FileProcessingUpdate.php +++ b/app/Events/FileProcessingUpdate.php @@ -23,12 +23,12 @@ class FileProcessingUpdate implements ShouldBroadcast protected $file; public $data; - public function __construct(PdfFile $file, $status, $data) + public function __construct(PdfFile $file, $status, $data = []) { $this->file = $file; $this->data = [ 'status' => $status, - 'data' => ['file_id' => $file->id] + 'data' => array_merge($data, ['file_id' => $file->id]) ]; } @@ -39,7 +39,7 @@ class FileProcessingUpdate implements ShouldBroadcast */ public function broadcastOn() { - return new PrivateChannel('fileProcessingStatus.'.$this->file->slug); + return new PrivateChannel('fileProcessingStatus'); } diff --git a/app/Jobs/ProcessPdfFile.php b/app/Jobs/ProcessPdfFile.php index 7f83b9e..613fdce 100644 --- a/app/Jobs/ProcessPdfFile.php +++ b/app/Jobs/ProcessPdfFile.php @@ -9,6 +9,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\SerializesModels; +use Throwable; class ProcessPdfFile implements ShouldQueue { @@ -20,6 +21,9 @@ class ProcessPdfFile implements ShouldQueue public $timeout = 180; + + + /** * Create a new job instance. * @@ -39,8 +43,24 @@ class ProcessPdfFile implements ShouldQueue public function handle() { $this->file->process(); - event(new FileProcessingUpdate($this->file,'done', [ - 'links' => $this->file->trackedLinks()->pluck('title') + event(new FileProcessingUpdate($this->file,'done')); + } + + /** + * Handle a job failure. + * + * @param \Throwable $exception + * @return void + */ + public function failed(Throwable $exception) + { + event(new FileProcessingUpdate($this->file,'failed', [ + 'error' => $exception->getMessage() ])); + $this->file->fail(); + + report($exception); + } } + diff --git a/app/PdfFile.php b/app/PdfFile.php index 22135c9..3990381 100644 --- a/app/PdfFile.php +++ b/app/PdfFile.php @@ -583,6 +583,16 @@ class PdfFile extends TwillModel implements Sortable } + /** + * Sets file as failed and deletes + */ + public function fail() + { + $this->update(['slug' => "FAILED_$this->slug"]); + $this->delete(); + } + + /** * @return Builder */ diff --git a/config/horizon.php b/config/horizon.php index 866e3e5..a4b563e 100644 --- a/config/horizon.php +++ b/config/horizon.php @@ -151,7 +151,7 @@ return [ | */ - 'memory_limit' => 64, + 'memory_limit' => 128, /* |-------------------------------------------------------------------------- @@ -182,6 +182,7 @@ return [ 'queue' => ['default'], 'balance' => 'simple', 'processes' => 3, + 'timeout' => 600, 'tries' => 1, ], ], diff --git a/config/queue.php b/config/queue.php index 00b76d6..178d302 100644 --- a/config/queue.php +++ b/config/queue.php @@ -63,7 +63,7 @@ return [ 'driver' => 'redis', 'connection' => 'default', 'queue' => env('REDIS_QUEUE', 'default'), - 'retry_after' => 90, + 'retry_after' => 600, 'block_for' => null, ], diff --git a/public/admin/js/admin.js b/public/admin/js/admin.js index fa47dde..d0e8d08 100644 --- a/public/admin/js/admin.js +++ b/public/admin/js/admin.js @@ -3146,6 +3146,11 @@ __webpack_require__.r(__webpack_exports__); // // // +// +// +// +// +// /* harmony default export */ __webpack_exports__["default"] = ({ @@ -3163,6 +3168,7 @@ __webpack_require__.r(__webpack_exports__); progressMode: 'determinate', csrf: document.querySelectorAll('meta[name="csrf-token"]')[0].content, status: 'start', + error: '', links: [], repeaterFields: [{ name: 'headline-repeater', @@ -3203,7 +3209,6 @@ __webpack_require__.r(__webpack_exports__); uploadedFile: function uploadedFile(file) { if (file.success) { this.progressMode = 'indeterminate'; - Echo["private"]("fileProcessingStatus.".concat(file.response.data.slug)).listen('.status.update', this.processStatusUpdate); } } }, @@ -3225,6 +3230,13 @@ __webpack_require__.r(__webpack_exports__); }); }); } + + if (e.status === 'failed') { + this.progressMode = 'determinate'; + this.status = 'error'; + this.error = e.data.error; + console.error(e.data.error); + } }, getNextRef: function getNextRef(collection_id) { var collection = this.collections.find(function (c) { @@ -3253,6 +3265,7 @@ __webpack_require__.r(__webpack_exports__); mounted: function mounted() { var _this2 = this; + Echo["private"]("fileProcessingStatus").listen('.status.update', this.processStatusUpdate); axios.get('/publish/collections').then(function (d) { _this2.collections = d.data.data; _this2.file_ref = _this2.getNextRef(1); @@ -51815,6 +51828,23 @@ var render = function() { _vm._m(1) ] ) + : _vm.status === "error" + ? _c( + "div", + { staticClass: "alert-danger alert", attrs: { role: "alert" } }, + [ + _c("i", { staticClass: "fas fa-exclamation-triangle" }), + _vm._v(" \n "), + _c("span", [ + _c("strong", [ + _vm._v( + "Une erreur est survenue lors du traitement du fichier. " + ) + ]), + _vm._v(" (" + _vm._s(_vm.error) + ")") + ]) + ] + ) : _vm._e(), _vm._v(" "), _vm.status === "done" diff --git a/public/js/app.js b/public/js/app.js index 99cea1c..79dd2fb 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -8341,6 +8341,11 @@ __webpack_require__.r(__webpack_exports__); // // // +// +// +// +// +// /* harmony default export */ __webpack_exports__["default"] = ({ @@ -8358,6 +8363,7 @@ __webpack_require__.r(__webpack_exports__); progressMode: 'determinate', csrf: document.querySelectorAll('meta[name="csrf-token"]')[0].content, status: 'start', + error: '', links: [], repeaterFields: [{ name: 'headline-repeater', @@ -8398,7 +8404,6 @@ __webpack_require__.r(__webpack_exports__); uploadedFile: function uploadedFile(file) { if (file.success) { this.progressMode = 'indeterminate'; - Echo["private"]("fileProcessingStatus.".concat(file.response.data.slug)).listen('.status.update', this.processStatusUpdate); } } }, @@ -8420,6 +8425,13 @@ __webpack_require__.r(__webpack_exports__); }); }); } + + if (e.status === 'failed') { + this.progressMode = 'determinate'; + this.status = 'error'; + this.error = e.data.error; + console.error(e.data.error); + } }, getNextRef: function getNextRef(collection_id) { var collection = this.collections.find(function (c) { @@ -8448,6 +8460,7 @@ __webpack_require__.r(__webpack_exports__); mounted: function mounted() { var _this2 = this; + Echo["private"]("fileProcessingStatus").listen('.status.update', this.processStatusUpdate); axios.get('/publish/collections').then(function (d) { _this2.collections = d.data.data; _this2.file_ref = _this2.getNextRef(1); @@ -81351,6 +81364,23 @@ var render = function() { _vm._m(1) ] ) + : _vm.status === "error" + ? _c( + "div", + { staticClass: "alert-danger alert", attrs: { role: "alert" } }, + [ + _c("i", { staticClass: "fas fa-exclamation-triangle" }), + _vm._v(" \n "), + _c("span", [ + _c("strong", [ + _vm._v( + "Une erreur est survenue lors du traitement du fichier. " + ) + ]), + _vm._v(" (" + _vm._s(_vm.error) + ")") + ]) + ] + ) : _vm._e(), _vm._v(" "), _vm.status === "done" diff --git a/resources/js/components/Publish/Step1UploadFile.vue b/resources/js/components/Publish/Step1UploadFile.vue index bdb08b1..06f64cf 100644 --- a/resources/js/components/Publish/Step1UploadFile.vue +++ b/resources/js/components/Publish/Step1UploadFile.vue @@ -95,6 +95,11 @@ Fichier enregistré, traitement en cours... + +