Création d'une API REST avec Node.js et une base de données Oracle. 2e partie

Partie 2: Création d'une API REST: bases de la base de données


Dans le premier article, vous avez créé un serveur Web, ici vous allez créer un module qui est responsable du démarrage et de l' arrêt du pool de connexion à la base de données à l'aide de node-oracledb . Et ajoutez une fonctionnalité qui simplifie l'exécution des instructions simples en obtenant et en libérant automatiquement les connexions du pool.

Exécution du pool de connexions


Étant donné que node-oracledb est construit au-dessus des bibliothèques clientes OCI, il prend en charge la création de pools OCI côté client et présente d'excellentes caractéristiques de performances. Pour créer un pool de connexions, commencez par créer un nouveau fichier de configuration appelé database.js dans le répertoire config . Copiez et collez le code suivant dans le fichier et enregistrez les modifications.

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

Comme avec le fichier config / webserver.js , ce fichier vous permet de définir certaines propriétés à l'aide de variables d'environnement. L'utilisation de variables d'environnement offre une flexibilité lors du déploiement de l'application dans différents environnements et aide à enregistrer les mots de passe et autres informations sensibles en dehors du code source. Exécutez les commandes suivantes à partir du terminal pour définir les variables d'environnement nécessaires et assurez-vous qu'elles sont disponibles dans les futures sessions du 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 

Vous remarquerez peut-être que poolMin et poolMax étaient identiques et que poolIncrement était défini sur 0. Cela créera un pool de taille fixe qui nécessite moins de ressources de gestion - une bonne idée pour les pools qui obtiennent une utilisation cohérente.

Bien que Node.js soit souvent décrit comme «à thread unique», il dispose d'un pool de threads disponible pour certaines opérations qui bloqueraient autrement le thread principal qui exécute le code JavaScript. Ce pool de threads est utilisé par node-oracledb pour effectuer toutes ses opérations asynchrones, telles que la réception de connexions et l'exécution de code SQL et PL / SQL. Cependant, la taille par défaut du pool de threads est 4. Si vous souhaitez que les 10 connexions du pool fonctionnent simultanément, vous devez augmenter le nombre de threads en conséquence.

La variable d'environnement UV_THREADPOOL_SIZE peut être utilisée pour ajuster la taille du pool de threads. UV_THREADPOOL_SIZE peut être défini avant d'exécuter l'application Node.js ou en interne, mais il doit être défini avant le premier appel à l'aide du pool de threads. Cela est dû au fait que le pool de threads est créé lors de sa première utilisation et après sa création, sa taille est fixe. Ouvrez le fichier index.js à la racine de l'application et ajoutez les lignes suivantes après la première ligne (qui contient le module de serveur 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; 

Maintenant que le pool de threads a la taille appropriée, vous pouvez accéder au module de base de données. Créez un nouveau fichier dans le répertoire des services nommé database.js . Copiez et collez le code suivant dedans et enregistrez les modifications.
 const oracledb = require('oracledb'); const dbConfig = require('../config/database.js'); async function initialize() { const pool = await oracledb.createPool(dbConfig.hrPool); } module.exports.initialize = initialize; 

Ce module présente d'abord node-oracledb et le fichier de configuration. Ensuite, une fonction asynchrone est définie avec le nom initialize, qui est ensuite fourni via l'objet module.exports. La fonction d'initialisation crée un pool de connexions, qui est stocké dans le cache interne des pools de connexions comme pool par défaut.

Vous devez maintenant tout connecter pour que le pool de connexions démarre avant l'ouverture du serveur Web. Revenez à index.js et ajoutez la ligne suivante sous la ligne 1.
 // *** line that requires services/web-server.js is here *** const database = require('./services/database.js'); 

Ajoutez ensuite le bloc try suivant à la fonction stratup, immédiatement avant le bloc try existant qui démarre le serveur 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 *** 

À ce stade, vous pouvez installer node-oracledb et tester le code. Exécutez les commandes suivantes dans un terminal à partir du répertoire hr_app.

 npm install oracledb -s node . 

Si vous voyez des messages indiquant que le module de base de données et le serveur Web sont en cours d'exécution, alors félicitations - votre pool de connexions fonctionne maintenant!

Pool de connexions d'arrêt


Si vous fermez l'application maintenant (en utilisant ctrl + c, comme précédemment), le processus Node.js sera détruit avant la fermeture du pool de connexions. Bien que tous les processus de base de données associés doivent être nettoyés automatiquement, il est préférable de fermer explicitement le pool de connexions avant de quitter le processus Node.js.

Revenez au fichier services / database.js , ajoutez les lignes de code suivantes à la fin et enregistrez les mises à jour.

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

La fonction close utilise la méthode oracledb.getPool () pour obtenir le pool par défaut de manière synchrone, puis appelle la méthode close sur le pool pour le fermer.

Pour appeler la fonction de fermeture au bon moment, ajoutez les lignes de code suivantes au fichier index.js à l'intérieur de la fonction d'arrêt immédiatement après le bloc try existant qui arrête le serveur 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; } 

Si vous redémarrez et fermez à nouveau l'application, vous verrez que le module de base de données est fermé après la fermeture du serveur Web, mais avant la fin du processus.

Simplifiez les opérations CRUD simples


L'exécution de code SQL ou PL / SQL à l'aide de node-oracledb est généralement un processus en trois étapes: obtenir la connexion, exécuter le code, puis libérer la connexion. Si tout ce que vous voulez faire est d'exécuter un seul appel (aucune transaction en plusieurs étapes n'est requise), l'obtention et la libération de la connexion peuvent ressembler à du code standard. J'aime créer une fonction qui exécute les trois opérations en un seul appel. Revenez au fichier services / database.js , ajoutez le code suivant ci-dessous et enregistrez les modifications.

 // *** 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; 

En règle générale, vous n'utiliserez pas le module de base de données dans le module de serveur Web, mais l'ajoutez maintenant pour vérifier qu'il fonctionne correctement. Ouvrez le fichier services / web-server.js et ajoutez la ligne suivante sous les déclarations de constantes existantes en haut.

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

Utilisez ensuite le code suivant pour remplacer l'intégralité du gestionnaire app.get qui répond par «Hello World!» (Les 3 lignes).

 // *** 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}`); }); 

Le nouveau gestionnaire utilise la fonction simpleExecute du module de base de données pour récupérer les valeurs de l'utilisateur actuel et de l'horodatage système de la base de données. Les valeurs sont ensuite utilisées dans le littéral de modèle pour répondre au client avec un message dynamique.

Lancez à nouveau l'application et accédez à localhost: 3000. Vous devriez voir quelque chose comme l'image suivante.

image

Si vous voyez ce message, alors tout fonctionne comme il se doit. Dans l' article suivant, vous continuerez à créer l'API en ajoutant le routage, le contrôleur et la logique de base de données pour la demande GET.

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


All Articles