Implement an "acquire" timeout functionality #61

Closed
kadishmal opened this Issue Feb 18, 2013 · 4 comments

Comments

Projects
None yet
4 participants

I am using node-cubrid, a CUBRID Database driver for Node.js with node-pool.

I have intentionally turned off the database server while having started the Node.js app which uses node-pool. I wanted to check what kind of an error I would receive from node-pool when acquiring a connection. However, node-pool was just hanging in there awaiting for a connection to be established for infinite time. Over 10 minutes has passed now, but node-pool is still not responding.

So, implementing a timeout functionality for acquire would be very useful.

raztus commented Aug 20, 2013

👍 agreed

You can do this in the create method. Perhaps doing something similar in your own code around acquire would work

Create Timeout

var poolModule = require('generic-pool')
var q = require('q')
var pool = poolModule.pool({
  name: 'test-pool',
  create: createFn
})

function createFn(cb) {
  createWithPromise()
   .then(function(item) {
     return cb(null, item)
   })
  .fail(function(err) {
    return cb(err)
  })
}

function createWithPromise() {
  var deferred = q.defer()
  create()
  setTimeout(rejectOnTimeout, 1000)
  return deferred.promise

  function rejectOnTimeout() {
    var error = new Error('timeout reached')
    return deferred.reject(error)
  }
  function create() {
    var item = {}
    // some async thing that might not complete before timeout
   // as an example the deferred.resolve line below is commented out
   // return deferred.resolve(item)
  }
}

Note in the example above how the deferred is never resolved. If the deferred is resolved but after it is rejected, the resolve handler with be a no-op. This is because the q promises library has the very nice property that a promise can only be either resolved or rejected exactly once

Acquire Timeout

var timeoutInMilliseconds = 1000
acquireWithTimeout(timeoutInMilliseconds)
  .then(function(client) {
    console.log('got client')
    // do something with the client here
  })
  .fail(function(err) {
    console.log('failed to get client')
    console.dir(err)
  })

function acquireWithTimeout(timeout) {
  var deferred = q.defer()
  pool.acquireWithPromise()
    .then(function(client) {
      return deferred.resolve(client
    })
  }

  setTimeout(reject, timeout)

  function reject() {
    var error = new Error('timeout reached trying to acquire client from pool')
    return deferred.reject(error)
  } 
}

function acquireWithPromise() {
  var deferred = q.defer()
  pool.acquire(callback)
  return deferred.promise

  function callback(err, client) {
     if (errr) {
      return deferred.reject(err)
    }
    return deferred.resolve(client
  }
}

Right, I think it's best to control this behavior in the factory create function.

kadishmal closed this Jul 28, 2014

The timeout of creating resource is NOT the same as acquire timeout. i.e. the creation of resource is successful, but these resource is insufficient, so we need a timeout setting for acquire. Can we reconsider it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment