coopernurse / node-pool

Generic resource pooling for node.js
2.37k stars 259 forks source link

How to delete a resource from the pool? #241

Open PertapaCode opened 5 years ago

PertapaCode commented 5 years ago

I'm using node-pool to handle multiple socket connections, when the connection goes down I need to be able to delete the socket resource from the pool, but looks like node-pool lacks this API.

I know pool.destroy will destroy the resource but this just works for previously borrowed resources which is not the case.

Is there any way to delete a resource from the pool that has not been previously borrowed?

sandfox commented 5 years ago

The only way out-of-the-box I think to do with would be to create a custom evictor that periodically checks the status of each connection in the pool and deletes anything that fails whatever check you specify.

As long as you create an Evictor class that has an instance method of evictthat accepts (poolConfig, resourceToCheck, availableObjectsCount) and returns a boolean, false to keep the resource and true to destroy the resource, it should be ok.

see https://github.com/coopernurse/node-pool/blob/master/lib/DefaultEvictor.js


const { Pool, Deque, PriorityQueue } = require("generic-pool")

class MyEvictor {
  evict: (config, resource, availableObjectsCount) {
    return resource.conn_status != "alive"
  }
}

const createPool = (factory, config) => {
  return new Pool(MyEvictor, Deque, PriorityQueue, factory, config);
}

// usual generic-pool style usage

const myPool = createPool({/* factory object */, /* config */}

The evictor is however limited to synchronously testing functions which may be too restrictive for you?

fbretel-cn commented 5 years ago

@PertapaCode not sure it applies to your use case, but I could solve mine using in the factory's validate():

const validator = instance => Promise.resolve(true)

const factory = {
  create: () => puppeteer.launch({...puppeteerLaunchArgs}).then(instance => {
    instance.disconnectionCount = 0;
    instance.on('disconnected', async () => {
      console.error(`Browser instance disconnected: ${instance.wsEndpoint()}`);
      instance.disconnectionCount += 1;
    });
    return instance;
  }),
  destroy: (instance) => {
    instance.close();
  },
  validate: (instance) => {
    return validator(instance)
      .then(valid => Promise.resolve(valid && instance.disconnectionCount === 0));
  },
};