Criando uma API REST com Node.js e um Banco de Dados Oracle. Parte 2

Parte 2: Criando uma API REST: Noções Básicas de Banco de Dados


No primeiro artigo, você criou um servidor Web, aqui você criará um módulo responsável por iniciar e desligar o pool de conexões do banco de dados usando o node-oracledb . E também adicione um recurso que simplifica a execução de instruções simples, obtendo e liberando automaticamente conexões do pool.

Executando conjunto de conexões


Como o node-oracledb é construído sobre as bibliotecas de clientes OCI, ele possui suporte interno para criar pools de OCI que são do lado do cliente e têm excelentes características de desempenho. Para criar um conjunto de conexões, comece criando um novo arquivo de configuração chamado database.js no diretório config . Copie e cole o seguinte código no arquivo e salve as alterações.

module.exports = { hrPool: { user: process.env.HR_USER, password: process.env.HR_PASSWORD, connectString: process.env.HR_CONNECTIONSTRING, poolMin: 10, poolMax: 10, poolIncrement: 0 } }; 

Assim como no arquivo config / webserver.js , esse arquivo permite definir algumas propriedades usando variáveis ​​de ambiente. O uso de variáveis ​​de ambiente fornece flexibilidade ao implantar o aplicativo em diferentes ambientes e ajuda a salvar senhas e outras informações confidenciais fora do código-fonte. Execute os seguintes comandos no terminal para definir as variáveis ​​de ambiente necessárias e verifique se elas estão disponíveis em futuras sessões do terminal.

 echo "export HR_USER=hr" >> ~/.bashrc echo "export HR_PASSWORD=oracle" >> ~/.bashrc echo "export HR_CONNECTIONSTRING=0.0.0.0/orcl" >> ~/.bashrc source ~/.bashrc 

Você pode notar que poolMin e poolMax eram iguais e poolIncrement foi definido como 0. Isso criará um pool de tamanho fixo que requer menos recursos de gerenciamento - uma boa idéia para pools que obtêm uso consistente.

Embora o Node.js seja frequentemente descrito como "single-threaded", ele possui um pool de threads disponível para determinadas operações que, de outra forma, bloqueariam o thread principal que executa o código JavaScript. Esse conjunto de encadeamentos é usado pelo node-oracledb para executar todas as operações assíncronas, como recebimento de conexões e execução de código SQL e PL / SQL. No entanto, o tamanho padrão do conjunto de encadeamentos é 4. Se você deseja que todas as 10 conexões no conjunto funcionem simultaneamente, é necessário aumentar o número de encadeamentos de acordo.

A variável de ambiente UV_THREADPOOL_SIZE pode ser usada para ajustar o tamanho do conjunto de encadeamentos. UV_THREADPOOL_SIZE pode ser definido antes da execução do aplicativo Node.js. ou internamente, mas deve ser definido antes da primeira chamada ser feita usando o conjunto de encadeamentos. Isso ocorre pelo fato de o conjunto de encadeamentos ser criado após o primeiro uso e, após sua criação, seu tamanho ser fixo. Abra o arquivo index.js na raiz do aplicativo e adicione as seguintes linhas após a primeira linha (que contém o módulo do servidor da web).

 // *** line that requires services/web-server.js is here *** const dbConfig = require('./config/database.js'); const defaultThreadPoolSize = 4; // Increase thread pool size by poolMax process.env.UV_THREADPOOL_SIZE = dbConfig.hrPool.poolMax + defaultThreadPoolSize; 

Agora que o conjunto de encadeamentos possui o tamanho apropriado, você pode acessar o módulo de banco de dados. Crie um novo arquivo no diretório de serviços chamado database.js . Copie e cole o código a seguir e salve as alterações.
 const oracledb = require('oracledb'); const dbConfig = require('../config/database.js'); async function initialize() { const pool = await oracledb.createPool(dbConfig.hrPool); } module.exports.initialize = initialize; 

Este módulo apresenta primeiro o nó-oracledb e o arquivo de configuração. Em seguida, uma função assíncrona é definida com o nome initialize, que é fornecido por meio do objeto module.exports. A função de inicialização cria um pool de conexões, que é armazenado no cache interno dos pools de conexões como o pool padrão.

Agora você precisa conectar tudo para que o conjunto de conexões seja iniciado antes da abertura do servidor da web. Volte para index.js e adicione a seguinte linha abaixo da linha 1.
 // *** line that requires services/web-server.js is here *** const database = require('./services/database.js'); 

Em seguida, adicione o seguinte bloco de teste à função de estratificação, imediatamente antes do bloco de teste existente que inicia o servidor da web.

 try { console.log('Initializing database module'); await database.initialize(); } catch (err) { console.error(err); process.exit(1); // Non-zero failure code } // *** existing try block in startup here *** 

Neste ponto, você pode instalar o node-oracledb e testar o código. Execute os seguintes comandos em um terminal no diretório hr_app.

 npm install oracledb -s node . 

Se você vir mensagens de que o módulo do banco de dados e o servidor da web estão em execução, parabéns - seu pool de conexões está funcionando agora!

Pool de conexões de desligamento


Se você fechar o aplicativo agora (usando ctrl + c, como antes), o processo Node.js. será destruído antes do fechamento do pool de conexões. Embora todos os processos relacionados ao banco de dados devam ser limpos automaticamente, é melhor fechar explicitamente o conjunto de conexões antes de sair do processo Node.js.

Retorne ao arquivo services / database.js , adicione as seguintes linhas de código ao final e salve as atualizações.

 // *** previous code above this line *** async function close() { await oracledb.getPool().close(); } module.exports.close = close; 

A função close usa o método oracledb.getPool () para obter o pool padrão de forma síncrona e, em seguida, chama o método close no pool para fechá-lo.

Para chamar a função close no momento certo, adicione as seguintes linhas de código ao arquivo index.js . dentro da função shutdown imediatamente após o bloco try existente que interrompe o servidor da web.

 // *** existing try-catch block in shutdown here *** try { console.log('Closing database module'); await database.close(); } catch (err) { console.log('Encountered error', e); err = err || e; } 

Se você iniciar e fechar o aplicativo novamente, verá que o módulo do banco de dados é fechado após o fechamento do servidor da Web, mas antes da conclusão do processo.

Simplifique as operações simples de CRUD


A execução de código SQL ou PL / SQL usando node-oracledb geralmente é um processo de três etapas: obtenha a conexão, execute o código e libere a conexão. Se tudo o que você quer fazer é fazer uma chamada para executar (nenhuma transação em várias etapas é necessária), então receber e liberar a conexão pode parecer um código padrão. Eu gosto de criar uma função que executa todas as três operações em uma chamada. Retorne ao arquivo services / database.js , adicione o seguinte código abaixo e salve as alterações.

 // *** previous code above this line *** function simpleExecute(statement, binds = [], opts = {}) { return new Promise(async (resolve, reject) => { let conn; opts.outFormat = oracledb.OBJECT; opts.autoCommit = true; try { conn = await oracledb.getConnection(); const result = await conn.execute(statement, binds, opts); resolve(result); } catch (err) { reject(err); } finally { if (conn) { // conn assignment worked, need to close try { await conn.close(); } catch (err) { console.log(err); } } } }); } module.exports.simpleExecute = simpleExecute; 

Normalmente, você não usará o módulo de banco de dados no módulo de servidor da web, mas adicione-o agora para verificar se está funcionando corretamente. Abra o arquivo services / web-server.js e adicione a seguinte linha sob as declarações constantes existentes na parte superior.

 // line that requires ../config/web-server.js here const database = require('./database.js'); 

Em seguida, use o código a seguir para substituir todo o manipulador app.get que responde com "Hello World!" (Todas as 3 linhas).

 // *** line that adds morgan to app here *** app.get('/', async (req, res) => { const result = await database.simpleExecute('select user, systimestamp from dual'); const user = result.rows[0].USER; const date = result.rows[0].SYSTIMESTAMP; res.end(`DB user: ${user}\nDate: ${date}`); }); 

O novo manipulador usa a função simpleExecute do módulo de banco de dados para recuperar os valores do usuário atual e o carimbo de systim do banco de dados. Os valores são usados ​​no literal do modelo para responder ao cliente com uma mensagem dinâmica.

Inicie o aplicativo novamente e vá para localhost: 3000. Você deve ver algo como a imagem a seguir.

imagem

Se você vir esta mensagem, tudo funcionará como deveria. No próximo artigo, você continuará criando a API adicionando a lógica de roteamento, controlador e banco de dados para a solicitação GET.

Source: https://habr.com/ru/post/pt473346/


All Articles