Skip to content

Commit

Permalink
1 carga de código do PyTrobot
Browse files Browse the repository at this point in the history
  • Loading branch information
matheuscorteletti-wmtrading committed Oct 11, 2024
1 parent 62802fd commit 650a6d0
Show file tree
Hide file tree
Showing 48 changed files with 1,212 additions and 16 deletions.
21 changes: 21 additions & 0 deletions src/core/decorator/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// core/decorator/config.js
const ConfigManager = require('../feature/configManager');

function Config(configKey, defaultValue = null) {
/**
* Função decoradora para injetar um valor de configuração na função decorada.
*
* @param {string} configKey - Chave da configuração a ser injetada.
* @param {*} [defaultValue=null] - Valor padrão a ser usado se a configuração não for encontrada.
*/
return function (func) {
return function (...args) {
// Obtém o valor da configuração usando o ConfigManager
const configManager = new ConfigManager(); // Supondo que seja um Singleton
const configValue = configManager.getConfig(configKey, defaultValue);

// Injeta o valor da configuração nos argumentos da função
return func(configValue, ...args);
};
};
}
16 changes: 16 additions & 0 deletions src/core/decorator/multithread.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// src\core\decorator\multithread.js
const MultithreadManager = require('../feature/multithreadManager');

function Thread(func) {
/**
* Proxy para o decorador @Thread do PyTRobot.
* Cria uma nova thread (ou worker) para a função decorada.
*/
const multithreadManager = new MultithreadManager();

return function (...args) {
// A função decorada é passada para a execução da thread
const thread = multithreadManager.newThread(() => func(...args));
return thread;
};
}
23 changes: 23 additions & 0 deletions src/core/decorator/sqs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// src\core\decorator\sqs.js
const SQSRegistry = require('../strategy/sqs/sqsRegistry');

function SQS(thread = false) {
/**
* Decorator que registra a classe como um worker SQS, com a opção
* de executar em uma nova thread ou não.
*
* @param {boolean} thread - Indica se a task deve ser executada em uma thread separada.
*/
return function (cls) {
const taskName = `${cls.name}`; // Usamos apenas o nome da classe em JS
const taskRegistry = new SQSRegistry(); // Obtém a instância do TaskRegistry (singleton)

// Armazena a preferência de execução em thread como um atributo da classe
cls.runInThread = thread;

// Registra a task no TaskRegistry
taskRegistry.register(taskName, cls);

return cls; // Retorna a classe sem modificá-la
};
}
25 changes: 25 additions & 0 deletions src/core/decorator/state.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// src\core\decorator\state.js
const StateRegistry = require('../strategy/state/stateRegistry');

function State(nextStateOnSuccess = '_FinisherState', nextStateOnFailure = '_FinisherState') {
/**
* Decorator que registra a classe como um estado.
*
* @param {string} nextStateOnSuccess - Estado subsequente em caso de sucesso.
* @param {string} nextStateOnFailure - Estado subsequente em caso de falha.
*/
return function (cls) {
const stateRegistry = new StateRegistry();
stateRegistry.register(cls, nextStateOnSuccess, nextStateOnFailure);
return cls;
};
}

function First(cls) {
/**
* Decorator que define o estado inicial (primeiro estado).
*/
const stateRegistry = new StateRegistry();
stateRegistry.firstStateName = cls.name; // Define o nome do primeiro estado
return cls;
}
15 changes: 15 additions & 0 deletions src/core/decorator/subprocess.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// core/decorator/subprocess.js
const SubprocessManager = require('../feature/subprocessManager');

function Subprocess(command, captureOutput = true, captureError = true) {
/**
* Função para acessar o SubprocessManager diretamente e executar um subprocesso.
*
* @param {Array<string>} command - Lista de strings contendo o comando a ser executado.
* @param {boolean} [captureOutput=true] - Indica se a saída padrão do subprocesso deve ser capturada.
* @param {boolean} [captureError=true] - Indica se a saída de erro do subprocesso deve ser capturada.
* @returns {Object} Resultado do subprocesso, conforme retornado pelo SubprocessManager.
*/
const subprocessManager = new SubprocessManager();
return subprocessManager.executeSubprocess(command, captureOutput, captureError);
}
117 changes: 117 additions & 0 deletions src/core/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// src\core\index.js
const path = require('path');
const fs = require('fs');
const importModule = require('import-module');
const ConfigManager = require('./feature/configManager');
const MultithreadManager = require('./feature/multithreadManager');
const { SQSStrategy, StateStrategy } = require('./strategy/sqs');
const Singleton = require('./singleton');
const LogManager = require('./utility/logManager');

class JsTRobot {
constructor(directory) {
if (!PyTRobot.instance) {
this.directory = directory || process.argv[2];
this.logger = new LogManager().getLogger('PyTRobot');
this.strategies = [];
this._initialize();
PyTRobot.instance = this;
}
return PyTRobot.instance;
}

_initialize() {
this.loadConfig();
this.loadSrc();
this.multithreadManager = new MultithreadManager();
this._checkAndRegisterStrategies();
}

loadConfig() {
this.configManager = new ConfigManager();
this.configManager.loadConfig(this.directory);
}

loadSrc() {
this.baseDirectory = this.directory;
this.srcPath = path.join(this.directory, 'src');
require('app-module-path').addPath(this.srcPath); // Para adicionar o diretório ao caminho
if (fs.existsSync(this.srcPath)) {
this._importAllFiles();
} else {
throw new Error("'src' directory not found.");
}
}

_importAllFiles() {
const files = fs.readdirSync(this.srcPath);
files.forEach(file => {
if (file.endsWith('.js') && file !== 'index.js') {
try {
importModule(path.join(this.srcPath, file));
} catch (error) {
this.logger.error(`Error importing module ${file}: ${error}`);
}
}
});
}

_checkAndRegisterStrategies() {
const SQSRegistry = require('./strategy/sqs/sqsRegistry');
const StateRegistry = require('./strategy/state/stateRegistry');

const taskRegistry = new SQSRegistry();
const stateRegistry = new StateRegistry();

if (Object.keys(taskRegistry.getAll()).length > 0) {
this.strategies.push(new SQSStrategy());
}
if (Object.keys(stateRegistry.getAll()).length > 0) {
this.strategies.push(new StateStrategy());
}

if (this.strategies.length === 0) {
throw new Error('Nenhuma estratégia registrada ou especificada na configuração.');
}
}

initializeApplication() {
this.strategies.forEach(strategy => strategy.initialize());
}

startApplication() {
const config = this.configManager.getAllConfigs();
const strategyPriority = (config.strategy_priority || 'sqs').toLowerCase();
const startDelay = config.strategy_start_delay || 10;

if (strategyPriority === 'sqs') {
this.strategies.sort(strategy => strategy.constructor.name.toLowerCase() !== 'sqsstrategy');
} else if (strategyPriority === 'state') {
this.strategies.sort(strategy => strategy.constructor.name.toLowerCase() !== 'statestrategy');
}

this.strategies.forEach(strategy => {
strategy.start();
if (startDelay > 0) {
setTimeout(() => strategy.start(), startDelay * 1000);
}
});

this.monitorThreads();
}

stopApplication() {
this.strategies.forEach(strategy => strategy.stop());
}

monitorThreads() {
setInterval(() => {
const activeThreads = this.multithreadManager.getNumberActiveThreads();
if (activeThreads === 0) {
this.logger.info("No active threads, terminating the process...");
this.stopApplication();
process.exit(0);
}
}, 10000);
}
}
20 changes: 20 additions & 0 deletions src/core/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// src\core\main.js
const JsTRobot = require('./index');

function entrypoint() {
if (process.argv.length < 3) {
console.error("Usage: node main.js <project_directory>");
process.exit(1);
}

const directory = process.argv[2];

// Inicializa o JsTRobot
const jstrobot = new JsTRobot(directory);
jstrobot.initializeApplication();
jstrobot.startApplication();
}

if (require.main === module) {
entrypoint();
}
25 changes: 25 additions & 0 deletions src/core/strategy/application_strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// src/core/strategy/applicationStrategy.js
const MultithreadManager = require('../feature/multithreadManager');
const SubprocessManager = require('../feature/subprocessManager');

class ApplicationStrategy {
constructor() {
if (this.constructor === ApplicationStrategy) {
throw new Error("Abstract classes can't be instantiated.");
}
this.multithreadManager = new MultithreadManager();
this.subprocessManager = new SubprocessManager();
}

initialize() {
throw new Error('Method "initialize()" must be implemented.');
}

start() {
throw new Error('Method "start()" must be implemented.');
}

stop() {
throw new Error('Method "stop()" must be implemented.');
}
}
Empty file.
21 changes: 5 additions & 16 deletions src/core/strategy/index.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
// src/core/strategy/index.js

class Strategy {
execute() {
throw new Error('execute() must be implemented');
}
}

class ConcreteStrategyA extends Strategy {
execute() {
console.log('Executing Strategy A');
}
}
const BaseRegistry = require('./base_registry');
const ApplicationStrategy = require('./application_strategy');

module.exports = {
Strategy,
ConcreteStrategyA,
};
BaseRegistry,
ApplicationStrategy,
};
34 changes: 34 additions & 0 deletions src/core/strategy/sqs/baseTask.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// src/core/strategy/sqs/base_task.js
const LogManager = require('../../utility/log_manager'); // Assumindo que você tenha algo semelhante

class BaseTask {
constructor() {
if (this.constructor === BaseTask) {
throw new Error("Abstract classes can't be instantiated.");
}
this.logManager = new LogManager();
this.logger = this.logManager.getLogger('SQS');
}

// Método principal chamado para rodar a task
run(...args) {
// Chama o método de entrada antes de executar a lógica principal
this._onEntry();
this.execute(...args);
}

// Método privado que chama o método on_entry do usuário
_onEntry() {
this.onEntry();
}

// Método abstrato para lógica de entrada
onEntry() {
throw new Error("Method 'onEntry()' must be implemented.");
}

// Método abstrato para lógica principal da task
execute(...args) {
throw new Error("Method 'execute()' must be implemented.");
}
}
17 changes: 17 additions & 0 deletions src/core/strategy/sqs/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// src\core\strategy\sqs\index.js

const BaseTask = require('./baseTask');
const SQSManager = require('./manager');
const SQSMessage = require('./messageBuilder').SQSMessage;
const SQSMessageBuilder = require('./messageBuilder').SQSMessageBuilder;
const SQSRegistry = require('./sqsRegistry');
const SQSStrategy = require('./strategy');

module.exports = {
BaseTask,
SQSManager,
SQSMessage,
SQSMessageBuilder,
SQSRegistry,
SQSStrategy,
};
Loading

0 comments on commit 650a6d0

Please sign in to comment.