Appearance
Restart Services
Restarts all receiver and output services in the system. This operation reinitializes device receivers and outputs based on the current configuration, allowing changes to take effect without a full system restart.
Request
http
GET /api/restart-servicesAuthentication Required: Must include JWT token in Authorization header.
Required Scope: restart_services
Content-Type: Not required (no request body)
Request Examples
Basic Service Restart
bash
curl -X GET "http://your-server-ip:port/api/restart-services" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"Using JavaScript
javascript
const response = await fetch('/api/restart-services', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});Response
Success (200 OK)
json
{
"success": true
}Error Responses
Note: Error responses are returned as plain text, not JSON (unlike most other endpoints).
401 Unauthorized
NOT_LOGGED_IN403 Forbidden
FORBIDDEN405 Method Not Allowed
Method Not AllowedService Restart Process
What Gets Restarted
The restart operation affects:
- Receiver Services: All configured device receivers are stopped and restarted
- Output Services: All configured output modules are stopped and restarted
- Configuration Reload: Current system configuration is reloaded during restart
- Connection Re-establishment: Device connections are re-established with new settings
When to Use Service Restart
Common Use Cases:
- After modifying receiver or output configuration
- When device communication issues occur
- After changing network settings that affect device connectivity
- To apply configuration changes without full system restart
- During maintenance procedures
Configuration Changes That Require Restart:
- Receiver settings modifications
- Output module configuration changes
- Network interface changes
- Device communication parameters
- Protocol settings updates
Usage Examples
Basic Service Restart
javascript
async function restartServices(token) {
try {
const response = await fetch('/api/restart-services', {
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
}
});
if (!response.ok) {
// Handle plain text error responses
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
const result = await response.json();
console.log('Services restarted successfully');
return result;
} catch (error) {
console.error('Failed to restart services:', error);
throw error;
}
}Service Management Class
javascript
class ServiceManager {
constructor(token) {
this.token = token;
}
async restartServices() {
console.log('Initiating service restart...');
try {
const response = await fetch('/api/restart-services', {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.token}`
}
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Restart failed: ${errorText}`);
}
const result = await response.json();
console.log('✓ All services restarted successfully');
return result;
} catch (error) {
console.error('✗ Service restart failed:', error.message);
throw error;
}
}
async restartWithStatusCheck(maxWaitTime = 30000) {
console.log('Restarting services with status monitoring...');
// Initiate restart
await this.restartServices();
// Wait for services to stabilize
const startTime = Date.now();
let servicesReady = false;
while (!servicesReady && (Date.now() - startTime) < maxWaitTime) {
try {
// Check if services are responding
const statusResponse = await fetch('/api/status', {
headers: { 'Authorization': `Bearer ${this.token}` }
});
if (statusResponse.ok) {
const status = await statusResponse.json();
// Check if essential services are running
if (status.database_ready && status.services_ready) {
servicesReady = true;
console.log('✓ Services are ready and responding');
}
}
} catch (statusError) {
// Services might still be restarting
console.log('Services still restarting...');
}
if (!servicesReady) {
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
}
}
if (!servicesReady) {
console.warn('⚠ Services restart completed, but status check timed out');
}
return servicesReady;
}
}
// Usage
const serviceManager = new ServiceManager(authToken);
// Simple restart
await serviceManager.restartServices();
// Restart with status monitoring
const ready = await serviceManager.restartWithStatusCheck();Configuration Change Workflow
javascript
class ConfigurationManager {
constructor(token) {
this.token = token;
this.serviceManager = new ServiceManager(token);
}
async updateConfigurationAndRestart(newSettings) {
console.log('Updating configuration and restarting services...');
try {
// Step 1: Update settings
console.log('1. Updating system settings...');
const settingsResponse = await fetch('/api/settings', {
method: 'PUT',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(newSettings)
});
if (!settingsResponse.ok) {
throw new Error('Failed to update settings');
}
console.log('✓ Settings updated successfully');
// Step 2: Restart services to apply changes
console.log('2. Restarting services to apply changes...');
await this.serviceManager.restartServices();
// Step 3: Verify services are running
console.log('3. Verifying services are operational...');
const ready = await this.serviceManager.restartWithStatusCheck();
if (ready) {
console.log('✓ Configuration update completed successfully');
return { success: true, message: 'Configuration updated and services restarted' };
} else {
console.warn('⚠ Configuration updated but service status unclear');
return { success: true, message: 'Configuration updated, please verify service status' };
}
} catch (error) {
console.error('✗ Configuration update failed:', error.message);
throw error;
}
}
}
// Usage
const configManager = new ConfigurationManager(authToken);
const newSettings = {
receivers: {
// Updated receiver configuration
},
outputs: {
// Updated output configuration
}
};
await configManager.updateConfigurationAndRestart(newSettings);Maintenance Workflow
javascript
class MaintenanceManager {
constructor(token) {
this.token = token;
this.serviceManager = new ServiceManager(token);
}
async performMaintenanceRestart(reason = 'Scheduled maintenance') {
const startTime = new Date();
console.log(`Starting maintenance restart: ${reason}`);
try {
// Log maintenance start
await this.logMaintenanceEvent('restart_start', reason, startTime);
// Perform restart
await this.serviceManager.restartServices();
// Verify services
const ready = await this.serviceManager.restartWithStatusCheck(45000); // 45 second timeout
const endTime = new Date();
const duration = endTime - startTime;
// Log maintenance completion
await this.logMaintenanceEvent('restart_complete', reason, endTime, duration, ready);
return {
success: true,
duration: duration,
servicesReady: ready,
startTime: startTime,
endTime: endTime
};
} catch (error) {
const endTime = new Date();
const duration = endTime - startTime;
// Log maintenance failure
await this.logMaintenanceEvent('restart_failed', reason, endTime, duration, false, error.message);
throw error;
}
}
async logMaintenanceEvent(event, reason, timestamp, duration = null, success = null, error = null) {
const logEntry = {
timestamp: timestamp.toISOString(),
event: event,
reason: reason,
duration: duration,
success: success,
error: error,
user: this.getCurrentUser()
};
console.log('MAINTENANCE_LOG:', JSON.stringify(logEntry));
// Send to audit/logging service
try {
await fetch('/api/maintenance/log', {
method: 'POST',
headers: {
'Authorization': `Bearer ${this.token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(logEntry)
});
} catch (logError) {
console.error('Failed to log maintenance event:', logError);
}
}
getCurrentUser() {
try {
const token = localStorage.getItem('authToken');
const payload = JSON.parse(atob(token.split('.')[1]));
return payload.username || payload.sub;
} catch {
return 'unknown';
}
}
}
// Usage
const maintenanceManager = new MaintenanceManager(authToken);
// Scheduled maintenance restart
await maintenanceManager.performMaintenanceRestart('Weekly scheduled restart');
// Emergency restart
await maintenanceManager.performMaintenanceRestart('Emergency restart due to communication issues');Error Handling and Retry Logic
javascript
class RestartServiceManager {
constructor(token, maxRetries = 3, retryDelay = 5000) {
this.token = token;
this.maxRetries = maxRetries;
this.retryDelay = retryDelay;
}
async restartServicesWithRetry() {
let lastError;
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
try {
console.log(`Restart attempt ${attempt}/${this.maxRetries}...`);
const response = await fetch('/api/restart-services', {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.token}`
}
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`HTTP ${response.status}: ${errorText}`);
}
const result = await response.json();
console.log(`✓ Services restarted successfully on attempt ${attempt}`);
return result;
} catch (error) {
lastError = error;
console.error(`✗ Restart attempt ${attempt} failed:`, error.message);
if (attempt < this.maxRetries) {
console.log(`Waiting ${this.retryDelay}ms before retry...`);
await new Promise(resolve => setTimeout(resolve, this.retryDelay));
}
}
}
throw new Error(`All ${this.maxRetries} restart attempts failed. Last error: ${lastError.message}`);
}
async handleRestartErrors(error) {
if (error.message.includes('NOT_LOGGED_IN')) {
throw new Error('Authentication expired. Please log in again.');
} else if (error.message.includes('FORBIDDEN')) {
throw new Error('Insufficient permissions. restart_services scope required.');
} else if (error.message.includes('Method Not Allowed')) {
throw new Error('Invalid request method. Use GET for restart endpoint.');
} else {
throw new Error(`Service restart failed: ${error.message}`);
}
}
}
// Usage with retry logic
const restartManager = new RestartServiceManager(authToken, 3, 10000);
try {
await restartManager.restartServicesWithRetry();
console.log('Services restarted successfully');
} catch (error) {
await restartManager.handleRestartErrors(error);
}Integration with Monitoring
javascript
class ServiceRestartMonitor {
constructor(token) {
this.token = token;
this.restartHistory = [];
}
async monitoredRestart(reason) {
const restartEvent = {
id: Date.now(),
reason: reason,
startTime: new Date(),
status: 'in_progress'
};
this.restartHistory.push(restartEvent);
try {
// Capture pre-restart status
const preStatus = await this.getSystemStatus();
restartEvent.preRestartStatus = preStatus;
// Perform restart
console.log(`Starting monitored restart: ${reason}`);
const response = await fetch('/api/restart-services', {
method: 'GET',
headers: {
'Authorization': `Bearer ${this.token}`
}
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(errorText);
}
const result = await response.json();
// Wait for services to stabilize
await new Promise(resolve => setTimeout(resolve, 5000));
// Capture post-restart status
const postStatus = await this.getSystemStatus();
// Update restart event
restartEvent.endTime = new Date();
restartEvent.duration = restartEvent.endTime - restartEvent.startTime;
restartEvent.status = 'completed';
restartEvent.postRestartStatus = postStatus;
restartEvent.success = true;
console.log(`✓ Monitored restart completed in ${restartEvent.duration}ms`);
return restartEvent;
} catch (error) {
restartEvent.endTime = new Date();
restartEvent.duration = restartEvent.endTime - restartEvent.startTime;
restartEvent.status = 'failed';
restartEvent.error = error.message;
restartEvent.success = false;
console.error(`✗ Monitored restart failed:`, error.message);
throw error;
}
}
async getSystemStatus() {
try {
const response = await fetch('/api/status', {
headers: { 'Authorization': `Bearer ${this.token}` }
});
if (response.ok) {
return await response.json();
}
} catch (error) {
console.warn('Could not fetch system status:', error.message);
}
return null;
}
getRestartHistory() {
return this.restartHistory;
}
getLastRestart() {
return this.restartHistory[this.restartHistory.length - 1];
}
}
// Usage
const restartMonitor = new ServiceRestartMonitor(authToken);
// Perform monitored restart
const restartEvent = await restartMonitor.monitoredRestart('Configuration update');
// Check restart history
const history = restartMonitor.getRestartHistory();
console.log('Recent restarts:', history);Security Considerations
Access Control
- Scope Required: Users must have the
restart_servicesscope - Admin Privilege: Service restart should typically be restricted to administrators
- Audit Logging: All restart operations should be logged for security audit
Service Availability
- Planned Maintenance: Use during scheduled maintenance windows when possible
- Impact Assessment: Consider impact on connected devices and active operations
- Recovery Planning: Have rollback procedures in case of restart issues
Monitoring and Alerting
javascript
async function secureServiceRestart(token, reason, userContext) {
// Validate user permissions
const userScopes = getUserScopes(token);
if (!userScopes.includes('restart_services')) {
throw new Error('Insufficient permissions for service restart');
}
// Log restart initiation for audit
await auditLog({
action: 'service_restart_initiated',
user: userContext.username,
reason: reason,
timestamp: new Date().toISOString()
});
try {
// Perform restart
const result = await restartServices(token);
// Log successful restart
await auditLog({
action: 'service_restart_completed',
user: userContext.username,
reason: reason,
success: true,
timestamp: new Date().toISOString()
});
return result;
} catch (error) {
// Log failed restart
await auditLog({
action: 'service_restart_failed',
user: userContext.username,
reason: reason,
success: false,
error: error.message,
timestamp: new Date().toISOString()
});
throw error;
}
}Important Notes
- Scope Required: Users must have the
restart_servicesscope to access this endpoint - Error Format: Unlike most endpoints, errors are returned as plain text, not JSON
- Service Interruption: Brief service interruption occurs during restart process
- Configuration Reload: Current configuration is reloaded and applied during restart
- Connection Re-establishment: Device connections are re-established after restart
- No Request Body: This is a GET request with no request body required
- Timeout Considerations: Service restart may take time to complete
- Status Verification: Consider checking system status after restart to verify services are operational
- Maintenance Planning: Use during planned maintenance windows to minimize operational impact