backend: implement health check for storage providers and integrate into service initialization
This commit is contained in:
parent
da26614033
commit
385dab5710
@ -90,5 +90,11 @@ const configureStorage = (storageMode: string) => {
|
|||||||
export const initializeEagerServices = async () => {
|
export const initializeEagerServices = async () => {
|
||||||
// Force the creation of services that need to be initialized at startup
|
// Force the creation of services that need to be initialized at startup
|
||||||
container.get(RecordingService);
|
container.get(RecordingService);
|
||||||
await container.get(MeetStorageService).initializeGlobalPreferences();
|
|
||||||
|
// Perform comprehensive health checks before initializing other services
|
||||||
|
const storageService = container.get(MeetStorageService);
|
||||||
|
await storageService.checkStartupHealth();
|
||||||
|
|
||||||
|
// Initialize global preferences after health checks pass
|
||||||
|
await storageService.initializeGlobalPreferences();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -148,4 +148,24 @@ export class ABSStorageProvider implements StorageProvider {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a health check on the Azure Blob Storage provider.
|
||||||
|
*/
|
||||||
|
async checkHealth(): Promise<{ accessible: boolean; bucketExists?: boolean; containerExists?: boolean }> {
|
||||||
|
try {
|
||||||
|
this.logger.debug('Performing ABS storage health check');
|
||||||
|
const healthResult = await this.azureBlobService.checkHealth();
|
||||||
|
return {
|
||||||
|
accessible: healthResult.accessible,
|
||||||
|
containerExists: healthResult.containerExists
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`ABS storage health check failed: ${error}`);
|
||||||
|
return {
|
||||||
|
accessible: false,
|
||||||
|
containerExists: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -287,4 +287,26 @@ export class ABSService {
|
|||||||
|
|
||||||
return `${prefix}/${name}`;
|
return `${prefix}/${name}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Health check for Azure Blob Storage service and container accessibility.
|
||||||
|
* Verifies both service connectivity and container existence.
|
||||||
|
*/
|
||||||
|
async checkHealth(): Promise<{ accessible: boolean; containerExists: boolean }> {
|
||||||
|
try {
|
||||||
|
// Check if we can access the container by checking if it exists
|
||||||
|
const exists = await this.containerClient.exists();
|
||||||
|
|
||||||
|
if (exists) {
|
||||||
|
this.logger.verbose(`ABS health check: service accessible and container '${MEET_AZURE_CONTAINER_NAME}' exists`);
|
||||||
|
return { accessible: true, containerExists: true };
|
||||||
|
} else {
|
||||||
|
this.logger.error(`ABS container '${MEET_AZURE_CONTAINER_NAME}' does not exist`);
|
||||||
|
return { accessible: true, containerExists: false };
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`ABS health check failed: ${error.message}`);
|
||||||
|
return { accessible: false, containerExists: false };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,4 +137,24 @@ export class S3StorageProvider implements StorageProvider {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a health check on the S3 storage provider.
|
||||||
|
*/
|
||||||
|
async checkHealth(): Promise<{ accessible: boolean; bucketExists?: boolean; containerExists?: boolean }> {
|
||||||
|
try {
|
||||||
|
this.logger.debug('Performing S3 storage health check');
|
||||||
|
const healthResult = await this.s3Service.checkHealth();
|
||||||
|
return {
|
||||||
|
accessible: healthResult.accessible,
|
||||||
|
bucketExists: healthResult.bucketExists
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error(`S3 storage health check failed: ${error}`);
|
||||||
|
return {
|
||||||
|
accessible: false,
|
||||||
|
bucketExists: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -233,6 +233,37 @@ export class S3Service {
|
|||||||
this.logger.info('S3 client destroyed');
|
this.logger.info('S3 client destroyed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Health check for S3 service and bucket accessibility.
|
||||||
|
* Verifies both service connectivity and bucket existence.
|
||||||
|
*/
|
||||||
|
async checkHealth(): Promise<{ accessible: boolean; bucketExists: boolean }> {
|
||||||
|
try {
|
||||||
|
// Check if we can access the S3 service by listing objects with a small limit
|
||||||
|
await this.run(
|
||||||
|
new ListObjectsV2Command({
|
||||||
|
Bucket: MEET_S3_BUCKET,
|
||||||
|
MaxKeys: 1
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// If we reach here, both service and bucket are accessible
|
||||||
|
this.logger.verbose(`S3 health check: service accessible and bucket '${MEET_S3_BUCKET}' exists`);
|
||||||
|
return { accessible: true, bucketExists: true };
|
||||||
|
} catch (error: any) {
|
||||||
|
this.logger.error(`S3 health check failed: ${error.message}`);
|
||||||
|
|
||||||
|
// Check if it's a bucket-specific error
|
||||||
|
if (error.name === 'NoSuchBucket') {
|
||||||
|
this.logger.error(`S3 bucket '${MEET_S3_BUCKET}' does not exist`);
|
||||||
|
return { accessible: true, bucketExists: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Service is not accessible
|
||||||
|
return { accessible: false, bucketExists: false };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs the full key for an S3 object by ensuring it includes the specified sub-bucket prefix.
|
* Constructs the full key for an S3 object by ensuring it includes the specified sub-bucket prefix.
|
||||||
* If the provided name already starts with the prefix, it is returned as-is.
|
* If the provided name already starts with the prefix, it is returned as-is.
|
||||||
|
|||||||
@ -93,6 +93,14 @@ export interface StorageProvider {
|
|||||||
* @returns A promise that resolves to a readable stream of the object content
|
* @returns A promise that resolves to a readable stream of the object content
|
||||||
*/
|
*/
|
||||||
getObjectAsStream(key: string, range?: { start: number; end: number }): Promise<Readable>;
|
getObjectAsStream(key: string, range?: { start: number; end: number }): Promise<Readable>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a health check on the storage provider.
|
||||||
|
* Verifies both service connectivity and container/bucket existence.
|
||||||
|
*
|
||||||
|
* @returns A promise that resolves to an object indicating accessibility and container/bucket existence
|
||||||
|
*/
|
||||||
|
checkHealth(): Promise<{ accessible: boolean; bucketExists?: boolean; containerExists?: boolean }>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -67,6 +67,36 @@ export class MeetStorageService<
|
|||||||
this.keyBuilder = keyBuilder;
|
this.keyBuilder = keyBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a health check on the storage system.
|
||||||
|
* Verifies both service connectivity and container/bucket existence.
|
||||||
|
* Terminates the process if storage is not accessible.
|
||||||
|
*/
|
||||||
|
async checkStartupHealth(): Promise<void> {
|
||||||
|
try {
|
||||||
|
this.logger.verbose('Performing storage health check...');
|
||||||
|
|
||||||
|
// Get the underlying storage service to perform health check
|
||||||
|
const isHealthy = await this.storageProvider.checkHealth();
|
||||||
|
|
||||||
|
if (!isHealthy.accessible) {
|
||||||
|
this.logger.error('Storage service is not accessible. Terminating process...');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isHealthy.bucketExists && !isHealthy.containerExists) {
|
||||||
|
this.logger.error('Storage bucket/container does not exist. Terminating process...');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.verbose('Storage health check passed successfully');
|
||||||
|
} catch (error) {
|
||||||
|
this.logger.error('Storage health check failed:', error);
|
||||||
|
this.logger.error('Terminating process due to storage health check failure...');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
// GLOBAL PREFERENCES DOMAIN LOGIC
|
// GLOBAL PREFERENCES DOMAIN LOGIC
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user