Skip to content

Commit

Permalink
adding the endpoint to retrieve the fflags
Browse files Browse the repository at this point in the history
  • Loading branch information
alexjavabraz committed Dec 12, 2023
1 parent 6d33dae commit 0c1935c
Show file tree
Hide file tree
Showing 10 changed files with 281 additions and 0 deletions.
22 changes: 22 additions & 0 deletions src/__tests__/unit/features.controller.unit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
expect, stubExpressContext,
} from '@loopback/testlab';
import { FeaturesController } from '../../controllers/features.controller';
import { FeaturesDataService } from '../../services';

describe('FeaturesController (unit)', () => {
const mockedService = <FeaturesDataService>{};
let context = stubExpressContext();


describe('get()',() => {
it('retrieves the features flags Information', async() => {
const controller = new FeaturesController(context.response, mockedService);
await controller.get();
let result = await context.result;
expect(result.payload).not.null();
});
});

});

68 changes: 68 additions & 0 deletions src/controllers/features.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { inject } from '@loopback/core';
import { getLogger, Logger } from 'log4js';
import { RestBindings, get, getModelSchemaRef, Response, } from '@loopback/rest';
import { ServicesBindings } from '../dependency-injection-bindings';
import { FeaturesDataService } from '../services/features-data.service';
import { FeaturesDbDataModel } from '../models/features-data.model';

export class FeaturesController {
logger: Logger;
private featuresDatService: FeaturesDataService;
HTTP_SUCCESS_OK = 200;
HTTP_ERROR = 500;
constructor(
@inject(RestBindings.Http.RESPONSE) private response: Response,
@inject(ServicesBindings.FEATURES_SERVICE)
featuresDatService: FeaturesDataService,
) {
this.featuresDatService = featuresDatService;
this.logger = getLogger('features-controller');
}

@get('/features', {
responses: {
'200': {
description: 'Get the feature flags info',
content: {
'application/json': {
schema: {
type: 'array',
items: getModelSchemaRef(FeaturesDbDataModel, {
includeRelations: true,
}),
},
},
},
},
'500': {
description: 'Could not retrieve the features',
content: {
'application/json': {
schema: {
type: 'array',
items: getModelSchemaRef(FeaturesDbDataModel, {
includeRelations: true,
}),
},
},
},
},
},
})
public async get(): Promise<Response> {
this.logger.debug('[get] started');
let retorno = [new FeaturesDbDataModel()];
let responseCode = this.HTTP_ERROR;
try {
retorno = await this.featuresDatService.getAll();
responseCode = this.HTTP_SUCCESS_OK;
this.logger.info(`[get] Retrieved the features: ${retorno}`);
} catch (e) {
this.logger.warn(`[get] Got an error: ${e}`);
}
this.response.contentType('application/json').status(responseCode).send(
retorno
);
return this.response;
}
}
1 change: 1 addition & 0 deletions src/dependency-injection-bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,5 @@ export const ServicesBindings = {
PEGOUT_STATUS_SERVICE: 'services.PegoutStatusService',
UTXO_PROVIDER_SERVICE: 'services.UtxoProvider',
REGISTER_SERVICE: 'services.RegisterService',
FEATURES_SERVICE: 'services.FeaturesDataService',
};
6 changes: 6 additions & 0 deletions src/dependency-injection-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {RskChainSyncService} from './services/rsk-chain-sync.service';
import {RskNodeService} from './services/rsk-node.service';
import {SyncStatusMongoService} from './services/sync-status-mongo.service';
import { PegoutDataProcessor } from './services/pegout-data.processor';
import { FeaturesMongoDbDataService } from './services/features-mongo.service';

export class DependencyInjectionHandler {
public static configureDependencies(app: Application): void {
Expand Down Expand Up @@ -153,5 +154,10 @@ export class DependencyInjectionHandler {
.bind(ServicesBindings.REGISTER_SERVICE)
.toClass(RegisterService)
.inScope(BindingScope.SINGLETON);

app
.bind(ServicesBindings.FEATURES_SERVICE)
.toClass(FeaturesMongoDbDataService)
.inScope(BindingScope.SINGLETON);
}
}
72 changes: 72 additions & 0 deletions src/models/features-data.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { SearchableModel } from "./rsk/searchable-model";
import {Entity, model, property} from '@loopback/repository';

export interface FeaturesDataModel {
creationDate: Date;
lastUpdateDate: Date;
name: string;
value: string;
version: number;
}

export class FeaturesAppDataModel implements FeaturesDataModel{
constructor(data?: Partial<FeaturesAppDataModel>) {
Object.assign(this, data);
}

creationDate: Date;
lastUpdateDate: Date;
name: string;
value: string;
version: number;
}

@model({settings: {strict: false}})
export class FeaturesDbDataModel implements SearchableModel, FeaturesDataModel {

@property({
type: 'date',
defaultFn: 'now'
})
creationDate: Date;

@property({
type: 'date',
defaultFn: 'now'
})
lastUpdateDate: Date;

@property({
type: 'string',
})
name: string;

@property({
type: 'string',
})
value: string;

@property({
type: 'number',
})
version: number;

getId() {
return this.name;
}
getIdFieldName(): string {
return 'name';
}

public static clone(other: FeaturesDbDataModel): FeaturesDbDataModel {
const features: FeaturesDbDataModel = new FeaturesDbDataModel();
features.creationDate = other.creationDate;
features.lastUpdateDate = other.lastUpdateDate;
features.name = other.name;
features.value = other.value;
features.version = other.version;
return features;
}

}

56 changes: 56 additions & 0 deletions src/models/features.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {Entity, model, property} from '@loopback/repository';


export class Features extends Entity {

@property({
type: 'date',
defaultFn: 'now'
})
creationDate: Date;

@property({
type: 'date',
defaultFn: 'now'
})
lastUpdateDate: Date;

@property({
type: 'string',
})
name: string;

@property({
type: 'string',
})
value: string;

@property({
type: 'number',
})
version: number;

@property({
type: 'number',
id: true,
generated: true,
})
id?: number;

// Define well-known properties here

// Indexer property to allow additional data
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[prop: string]: any;

constructor(data?: Partial<Features>) {
super(data);
}
getIdFieldName(): string {
return 'id';
}
getId() {
return this.id;
}

}
1 change: 1 addition & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export * from '../models/rsk/sync-status.model';
export *from '../models/btc-last-block.model';
export * from './fee-amount.model';
export * from './register-payload.model';
export * from './features.model';
6 changes: 6 additions & 0 deletions src/services/features-data.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { GenericDataService } from './generic-data-service';
import { FeaturesDbDataModel } from '../models/features-data.model';

export interface FeaturesDataService extends GenericDataService<FeaturesDbDataModel> {
getAll(): Promise<FeaturesDbDataModel[]>;
}
48 changes: 48 additions & 0 deletions src/services/features-mongo.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-floating-promises */
import mongoose from 'mongoose';
import { FeaturesDataService } from './features-data.service';
import {FeaturesDbDataModel} from '../models/features-data.model';
import {MongoDbDataService} from '../services/mongodb-data.service';

/*
- THESE MODEL INTERFACES AND CLASSES ARE REQUIRED FOR MONGO BUT WE DON'T WANT THEM EXPOSED OUT OF THIS LAYER
*/
interface FeaturesMongoModel extends mongoose.Document, FeaturesDbDataModel {
}

const FeaturesSchema = new mongoose.Schema({
creationDate: {type: Date},
lastUpdateDate: {type: Date},
name: {type: String, required: true},
value: {type: String, required: true},
version: {type: Number, required: true},
});

const FeaturesConnector = mongoose.model<FeaturesMongoModel>("Features", FeaturesSchema);

export class FeaturesMongoDbDataService extends MongoDbDataService<FeaturesDbDataModel, FeaturesMongoModel> implements FeaturesDataService {
protected getByIdFilter(id: any) {
throw new Error('Method not implemented.');
}
protected getManyFilter(filter?: any) {
throw new Error('Method not implemented.');
}
protected getLoggerName(): string {
return 'FeaturesMongoService';
}
protected getConnector(): mongoose.Model<FeaturesMongoModel, {}, {}> {
this.verifyAndCreateConnectionIfIsNecessary();
return FeaturesConnector;
}
async verifyAndCreateConnectionIfIsNecessary() {
await this.ensureConnection();
}
public async getAll(): Promise<FeaturesDbDataModel[]> {
const documents = await this.getConnector()
.find({})
.exec();
return documents.map(FeaturesDbDataModel.clone);
}

}
1 change: 1 addition & 0 deletions src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export * from './btc-last-block.service';
export * from './sync-status-data.service';
export * from './rsk-node.service';
export * from './register.service';
export * from './features-data.service';

0 comments on commit 0c1935c

Please sign in to comment.