Search code examples
node.jsapinode-oracledboracle18c

Connection pool is never closed with node-oracledb and nodejs


I'm making a little API using Node Js and Oracle, using node-oracledb for that. I have been guided by the following article: API with OracleDB and Node JS

The project files contain the following:

/services/web-server.js

const http = require('http');
const morgan = require('morgan');
const express = require('express');
const webServerConfig = require('../config/web-server');

let httpServer;

function initialize(){
    return new Promise((resolve, reject) => {
        const app = express();
        httpServer = http.createServer(app);

        app.use(morgan('combined'));

        app.get('/', (req, res) => {
            res.end('Hello World');
        });

        httpServer.listen(webServerConfig.port, err => {
            if(err){
                reject(err);
                return;
            }          
            
            console.log(`Web server listening on localhost:${webServerConfig.port}`);

            resolve();
        });
    });
}

module.exports.initialize = initialize;

function close(){
    return new Promise((resolve, reject) => {
        httpServer.close(err => {
            if(err){
                reject(err);
                return;
            }

            resolve();
        });
    });
}

module.exports.close = close;

/services/database.js

const oracledb = require('oracledb');
const dbConfig = require('../config/database');

async function initialize(){
    const pool = await oracledb.createPool(dbConfig.gtsmpPool);
}

module.exports.initialize = initialize;

async function close(){
    await oracledb.getPool().close();
}

module.exports.close = close;

And /index.js

const webServer = require('./services/web-server');
const database = require('./services/database');
const dbConfig = require('./config/database');
const defaultThreadPoolSize = 4;

// Increase thread pool size by poolMax
process.env.UV_THREADPOOL_SIZE = dbConfig.gtsmpPool.poolMax + defaultThreadPoolSize;

async function startup(){
    console.log('Starting application');
    
    try{
        console.log('Initializing database module');

        await database.initialize();
    }catch(err){
        console.error(err);

        process.exit(1);    // Non-zero failure code
    }


    try{
        console.log('Initializing web server module');

        await webServer.initialize();
    }catch(err){
        console.error(err);

        process.exit(1);    // Non-zero failure code
    }
}

startup();

async function shutdown(e){
    let err = e;

    console.log('Shutting down');

    try{
        console.log('Closing web server module');

        await webServer.close();
    }catch(e){
        console.log('Encountered error', e);

        err = err || e;
    }

    console.log('Exiting process');

    try{
        console.log('Closing database module');

        await database.close();
    }catch(err){
        console.log('Encountered error', err);

        err = err || e;
    }

    if(err){
        process.exit(1);    // Non-zero failure code
    }else{
        process.exit(0);
    }
}

process.on('SIGTERM', () => {
    console.log('Received SIGTERM');

    shutdown();
});

process.on('SIGINT', () => {
    console.log('Received SIGINT');

    shutdown();
});
  
process.on('uncaughtException', err => {
    console.log('Uncaught exception');
    console.error(err);

    shutdown(err);
});

/config/database.js

module.exports = {    
    gtsmpPool: {
        user: process.env.GTSMP_USER,
        password: process.env.GTSMP_PASSWORD,
        connectString: process.env.GTSMP_CONNECTIONSTRING,
        poolMin: 10,
        poolMax: 10,
        poolIncrement: 0    
    }
};

The connection to the database is succesful. The problem is that when I want to terminate the application and close the connection pool, the await statement oracledb.getPool().close() never gets resolved and seems to get stuck.

If I try to forcefully finish I get the following messages

Encountered error Error [ERR_SERVER_NOT_RUNNING]: Server is not running.
    at Server.close (net.js:1604:12)
    at Object.onceWrapper (events.js:416:28)
    at Server.emit (events.js:310:20)
    at emitCloseNT (net.js:1657:8)
    at processTicksAndRejections (internal/process/task_queues.js:83:21) {
  code: 'ERR_SERVER_NOT_RUNNING'

And

Encountered error Error: NJS-002: invalid pool

I'm using Oracle 18c XE on docker container, Node v12.16.3 and instantclient_18_5

Any idea how to fix it? Thanks.


Solution

  • There are some notes in the node-oracledb pool example...

        // Get the pool from the pool cache and close it when no
        // connections are in use, or force it closed after 10 seconds.
        // If this hangs, you may need DISABLE_OOB=ON in a sqlnet.ora file.
        // This setting should not be needed if both Oracle Client and Oracle
        // Database are 19c (or later).
        await oracledb.getPool().close(10);