Skip to content

Commit

Permalink
Merge pull request #338 from Ontotext-AD/GDB-5278-Restart-Repository-…
Browse files Browse the repository at this point in the history
…Without-Restarting-GDB

GDB-5278 Restart repository without restarting GDB
  • Loading branch information
avataar authored Dec 17, 2020
2 parents 2bdf615 + ad79d23 commit 03affc2
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 26 deletions.
31 changes: 27 additions & 4 deletions src/js/angular/core/services/repositories.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ const modules = [

const repositories = angular.module('graphdb.framework.core.services.repositories', modules);

repositories.service('$repositories', ['$http', 'toastr', '$rootScope', '$timeout', '$location', 'productInfo', '$jwtAuth', 'RepositoriesRestService', 'LocationsRestService', 'LicenseRestService',
function ($http, toastr, $rootScope, $timeout, $location, productInfo, $jwtAuth, RepositoriesRestService, LocationsRestService, LicenseRestService) {
repositories.service('$repositories', ['$http', 'toastr', '$rootScope', '$timeout', '$location', 'productInfo', '$jwtAuth',
'RepositoriesRestService', 'LocationsRestService', 'LicenseRestService',
function ($http, toastr, $rootScope, $timeout, $location, productInfo, $jwtAuth,
RepositoriesRestService, LocationsRestService, LicenseRestService) {
this.repositoryStorageName = 'com.ontotext.graphdb.repository';

this.location = '';
Expand Down Expand Up @@ -98,8 +100,14 @@ repositories.service('$repositories', ['$http', 'toastr', '$rootScope', '$timeou
return this.degradedReason;
};

this.init = function (successCallback, errorCallback) {
this.locationsShouldReload = true;
this.initQuick = function () {
this.init(null, null, true);
};

this.init = function (successCallback, errorCallback, quick) {
if (!quick) {
this.locationsShouldReload = true;
}
this.loading = true;
// noCancelOnRouteChange Prevent angularCancelOnNavigateModule.js from canceling this request on route change
LocationsRestService.getActiveLocation().then(
Expand Down Expand Up @@ -130,6 +138,9 @@ repositories.service('$repositories', ['$http', 'toastr', '$rootScope', '$timeou
} else {
loadingDone();
// no active location
if (quick) {
that.locationsShouldReload = true;
}
that.location = '';
that.repositories = [];
that.setRepository('');
Expand Down Expand Up @@ -298,6 +309,18 @@ repositories.service('$repositories', ['$http', 'toastr', '$rootScope', '$timeou
}
};

this.restartRepository = function (repositoryId) {
RepositoriesRestService.restartRepository(repositoryId)
.success(function () {
toastr.success(`Restarting repository ${repositoryId}`);
// This provides immediate visual feedback by updating the status
that.initQuick();
}).error(function (data) {
const msg = getError(data);
toastr.error(msg, 'Error');
});
};

this.getRepositoryTurtleConfig = function (repository) {
return $http.get('rest/repositories/' + repository.id, {
headers: {
Expand Down
74 changes: 56 additions & 18 deletions src/js/angular/repositories/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,10 @@ const getFileName = function(path) {
return name;
};

LocationsAndRepositoriesCtrl.$inject = ['$scope', '$modal', 'toastr', '$repositories', 'ModalService', '$jwtAuth', 'LocationsRestService', 'LocalStorageAdapter'];
function LocationsAndRepositoriesCtrl($scope, $modal, toastr, $repositories, ModalService, $jwtAuth, LocationsRestService, LocalStorageAdapter) {
LocationsAndRepositoriesCtrl.$inject = ['$scope', '$modal', 'toastr', '$repositories', 'ModalService',
'$jwtAuth', 'LocationsRestService', 'LocalStorageAdapter', '$interval'];
function LocationsAndRepositoriesCtrl($scope, $modal, toastr, $repositories, ModalService,
$jwtAuth, LocationsRestService, LocalStorageAdapter, $interval) {
$scope.loader = true;

$scope.isLocationInactive = function (location) {
Expand Down Expand Up @@ -250,8 +252,9 @@ function LocationsAndRepositoriesCtrl($scope, $modal, toastr, $repositories, Mod
$scope.deleteRepository = function (repositoryId) {
ModalService.openSimpleModal({
title: 'Confirm delete',
message: 'Are you sure you want to delete the repository \'' + repositoryId + '\'?' +
'<p>All data in the repository will be lost.</p>',
message: `<p>Are you sure you want to delete the repository <strong>${repositoryId}</strong>?</p>
<p><span class="icon-2x icon-warning" style="color: #d54a33"/>
All data in the repository will be lost.</p>`,
warning: true
}).result
.then(function () {
Expand All @@ -261,6 +264,21 @@ function LocationsAndRepositoriesCtrl($scope, $modal, toastr, $repositories, Mod
});
};

$scope.restartRepository = function (repositoryId) {
ModalService.openSimpleModal({
title: 'Confirm restart',
message: `<p>Are you sure you want to restart the repository <strong>${repositoryId}</strong>?</p>
<p><span class="icon-2x icon-warning" style="color: #d54a33"/>
The repository will be shut down immediately and all running queries
and updates will be cancelled.</p>`,
warning: true
}).result
.then(function () {
$scope.loader = true;
$repositories.restartRepository(repositoryId);
});
}

$scope.toggleDefaultRepository = function (repositoryId) {
if ($scope.getDefaultRepository() === repositoryId) {
// unset
Expand Down Expand Up @@ -330,7 +348,14 @@ function LocationsAndRepositoriesCtrl($scope, $modal, toastr, $repositories, Mod
});
};

$repositories.init();
const timer = $interval(function () {
// Update repositories state
$repositories.initQuick();
}, 5000);

$scope.$on('$destroy', function () {
$interval.cancel(timer);
});

function removeCachedGraphsOnDelete(repoId) {
const cashedDependenciesGraphPrefix = `dependencies-selectedGraph-${repoId}`;
Expand Down Expand Up @@ -560,7 +585,7 @@ function AddRepositoryCtrl($scope, toastr, $repositories, $location, Upload, isE

$scope.createRepo = function () {
if (!$scope.repositoryInfo.id) {
toastr.error('Repository id cannot be empty');
toastr.error('Repository ID cannot be empty');
return;
}
if ($scope.repositoryInfo.type === 'ontop') {
Expand Down Expand Up @@ -652,6 +677,7 @@ function EditRepositoryCtrl($scope, $routeParams, toastr, $repositories, $locati
$scope.isFreeEdition = isFreeEdition;
$scope.repositoryInfo = {};
$scope.repositoryInfo.id = $scope.params.repositoryId;
$scope.repositoryInfo.restartRequested = false;
$scope.saveRepoId = $scope.params.repositoryId;
$scope.pageTitle = 'Edit Repository: ' + $scope.params.repositoryId;
$scope.hasActiveLocation = function () {
Expand Down Expand Up @@ -718,25 +744,38 @@ function EditRepositoryCtrl($scope, $routeParams, toastr, $repositories, $locati
.success(function () {
toastr.success('The repository ' + $scope.repositoryInfo.saveId + ' has been edited.');
$repositories.init($scope.goBackToPreviousLocation);
if ($scope.repositoryInfo.saveId === $scope.repositoryInfo.id && $scope.repositoryInfo.restartRequested) {
$repositories.restartRepository($scope.repositoryInfo.id);
}
}).error(function (data) {
const msg = getError(data);
toastr.error(msg, 'Error');
$scope.loader = false;
});
const msg = getError(data);
toastr.error(msg, 'Error');
$scope.loader = false;
});
};

$scope.editRepository = function () {
$scope.isInvalidRepoName = !filenamePattern.test($scope.repositoryInfo.id);
if ($scope.repositoryInfo.type != 'ontop') {
if ($scope.repositoryInfo.type !== 'ontop') {
$scope.isInvalidEntityIndexSize = !numberPattern.test($scope.repositoryInfo.params.entityIndexSize.value);
$scope.isInvalidQueryTimeout = !numberPattern.test($scope.repositoryInfo.params.queryTimeout.value);
$scope.isInvalidQueryLimit = !numberPattern.test($scope.repositoryInfo.params.queryLimitResults.value);
}
let modalMsg = `Save changes to repository <strong>${$scope.repositoryInfo.id}</strong>?<br><br>`;
if ($scope.repositoryInfo.saveId !== $scope.repositoryInfo.id) {
modalMsg += `<span class="icon-2x icon-warning" style="color: #d54a33"/>
The repository will be stopped and renamed.`;
} else if ($scope.repositoryInfo.restartRequested) {
modalMsg += `<span class="icon-2x icon-warning" style="color: #d54a33"/>
The repository will be restarted.`;
} else {
modalMsg += `<span class="icon-2x icon-warning" style="color: #d54a33"/>
Repository restart required for changes to take effect.`;
}
if (!$scope.isInvalidRepoName) {
ModalService.openSimpleModal({
title: 'Confirm edit',
message: (($scope.repositoryInfo.saveId !== $scope.repositoryInfo.id) ? ' You are changing the repository id. Are you sure?' :
'Save changes to this repository?<br><br><span class="icon-warning" style="color: #d54a33"> Restart of GraphDB needed!</span>'),
title: 'Confirm save',
message: modalMsg,
warning: true
}).result
.then(function () {
Expand All @@ -748,13 +787,13 @@ function EditRepositoryCtrl($scope, $routeParams, toastr, $repositories, $locati
};

$scope.editRepositoryId = function () {
let msg = 'Changing the repository id is a dangerous operation since it moves the repository folder. Also, it may be slow due to reinitialisation of the repository.';
let msg = '<p>Changing the repository ID is a dangerous operation since it renames the repository folder and enforces repository shutdown.</p>';
if ($scope.isEnterprise) {
msg += 'If your repository is in a cluster, it is your responsibility to update the cluster after renaming.';
msg += '<p>If your repository is in a cluster, it is your responsibility to update the cluster after renaming.</p>';
}
ModalService.openSimpleModal({
title: 'Confirm enable edit',
message: msg + ' Are you sure you want to enable repository id editing?',
message: msg,
warning: true
}).result.then(function () {
$scope.canEditRepoId = true;
Expand Down Expand Up @@ -791,5 +830,4 @@ function EditRepositoryCtrl($scope, $routeParams, toastr, $repositories, $locati
toastr.error(msg, 'Failed to connect');
});
}

}
7 changes: 6 additions & 1 deletion src/js/angular/rest/repositories.rest.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ function RepositoriesRestService($http) {
getCluster,
getRepositoryFileContent,
updateRepositoryFileContent,
validateOntopPropertiesConnection
validateOntopPropertiesConnection,
restartRepository
};

function getRepository(repositoryid) {
Expand All @@ -42,6 +43,10 @@ function RepositoriesRestService($http) {
return $http.put(`${REPOSITORIES_ENDPOINT}/${repositoryId}`, config);
}

function restartRepository(repositoryId) {
return $http.post(`${REPOSITORIES_ENDPOINT}/${repositoryId}/restart`);
}

function getRepositoryConfiguration(repositoryType) {
return $http.get(`${REPOSITORIES_ENDPOINT}/defaultConfig/${repositoryType}`);
}
Expand Down
11 changes: 10 additions & 1 deletion src/pages/repositories.html
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ <h1>
popover-trigger="mouseenter" popover-placement="bottom-right"
popover-template="popoverTemplate" popover-title="Repository {{repository.id}}">
<span class="icon-lg" ng-class="'icon-repo-' + repository.type"></span>
<strong class="repository-id">{{repository.id}}</strong></span><span class="small" ng-if="repository.title"><small> &middot; {{repository.title}}</small></span>
<strong class="repository-id">{{repository.id}}</strong></span>
<span class="small"><small> &middot; <span class="text-secondary">{{repository.state}}</span></small></span>
<span class="small" ng-if="repository.title"><small> &middot; {{repository.title}}</small></span>
</div>
</td>
<td width="150" class="text-nowrap repository-actions">
Expand Down Expand Up @@ -97,6 +99,13 @@ <h1>
tooltip-trigger="mouseenter">
<em class="icon-download"></em>
</a>
<button class="btn btn-link p-0 restart-repository-btn" type="button"
tooltip="Restart repository {{repository.id}}"
tooltip-placement="top"
tooltip-trigger="mouseenter"
ng-click="restartRepository(repository.id)">
<span class="icon-reload"></span>
</button>
<button class="btn btn-link p-0 secondary delete-repository-btn" type="button"
tooltip="Delete repository"
tooltip-placement="top"
Expand Down
12 changes: 12 additions & 0 deletions src/pages/repository.html
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,18 @@ <h1>{{pageTitle}}</h1>
<input class="form-control" id="nonInterpretablePredicates" name="nonInterpretablePredicates" type="url" ng-model="repositoryInfo.params.nonInterpretablePredicates.value"/>
</div>
</div>
<div class="form-group row" ng-if="editRepoPage">
<div class="checkbox offset-xs-3 offset-md-3">
<label class="col-xs-4 col-sm-4 col-md-4 col-md-offset-3">
<input id="restartRepo" name="restartRepo"
type="checkbox"
ng-model="repositoryInfo.restartRequested"
ng-checked="repositoryInfo.restartRequested || repositoryInfo.saveId !== repositoryInfo.id"
ng-disabled="repositoryInfo.saveId !== repositoryInfo.id"/>
Restart repository
</label>
</div>
</div>
</div>
<div class="form-group row">
<div class="col-xs-4 col-sm-4 col-md-4 col-md-offset-3">
Expand Down
2 changes: 1 addition & 1 deletion test-cypress/integration/repository/repositories.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ describe('Repositories', () => {
getToast()
.find('.toast-error')
.should('be.visible')
.and('contain', 'Repository id cannot be empty');
.and('contain', 'Repository ID cannot be empty');
});

it('should allow creation of repositories with custom settings', () => {
Expand Down
4 changes: 3 additions & 1 deletion test/repositories/controllers.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,9 @@ describe('==> Repository module controllers tests', function () {
const argument = modalInstance.openSimpleModal.calls.first().args[0];
expect(argument).toEqual({
title: 'Confirm delete',
message: `Are you sure you want to delete the repository '${repoId}'?<p>All data in the repository will be lost.</p>`,
message: `<p>Are you sure you want to delete the repository <strong>${repoId}</strong>?</p>
<p><span class="icon-2x icon-warning" style="color: #d54a33"/>
All data in the repository will be lost.</p>`,
warning: true
});

Expand Down

0 comments on commit 03affc2

Please sign in to comment.