Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/production' into staging
Browse files Browse the repository at this point in the history
  • Loading branch information
daneryl committed Sep 27, 2024
2 parents ba0db83 + f97774f commit a16ac90
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { DefaultTransactionManager } from 'api/common.v2/database/data_source_defaults';
import { getConnection } from 'api/common.v2/database/getConnectionForCurrentTenant';
import { MongoTemplatesDataSource } from 'api/templates.v2/database/MongoTemplatesDataSource';
import { DefaultTransactionManager } from 'api/common.v2/database/data_source_defaults';
import { DefaultTemplatesDataSource } from 'api/templates.v2/database/data_source_defaults';
import { DefaultEntitiesDataSource } from 'api/entities.v2/database/data_source_defaults';
import { GenerateAutomaticTranslationsCofig } from './GenerateAutomaticTranslationConfig';
import { MongoATConfigDataSource } from './infrastructure/MongoATConfigDataSource';
import { AJVATConfigValidator } from './infrastructure/AJVATConfigValidator';
import { SaveEntityTranslations } from './SaveEntityTranslations';
import { AJVTranslationResultValidator } from './infrastructure/AJVTranslationResultValidator';

const AutomaticTranslationFactory = {
defaultGenerateATConfig() {
Expand All @@ -13,6 +17,15 @@ const AutomaticTranslationFactory = {
new AJVATConfigValidator()
);
},

defaultSaveEntityTranslations() {
const transactionManager = DefaultTransactionManager();
return new SaveEntityTranslations(
DefaultTemplatesDataSource(transactionManager),
DefaultEntitiesDataSource(transactionManager),
new AJVTranslationResultValidator()
);
},
};

export { AutomaticTranslationFactory };
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { tenants } from 'api/tenants';
import { TaskManager } from 'api/services/tasksmanager/TaskManager';
import { ATTranslationResultValidator } from '../../contracts/ATTranslationResultValidator';
import { AJVTranslationResultValidator } from '../../infrastructure/AJVTranslationResultValidator';
import { InvalidATServerResponse } from '../../errors/generateATErrors';
import { AutomaticTranslationFactory } from '../../AutomaticTranslationFactory';

export class ATServiceListener {
static SERVICE_NAME = 'AutomaticTranslation';

private taskManager: TaskManager;

constructor(ATFactory: typeof AutomaticTranslationFactory = AutomaticTranslationFactory) {
const validator: ATTranslationResultValidator = new AJVTranslationResultValidator();
this.taskManager = new TaskManager({
serviceName: ATServiceListener.SERVICE_NAME,
processResults: async result => {
if (!validator.validate(result)) {
throw new InvalidATServerResponse(validator.getErrors()[0]);
}

await tenants.run(async () => {
await ATFactory.defaultSaveEntityTranslations().execute(result);
}, result.key[0]);
},
});
}

start(interval = 500) {
this.taskManager.subscribeToResults(interval);
}

async stop() {
await this.taskManager.stop();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { config } from 'api/config';
import { tenants } from 'api/tenants';
import Redis from 'redis';
import RedisSMQ from 'rsmq';
import waitForExpect from 'wait-for-expect';
import { AutomaticTranslationFactory } from 'api/externalIntegrations.v2/automaticTranslation/AutomaticTranslationFactory';
import { testingEnvironment } from 'api/utils/testingEnvironment';
import { GenerateAutomaticTranslationsCofig } from 'api/externalIntegrations.v2/automaticTranslation/GenerateAutomaticTranslationConfig';
import { SaveEntityTranslations } from 'api/externalIntegrations.v2/automaticTranslation/SaveEntityTranslations';
import { ATServiceListener } from '../ATServiceListener';

const prepareATFactory = (executeSpy: jest.Mock<any, any, any>) => {
const ATFactory: typeof AutomaticTranslationFactory = {
defaultGenerateATConfig() {
return {} as GenerateAutomaticTranslationsCofig;
},
defaultSaveEntityTranslations() {
return { execute: executeSpy } as unknown as SaveEntityTranslations;
},
};

return ATFactory;
};

describe('ATServiceListener', () => {
let listener: ATServiceListener;
let redisClient: Redis.RedisClient;
let redisSMQ: RedisSMQ;
let executeSpy: jest.Mock<any, any, any>;

beforeEach(async () => {
await testingEnvironment.setUp({
settings: [{ features: { automaticTranslation: { active: true } } }],
});
await testingEnvironment.setTenant('tenant');

executeSpy = jest.fn();

listener = new ATServiceListener(prepareATFactory(executeSpy));
const redisUrl = `redis://${config.redis.host}:${config.redis.port}`;
redisClient = Redis.createClient(redisUrl);
redisSMQ = new RedisSMQ({ client: redisClient });

const recreateQueue = async (queueName: string): Promise<void> => {
try {
await redisSMQ.getQueueAttributesAsync({ qname: queueName });
await redisSMQ.deleteQueueAsync({ qname: queueName });
} catch (error: any) {
if (error.name === 'queueNotFound') {
// No action needed
} else {
throw error;
}
}

await redisSMQ.createQueueAsync({ qname: queueName });
};

await recreateQueue('AutomaticTranslation_results').catch(error => {
throw error;
});

listener.start(0);
});

afterAll(async () => {
redisClient.end(true);
await listener.stop();
await testingEnvironment.tearDown();
});

describe('Save Translations', () => {
it('should call on saveEntityTranslations after validating the result', async () => {
const message = {
key: ['tenant', 'sharedId', 'propName'],
text: 'original text',
language_from: 'en',
languages_to: ['es'],
translations: [
{ text: 'texto traducido', language: 'es', success: true, error_message: '' },
],
};

executeSpy.mockClear();

await redisSMQ.sendMessageAsync({
qname: 'AutomaticTranslation_results',
message: JSON.stringify(message),
});

await waitForExpect(async () => {
await tenants.run(async () => {
expect(executeSpy).toHaveBeenCalledWith(message);
}, 'tenant');
});
});
});
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable max-classes-per-file */
export class GenerateATConfigError extends Error {}
export class InvalidInputDataFormat extends Error {}
export class InvalidATServerResponse extends Error {}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "uwazi",
"version": "1.186.0-rc5",
"version": "1.186.0-rc6",
"description": "Uwazi is a free, open-source solution for organising, analysing and publishing your documents.",
"keywords": [
"react"
Expand Down

0 comments on commit a16ac90

Please sign in to comment.