node package manager

@shimataro/resource-manager

Resource Manager for JavaScript

Features

  • open any resources
  • reuse previous resource (singleton)
  • close all resources at a stretch

Where to use

Since JavaScript does not have destructor, resources will not be closed automatically (except memory). This may cause critical problem when it works as a server in particular.

So, generally, resources should be closed each time they become unnecessary. But it might be better to close all resources at the end of the request.

In addition, reusing DB connection might be better for transaction.

How to install

npm install -S @shimataro/resource-manager

Usage (for Express.js)

Register the middleware like this in advance (before using resources).

import ResourceManager from "@shimataro/resource-manager";
 
function middleware(req, res, next) {
    // add resource manager to req
    const objResourceManager = ResourceManager.factory();
    req.objResourceManager = objResourceManager;
 
    // specify the resource name, how to open/close
    objResourceManager.register(
        "mysql",
        (options) => {
            return mysql.createConnection(options);
        },
        (conn) => {
            conn.end();
        });
 
    // close all resources at exit
    res
        .on("close", () => {
            // disconnected
            objResourceManager.close();
        })
        .on("finish", () => {
            // finished
            objResourceManager.close();
        });
    if (res.socket.destroyed) {
        // already disconnected
        objResourceManager.close();
    }
 
    next();
}

You can make closing part brief using on-finished:

import ResourceManager from "@shimataro/resource-manager";
import onFinished from "on-finished";
 
function middleware(req, res, next) {
    // ...
 
    // close all resources at exit
    onFinished(res, () => {
        objResourceManager.close();
    });
 
    next();
}

Open resources like this.

app.get("/", (req, res, next) => {
    // connect to DB
    const conn1 = req.objResourceManager.open("mysql", {/* options 1 */});
 
    // openSingleton() returns single resource when name and options are same.
    // (in this case, conn2_1 and conn2_2 indicate same object)
    const conn2_1 = req.objResourceManager.openSingleton("mysql", {/* options 2 */});
    const conn2_2 = req.objResourceManager.openSingleton("mysql", {/* options 2 */});
 
    // all resources will be closed at the end of request
    res.send("OK");
});

Built-in resources

The following resource names can be used without registering, because they are already defined as "built-in resources".

These resources also release elements by calling close(), so keys of Map or Set will be the target of garbage collection at that point. In other words, you don't need to use WeakMap or WeakSet.

You can also use them as "request-local" collection with openSingleton():

function middleware1(req, res, next) {
    const map1 = req.objResourceManager.openSingleton("map", 1);
    console.log(map1.size); // 0
    map1.set(1, "a");
 
    const map2 = req.objResourceManager.openSingleton("map", 2);
    console.log(map2.size); // 0
    map2.set(2, "b");
 
    next();
}
 
function middleware2(req, res, next) {
    const map1 = req.objResourceManager.openSingleton("map", 1);
    console.log(map1.get(1)); // "a"
    console.log(map1.get(2)); // undefined
 
    const map2 = req.objResourceManager.openSingleton("map", 2);
    console.log(map2.get(1)); // undefined
    console.log(map2.get(2)); // "b"
 
    next();
}

License

MIT License

Copyright

© 2018 shimataro