Skip to content

Commit

Permalink
Added health module, made tsconfig more strict and fixed upcoming iss…
Browse files Browse the repository at this point in the history
…sues
  • Loading branch information
[email protected] committed May 16, 2024
1 parent 46b0345 commit 19315af
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 40 deletions.
3 changes: 2 additions & 1 deletion src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Module } from '@nestjs/common';
import { EventModule } from './event/event.module';
import { ConfigurationModule } from './configuration/configuration.module';
import { HealthModule } from './health/health.module';

/**
* Main application module.
*/
@Module({
imports: [EventModule, ConfigurationModule],
imports: [EventModule, ConfigurationModule, HealthModule],
})
export class AppModule {}
30 changes: 16 additions & 14 deletions src/configuration/configuration.controller.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { Body, Controller, Get, Param, Put } from '@nestjs/common';
import { ConfigurationService } from './configuration.service';
import { ConfigurationVariable, ConfigurationVariableDefinition, ServiceConfiguration, ServiceReplica } from './entities/service-configuration.entity';
import {
ConfigurationVariable,
ConfigurationVariableDefinition,
ServiceConfiguration,
ServiceReplica,
} from './entities/service-configuration.entity';
import { UpdateVariableDto } from './dto/update-variable.dto';
import { BatchUpdateVariableDto } from './dto/batch-update-variables.dto';

Expand All @@ -9,7 +14,6 @@ import { BatchUpdateVariableDto } from './dto/batch-update-variables.dto';
*/
@Controller('configuration')
export class ConfigurationController {

/**
* Creates an instance of the ConfigurationController class.
* @param configurationService The configuration service.
Expand All @@ -21,7 +25,7 @@ export class ConfigurationController {
* @returns All services configurations.
*/
@Get()
getAllServices(): ServiceConfiguration[] {
getAllServices(): ServiceConfiguration[] {
return this.configurationService.findAllServices();
}

Expand All @@ -41,7 +45,7 @@ export class ConfigurationController {
*/
@Get(':service/defined-variables')
getServiceDefinedVariables(
@Param('service') serviceName: string
@Param('service') serviceName: string,
): ConfigurationVariableDefinition[] {
return this.configurationService.findService(serviceName)
?.variableDefinitions;
Expand All @@ -54,7 +58,7 @@ export class ConfigurationController {
*/
@Get(':service/variables')
getServiceVariables(
@Param('service') serviceName: string
@Param('service') serviceName: string,
): ConfigurationVariable[] {
return this.configurationService.findService(serviceName)?.globalVariables;
}
Expand All @@ -69,13 +73,12 @@ export class ConfigurationController {
return this.configurationService.findService(serviceName)?.replicas;
}


/**
* HTTP Endpoint to update the variables for a specific service.
* @param serviceName - The name of the service.
* @param batchUpdateDto - The DTO containing the variables to be updated.
* @returns The updated service configuration.
*/
*/
@Put(':service/variables')
updateServiceVariables(
@Param('service') serviceName: string,
Expand All @@ -87,13 +90,12 @@ export class ConfigurationController {
);
}


/**
* HTTP Endpoint to retrieve the value of a variable for a specific service.
* @param serviceName - The name of the service.
* @param variableKey - The key of the variable.
* @returns The configuration variable.
*/
*/
@Get(':service/variables/:variable')
getServiceVariable(
@Param('service') serviceName: string,
Expand All @@ -111,7 +113,7 @@ export class ConfigurationController {
* @param variableKey - The key of the variable.
* @param updateDto - The DTO containing the updated value.
* @returns The updated service configuration.
*/
*/
@Put(':service/variables/:variable')
updateServiceVariable(
@Param('service') serviceName: string,
Expand All @@ -133,7 +135,7 @@ export class ConfigurationController {
* @param serviceName - The name of the service.
* @param replicaId - The ID of the replica.
* @returns All variables for the replica.
*/
*/
@Get(':service/replicas/:replica/variables')
getReplicaVariables(
@Param('service') serviceName: string,
Expand All @@ -149,7 +151,7 @@ export class ConfigurationController {
* @param replicaId - The ID of the replica.
* @param batchUpdateDto - The DTO containing the variables to be updated.
* @returns The updated replica configuration.
*/
*/
@Put(':service/replicas/:replica/variables')
updateReplicaVariables(
@Param('service') serviceName: string,
Expand All @@ -169,7 +171,7 @@ export class ConfigurationController {
* @param replicaId - The ID of the replica.
* @param variableKey - The key of the variable.
* @returns The configuration variable.
*/
*/
@Get(':service/replicas/:replica/variables/:variable')
getReplicaVariable(
@Param('service') serviceName: string,
Expand All @@ -190,7 +192,7 @@ export class ConfigurationController {
* @param variableKey - The key of the variable.
* @param updateDto - The DTO containing the updated value.
* @returns The updated replica configuration.
*/
*/
@Put(':service/replicas/:replica/variables/:variable')
updateReplicaVariable(
@Param('service') serviceName: string,
Expand Down
23 changes: 17 additions & 6 deletions src/configuration/configuration.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ export class ServiceConfigurationRepository {
* @throws Error if the service name already exists.
* @returns The created service configuration.
*/
public create(serviceConfiguration: ServiceConfiguration): ServiceConfiguration {
public create(
serviceConfiguration: ServiceConfiguration,
): ServiceConfiguration {
const serviceName = serviceConfiguration.name;
if (this.serviceConfigurations.has(serviceName)) {
throw new Error(`Service configuration with name "${serviceName}" already exists.`);
throw new Error(
`Service configuration with name "${serviceName}" already exists.`,
);
}
this.serviceConfigurations.set(serviceName, serviceConfiguration);
return serviceConfiguration;
Expand All @@ -40,7 +44,9 @@ export class ServiceConfigurationRepository {
public findByName(name: string): ServiceConfiguration {
const service = this.serviceConfigurations.get(name);
if (!service) {
throw new NotFoundException(`Service configuration with name "${name}" not found.`);
throw new NotFoundException(
`Service configuration with name "${name}" not found.`,
);
}
return service;
}
Expand All @@ -60,11 +66,16 @@ export class ServiceConfigurationRepository {
* @returns The updated service configuration
* @throws NotFoundException if the service configuration with the provided name is not found.
*/
public update(name: string, update: Partial<ServiceConfiguration>): ServiceConfiguration {
public update(
name: string,
update: Partial<ServiceConfiguration>,
): ServiceConfiguration {
const serviceConfiguration = this.findByName(name);
if (!serviceConfiguration) {
throw new NotFoundException(`Service configuration with name "${name}" not found.`);
};
throw new NotFoundException(
`Service configuration with name "${name}" not found.`,
);
}
Object.assign(serviceConfiguration, update);
this.serviceConfigurations.set(name, serviceConfiguration);
return serviceConfiguration;
Expand Down
27 changes: 18 additions & 9 deletions src/configuration/configuration.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,10 @@ export class ConfigurationService {
* @param replicaId - The ID of the replica.
*/
heartbeat(serviceName: string, replicaId: string) {
if (!this.serviceRepository.exists(serviceName) && !this.mutex[serviceName]) {
if (
!this.serviceRepository.exists(serviceName) &&
!this.mutex[serviceName]
) {
return this.handleFirstHeartbeat(serviceName, replicaId);
}
const service = this.findService(serviceName);
Expand All @@ -72,7 +75,7 @@ export class ConfigurationService {
try {
return this.addService(serviceName, replicaId);
} catch (error) {
this.logger.error(`{heartbeat} ${error.message}`)
this.logger.error(`{heartbeat} ${error.message}`);
this.mutex[serviceName] = false;
return;
}
Expand All @@ -95,7 +98,9 @@ export class ConfigurationService {
variableDefinitions: [],
};

this.logger.log(`Adding service ${serviceName} with replica ${initialReplicaId}`);
this.logger.log(
`Adding service ${serviceName} with replica ${initialReplicaId}`,
);
this.serviceRepository.create(service);
return this.buildServiceConfiguration(service);
}
Expand Down Expand Up @@ -280,7 +285,7 @@ export class ConfigurationService {
this.eventService.publishConfiguration(serviceName, service.replicas);
return service;
} catch (error) {
this.logger.error(`{batchAddOrUpdateServiceVariables} ${error.message}`)
this.logger.error(`{batchAddOrUpdateServiceVariables} ${error.message}`);
throw error;
}
}
Expand Down Expand Up @@ -313,7 +318,7 @@ export class ConfigurationService {
this.eventService.publishConfiguration(serviceName, [replica]);
return service;
} catch (error) {
this.logger.error(`{batchAddOrUpdateReplicaVariables} ${error.message}`)
this.logger.error(`{batchAddOrUpdateReplicaVariables} ${error.message}`);
throw error;
}
}
Expand All @@ -326,15 +331,19 @@ export class ConfigurationService {
*/
validateVariables(variables: ConfigurationVariable[], serviceName: string) {
const { variableDefinitions } = this.findService(serviceName);
variables.forEach(variable => {
const definition = variableDefinitions.find(def => def.key === variable.key);
variables.forEach((variable) => {
const definition = variableDefinitions.find(
(def) => def.key === variable.key,
);
if (!definition) {
throw new Error(`Variable definition not found for ${variable.key}`);
}
const validate = this.ajv.compile(definition.type);
const valid = validate(variable.value);
if (!valid) {
throw new BadRequestException(`[${variable.key}] Validation failed: ${validate.errors?.map(err => `${err.instancePath} ${err.message}`).join(', ')}`);
throw new BadRequestException(
`[${variable.key}] Validation failed: ${validate.errors?.map((err: any) => `${err.instancePath} ${err.message}`).join(', ')}`,
);
}
});
}
Expand All @@ -346,7 +355,7 @@ export class ConfigurationService {
* @throws NotFoundException if the service is not found.
*/
deleteService(name: string): boolean {
const deleted = this.serviceRepository.delete(name);
const deleted = this.serviceRepository.delete(name);
if (!deleted) {
this.logger.error(`Failed to delete service ${name} as it does not exist`);
throw new NotFoundException(`Service '${name}' not found`);
Expand Down
2 changes: 1 addition & 1 deletion src/configuration/connector.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { VariableDefinitionsDto } from './dto/variable-definitions.dto';
*/
@Injectable()
export class ConnectorService {
private baseUrl:string = 'http://localhost:3500/v1.0/invoke';
private baseUrl: string = 'http://localhost:3500/v1.0/invoke';
constructor(
private readonly logger: Logger,
private readonly httpService: HttpService,
Expand Down
2 changes: 1 addition & 1 deletion src/event/events.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export class EventService {
accumulator[currentConfiguration.key] = currentConfiguration.value;
return accumulator;
},
{},
{} as Record<string, any>,
);
return {
replicaId: replica.id,
Expand Down
18 changes: 18 additions & 0 deletions src/health/health.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { HealthController } from './health.controller';

describe('HealthController', () => {
let controller: HealthController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [HealthController],
}).compile();

controller = module.get<HealthController>(HealthController);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});
});
16 changes: 16 additions & 0 deletions src/health/health.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Controller, Get } from '@nestjs/common';

/**
* Controller for Health checks
*/
@Controller('health')
export class HealthController {
/**
* Returns the health status of the application.
* @returns a JSON including the health status of the application.
*/
@Get()
getHealth(): { status: string } {
return { status: 'OK' };
}
}
10 changes: 10 additions & 0 deletions src/health/health.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { HealthController } from './health.controller';

/**
* Module for health checks.
*/
@Module({
controllers: [HealthController],
})
export class HealthModule {}
6 changes: 0 additions & 6 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@ async function bootstrap() {
app.useBodyParser('json', {
type: ['application/json', 'application/cloudevents+json'],
});
app.enableCors({
origin: ['http://localhost:4200'],
methods: 'GET,PUT',
preflightContinue: false,
optionsSuccessStatus: 204,
});
await app.listen(8080);

app.useLogger(logger);
Expand Down
2 changes: 1 addition & 1 deletion src/shared/pipes/logging-validation.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
*/
@Injectable()
export class LoggingValidationPipe extends ValidationPipe {
constructor(options?) {
constructor(options?: any) {
super(options);
}

Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"incremental": true,
"skipLibCheck": true,
"strictNullChecks": true,
"noImplicitAny": false,
"noImplicitAny": true,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false,
Expand Down

0 comments on commit 19315af

Please sign in to comment.