From f6d13266760da040cc16e93eaee68cc05c741464 Mon Sep 17 00:00:00 2001 From: Vladyslav_Prykhodko Date: Wed, 22 May 2019 12:44:05 +0300 Subject: [PATCH] Add resend request for error 429 --- ui/src/app/api/device.service.js | 35 +++---------------- ui/src/app/global-interceptor.service.js | 20 +++++++++++ .../import-dialog-csv.controller.js | 3 +- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/ui/src/app/api/device.service.js b/ui/src/app/api/device.service.js index c0db363869..c99376e17f 100644 --- a/ui/src/app/api/device.service.js +++ b/ui/src/app/api/device.service.js @@ -20,7 +20,7 @@ export default angular.module('thingsboard.api.device', [thingsboardTypes]) .name; /*@ngInject*/ -function DeviceService($http, $q, $window, userService, attributeService, customerService, types, $timeout) { +function DeviceService($http, $q, $window, userService, attributeService, customerService, types) { var service = { assignDeviceToCustomer: assignDeviceToCustomer, @@ -173,23 +173,6 @@ function DeviceService($http, $q, $window, userService, attributeService, custom return deferred.promise; } - function resendRequest(callback){ - const deferred = $q.defer(); - let request = callback(); - request.then(function success(response) { - deferred.resolve(response); - }, function fail(response) { - if (response.status === 429) { - $timeout(function () { - request = callback(); - }, 1000 + Math.random() * 10000); - } else { - deferred.reject(response); - } - }); - return deferred.promise; - } - function saveDeviceRelarion(deviceId, deviceRelation, config) { const deferred = $q.defer(); let attributesType = Object.keys(types.attributesScope); @@ -197,16 +180,12 @@ function DeviceService($http, $q, $window, userService, attributeService, custom let promise = ""; for (let i = 0; i < attributesType.length; i++) { if (deviceRelation.attributes[attributesType[i]] && deviceRelation.attributes[attributesType[i]].length !== 0) { - promise = resendRequest(function () { - return attributeService.saveEntityAttributes(types.entityType.device, deviceId, types.attributesScope[attributesType[i]].value, deviceRelation.attributes[attributesType[i]], config); - }); + promise = attributeService.saveEntityAttributes(types.entityType.device, deviceId, types.attributesScope[attributesType[i]].value, deviceRelation.attributes[attributesType[i]], config); allPromise.push(promise); } } if (deviceRelation.timeseries.length !== 0) { - promise = resendRequest(function () { - return attributeService.saveEntityTimeseries(types.entityType.device, deviceId, "time", deviceRelation.timeseries, config); - }); + promise = attributeService.saveEntityTimeseries(types.entityType.device, deviceId, "time", deviceRelation.timeseries, config); allPromise.push(promise); } $q.all(allPromise).then(function success() { @@ -227,9 +206,7 @@ function DeviceService($http, $q, $window, userService, attributeService, custom name: deviceParameters.name, type: deviceParameters.type }; - resendRequest(function () { - return saveDevice(newDevice, config); - }).then(function success(response) { + saveDevice(newDevice, config).then(function success(response) { statisticalInfo.create.device = 1; saveDeviceRelarion(response.id.id, deviceParameters, config).then(function success() { deferred.resolve(statisticalInfo); @@ -237,9 +214,7 @@ function DeviceService($http, $q, $window, userService, attributeService, custom }, function fail(response) { console.log(response); // eslint-disable-line if (update) { - resendRequest(function () { - return findByName(deviceParameters.name, config); - }).then(function success(response) { + findByName(deviceParameters.name, config).then(function success(response) { statisticalInfo.update.device = 1; saveDeviceRelarion(response.id.id, deviceParameters, config).then(function success() { deferred.resolve(statisticalInfo); diff --git a/ui/src/app/global-interceptor.service.js b/ui/src/app/global-interceptor.service.js index f45bf89d81..f5dc3bb576 100644 --- a/ui/src/app/global-interceptor.service.js +++ b/ui/src/app/global-interceptor.service.js @@ -21,6 +21,7 @@ export default function GlobalInterceptor($rootScope, $q, $injector) { var userService; var types; var http; + var timeout; var internalUrlPrefixes = [ '/api/auth/token', @@ -71,6 +72,13 @@ export default function GlobalInterceptor($rootScope, $q, $injector) { return http; } + function getTimeout() { + if (!timeout) { + timeout = $injector.get("$timeout"); + } + return timeout; + } + function rejectionErrorCode(rejection) { if (rejection && rejection.data && rejection.data.errorCode) { return rejection.data.errorCode; @@ -144,12 +152,20 @@ export default function GlobalInterceptor($rootScope, $q, $injector) { return response; } + function retryRequest (httpConfig) { + var thisTimeout = 1000 + Math.random() * 10000; + return getTimeout()(function() { + return getHttp()(httpConfig); + }, thisTimeout); + } + function responseError(rejection) { if (rejection.config.url.startsWith('/api/')) { updateLoadingState(rejection.config, false); } var unhandled = false; var ignoreErrors = rejection.config.ignoreErrors; + var resendRequest = rejection.config.resendRequest; if (rejection.refreshTokenPending || rejection.status === 401) { var errorCode = rejectionErrorCode(rejection); if (rejection.refreshTokenPending || (errorCode && errorCode === getTypes().serverErrorCode.jwtTokenExpired)) { @@ -161,6 +177,10 @@ export default function GlobalInterceptor($rootScope, $q, $injector) { if (!ignoreErrors) { $rootScope.$broadcast('forbidden'); } + } else if (rejection.status === 429) { + if (resendRequest) { + return retryRequest(rejection.config); + } } else if (rejection.status === 0 || rejection.status === -1) { getToast().showError(getTranslate().instant('error.unable-to-connect')); } else if (!rejection.config.url.startsWith('/api/plugins/rpc')) { diff --git a/ui/src/app/import-export/import-dialog-csv.controller.js b/ui/src/app/import-export/import-dialog-csv.controller.js index 873d9c5799..a2e4732006 100644 --- a/ui/src/app/import-export/import-dialog-csv.controller.js +++ b/ui/src/app/import-export/import-dialog-csv.controller.js @@ -147,7 +147,8 @@ export default function ImportDialogCsvController($scope, $mdDialog, toast, impo data = parseData; var arrayData = []; var config = { - ignoreErrors: true + ignoreErrors: true, + resendRequest: true }; for (var i = 0; i < data.rows.length; i ++) { var obj = {