diff --git a/data-access/seedwork/services-seedwork-cognitive-search-az/index.ts b/data-access/seedwork/services-seedwork-cognitive-search-az/index.ts index 2fea512e..126befb7 100644 --- a/data-access/seedwork/services-seedwork-cognitive-search-az/index.ts +++ b/data-access/seedwork/services-seedwork-cognitive-search-az/index.ts @@ -16,27 +16,42 @@ export class AzCognitiveSearch implements CognitiveSearchBase { constructor(endpoint: string) { let credentials: TokenCredential; - if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') { - credentials = new DefaultAzureCredential(); - } else if (process.env.MANAGED_IDENTITY_CLIENT_ID !== undefined) { - credentials = new DefaultAzureCredential({ ManangedIdentityClientId: process.env.MANAGED_IDENTITY_CLIENT_ID } as DefaultAzureCredentialOptions); - } else { - credentials = new DefaultAzureCredential(); + try { + if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') { + credentials = new DefaultAzureCredential(); + } else if (process.env.MANAGED_IDENTITY_CLIENT_ID !== undefined) { + credentials = new DefaultAzureCredential({ managedIdentityClientId: process.env.MANAGED_IDENTITY_CLIENT_ID } as DefaultAzureCredentialOptions); + } else { + credentials = new DefaultAzureCredential(); + } + this.client = new SearchIndexClient(endpoint, credentials); + } catch (error) { + const errorMessage = + 'Failed to initialize DefaultAzureCredential. ' + + 'Please ensure you have proper Azure credentials configured. ' + + 'This could be due to missing environment variables, invalid credentials, or network issues.'; + throw new Error(`${errorMessage}\nOriginal error: ${error instanceof Error ? error.message : String(error)}`); } - this.client = new SearchIndexClient(endpoint, credentials); } - private getSearchClient(indexName: string): SearchClient { - let client = this.searchClients.get(indexName); - if (!client) { - client = this.client.getSearchClient(indexName); - this.searchClients.set(indexName, client); + async initializeSearchClients(): Promise { + try { + const indexNames = this.client.listIndexesNames(); + for await (const indexName of indexNames) { + this.searchClients.set(indexName, this.client.getSearchClient(indexName)); + } + } catch (error) { + throw new Error( + `Failed to initialize search clients while listing indexes. This could be due to network issues or insufficient permissions.\nOriginal error: ${ + error instanceof Error ? error.message : String(error) + }` + ); } - return client; } + // check if index exists - async indexExists(indexName: string): Promise { + indexExists(indexName: string): boolean { return this.searchClients.has(indexName); } @@ -48,7 +63,7 @@ export class AzCognitiveSearch implements CognitiveSearchBase { this.searchClients.set(indexDefinition.name, this.client.getSearchClient(indexDefinition.name)); console.log(`Index ${indexDefinition.name} created`); } catch (error) { - throw new Error(`Failed to create index ${indexDefinition.name}: ${error.message}`); + throw new Error(`Failed to create index ${indexDefinition.name}: ${error.message}\nCause: ${error}`); } } } @@ -64,13 +79,13 @@ export class AzCognitiveSearch implements CognitiveSearchBase { console.log(`Index ${indexName} updated`); } } catch (error) { - throw new Error(`Failed to create or update index ${indexName}: ${error.message}`); + throw new Error(`Failed to create or update index ${indexName}: ${error.message}\nCause: ${error}`); } } async search(indexName: string, searchText: string, options?: any): Promise>> { const startTime = new Date(); - const result = await this.getSearchClient(indexName).search(searchText, options); + const result = await this.searchClients.get(indexName).search(searchText, options); console.log(`SearchLibrary took ${new Date().getTime() - startTime.getTime()}ms`); return result; } @@ -79,7 +94,7 @@ export class AzCognitiveSearch implements CognitiveSearchBase { try { await this.searchClients.get(indexName).deleteDocuments([document]); } catch (error) { - throw new Error(`Failed to delete document from index ${indexName}: ${error.message}`); + throw new Error(`Failed to delete document from index ${indexName}: ${error.message}\nCause: ${error}`); } } diff --git a/data-access/seedwork/services-seedwork-cognitive-search-in-memory/index.ts b/data-access/seedwork/services-seedwork-cognitive-search-in-memory/index.ts index 32701e5c..9207e283 100644 --- a/data-access/seedwork/services-seedwork-cognitive-search-in-memory/index.ts +++ b/data-access/seedwork/services-seedwork-cognitive-search-in-memory/index.ts @@ -11,9 +11,9 @@ export interface IMemoryCognitiveSearch { deleteDocument(indexName: string, document: any): Promise; indexDocument(indexName: string, document: any): Promise; search(indexName: string, searchText: string, options?: any): Promise; - indexExists(indexName: string): Promise; + indexExists(indexName: string): boolean; logSearchCollectionIndexMap(): void; - + initializeSearchClients(): Promise } @@ -47,9 +47,9 @@ export class MemoryCognitiveSearch implements IMemoryCognitiveSearch, CognitiveS this.searchCollectionIndexDefinitionMap = new Map(); } initializeSearchClients(): Promise { - throw new Error("Method not implemented."); + throw new Error('Method not implemented.'); } - + deleteIndex(indexName: string): Promise { throw new Error("Method not implemented."); } @@ -92,7 +92,7 @@ export class MemoryCognitiveSearch implements IMemoryCognitiveSearch, CognitiveS } } - async indexExists(indexName: string): Promise { + indexExists(indexName: string): boolean { return this.searchCollectionIndexMap.has(indexName); } } \ No newline at end of file diff --git a/data-access/seedwork/services-seedwork-cognitive-search-interfaces/index.ts b/data-access/seedwork/services-seedwork-cognitive-search-interfaces/index.ts index 6ee71e8b..ebd51d3a 100644 --- a/data-access/seedwork/services-seedwork-cognitive-search-interfaces/index.ts +++ b/data-access/seedwork/services-seedwork-cognitive-search-interfaces/index.ts @@ -8,5 +8,6 @@ export interface CognitiveSearchBase { deleteDocument(indexName: string, document: any): Promise; indexDocument(indexName: string, document: any): Promise; deleteIndex(indexName: string): Promise; - indexExists(indexName: string): Promise; + indexExists(indexName: string): boolean; + initializeSearchClients(): Promise } \ No newline at end of file diff --git a/data-access/src/functions/core/initialize-function-app.ts b/data-access/src/functions/core/initialize-function-app.ts index 3f17044f..ef023a89 100644 --- a/data-access/src/functions/core/initialize-function-app.ts +++ b/data-access/src/functions/core/initialize-function-app.ts @@ -29,7 +29,7 @@ export async function initializeFunctionApp() { await cosmosDbConnection.connect(); // Initialize the infrastructure services - InfrastructureServicesBuilder.initialize(); + await InfrastructureServicesBuilder.initialize(); const infrastructureServices = InfrastructureServicesBuilder.getInstance(); // Initialize the domain diff --git a/data-access/src/infrastructure-services-impl/infrastructure-services-builder.ts b/data-access/src/infrastructure-services-impl/infrastructure-services-builder.ts index 423afa44..07272b53 100644 --- a/data-access/src/infrastructure-services-impl/infrastructure-services-builder.ts +++ b/data-access/src/infrastructure-services-impl/infrastructure-services-builder.ts @@ -15,7 +15,7 @@ import { tryGetEnvVar } from '../../seedwork/utils/get-env-var'; import { PaymentInfrastructureService } from '../app/infrastructure-services/payment'; import { CybersourceImpl } from './payment/cybersource/impl'; -export class InfrastructureServicesBuilder implements InfrastructureServices{ +export class InfrastructureServicesBuilder implements InfrastructureServices { private _vercel: VercelInfrastructureService; private _contentModerator: ContentModeratorInfrastructureService; private _cognitiveSearch: CognitiveSearchInfrastructureService; @@ -23,7 +23,7 @@ export class InfrastructureServicesBuilder implements InfrastructureServices{ private _payment: PaymentInfrastructureService; private _datastore: DatastoreInfrastructureService; private _maps: MapsInfrastructureService; - + private constructor() { this._vercel = this.InitVercel(); this._contentModerator = this.InitContentModerator(); @@ -49,7 +49,7 @@ export class InfrastructureServicesBuilder implements InfrastructureServices{ public get payment(): PaymentInfrastructureService { return this._payment; - } + } public get datastore(): DatastoreInfrastructureService { return this._datastore; @@ -59,7 +59,6 @@ export class InfrastructureServicesBuilder implements InfrastructureServices{ return this._maps; } - private InitContentModerator(): ContentModeratorInfrastructureService { const subscriptionKey = tryGetEnvVar('CONTENT_MODERATOR_SUBSCRIPTION_KEY'); const endpoint = tryGetEnvVar('CONTENT_MODERATOR_ENDPOINT'); @@ -96,13 +95,12 @@ export class InfrastructureServicesBuilder implements InfrastructureServices{ } private static _instance: InfrastructureServicesBuilder; - public static initialize(): void { + public static async initialize(): Promise { if (InfrastructureServicesBuilder._instance) { throw new Error('InfrastructureServicesBuilder is already initialized'); } InfrastructureServicesBuilder._instance = new InfrastructureServicesBuilder(); - - + await InfrastructureServicesBuilder._instance._cognitiveSearch.initializeSearchClients(); } public static getInstance(): InfrastructureServicesBuilder { if (!InfrastructureServicesBuilder._instance) { @@ -110,4 +108,4 @@ export class InfrastructureServicesBuilder implements InfrastructureServices{ } return InfrastructureServicesBuilder._instance; } -} \ No newline at end of file +}