# Net::LDAP connection semantics problem and nested blocks

**URL:** <https://www.ruby-forum.com/t/net-ldap-connection-semantics-problem-and-nested-blocks/74628>\
**Category:** Ruby\
**Created:** [November 7, 2006, 10:50am UTC](https://www.ruby-forum.com/t/net-ldap-connection-semantics-problem-and-nested-blocks/74628 "2006-11-07T10:50:47Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![lukeda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/51bf81/32.png) [@lukeda](https://www.ruby-forum.com/u/lukeda)\
**Post date:** [November 7, 2006, 10:50am UTC](https://www.ruby-forum.com/t/net-ldap-connection-semantics-problem-and-nested-blocks/74628/1 "2006-11-07T10:50:47Z")

</div>

Hi,

I am working with the Net::LDAP library to communicate with active  
directory. The connection semantics of that library are causing me  
problems which I am trying to solve. The library was designed to  
connect and then disconnect from the LDAP server before and after  
each operation. I am running into a problem where the server is  
refusing connections because of too many successive connections.

Some background…

I have a Net::LDAP subclass that among other things, supplies  
credential and connection information to the parent on construction  
based on a single key string that is given.

class MyLDAP \< Net::LDAP

@cache = {}

def self.get(key)  
if @cache.has\_key? key  
@cache[key]  
else  
@cache[key] = CortecsLDAP.new(key)  
end  
end

def initialize(key)  
super self.connect\_details\_for\_key(key)  
end

def self.connect\_details\_for\_key(key)  
# Connect to DB and get details here relating to key  
end

The caching business is because this it is common for 1000+ ldap  
operations to happen in one execution so I thought I was being more  
efficient in holding the connections open like that.

The semantics of Net::LDAP however open and close underling tcp  
connection before and after each operation. Basically making my  
caching obsolete. However, Net::LDAP provides the method open() at  
the class and object level which takes a block and passes a Net::LDAP  
object to the block, keeping its connection open for the duration of  
the block. What I would like to do is be able to hold open all of the  
objects in the cache for the duration of a block. This is probably  
what I would want the interface to look like…

LDAPSession.open do | ldap\_connection\_cache |  
my\_ldap\_instance = ldap\_connection\_cache.get(‘some\_key’)  
my\_other\_ldap\_instance = ldap\_connection\_cache.get(‘some\_other\_key’)  
end

The important thing here is that my\_ldap\_instance and  
my\_other\_ldap\_instance remain open for the whole time they are in the  
block they are in. The only way to keep a Net::LDAP connection open  
is to use the open() method described above and pass it a block.

I hope that makes sense to someone who can help.

Cheers.

---

<div class="post-metadata">

**Author:** ![lukeda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/51bf81/32.png) [@lukeda](https://www.ruby-forum.com/u/lukeda)\
**Post date:** [November 7, 2006, 10:50am UTC](https://www.ruby-forum.com/t/net-ldap-connection-semantics-problem-and-nested-blocks/74628/2 "2006-11-07T10:50:57Z")

</div>

On 10/31/06, Luke D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> Hi,
> 
> I am working with the Net::LDAP library to communicate with active  
> directory. The connection semantics of that library are causing me  
> problems which I am trying to solve. The library was designed to  
> connect and then disconnect from the LDAP server before and after  
> each operation. I am running into a problem where the server is  
> refusing connections because of too many successive connections.

What LDAP operations are you performing here?

---

<div class="post-metadata">

**Author:** ![lukeda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/51bf81/32.png) [@lukeda](https://www.ruby-forum.com/u/lukeda)\
**Post date:** [November 7, 2006, 11:04am UTC](https://www.ruby-forum.com/t/net-ldap-connection-semantics-problem-and-nested-blocks/74628/3 "2006-11-07T11:04:59Z")

</div>

On 01/11/2006, at 3:11 PM, Francis C. wrote:

> What LDAP operations are you performing here?

In the particular case when I hit the problem, it was an attribute  
level modify operation. I realise my original post was extremely hard  
to decipher, I was rather pressed for time when I put it together.

I have a script which consumes ‘jobs’ off a queue. One of the jobs  
may be to update the name details for a particular user in domain a,  
the next to update the phone number in domain b. Therefore opening  
one connection using open() is not an option.

I have thought long and hard about this and I can’t come up with a  
solution. The only way for this to work the way I want would be to  
have a flag that changes the connection model and maybe allows me to  
specify when to open/close the underlying connection. However, I see  
from the in code comments that it was an explicit design decision to  
have the API work the way it does. I do understand the reason for  
this, but it just doesn’t suit my needs for this.

If this is something that you don’t wish too change (quite  
reasonable) I will go back to the other ruby ldap options.

On a side note, your ldap implementation performs very well compared  
to the Perl net::ldap which I was surprised about. It may have been a  
peculiarity of my environment, but when I moved to Perl to get the  
task I needed done, there was a noticeable slow down in processing  
large result sets compared to your ruby implementation.

Cheers.

---

<div class="post-metadata">

**Author:** ![lukeda](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/51bf81/32.png) [@lukeda](https://www.ruby-forum.com/u/lukeda)\
**Post date:** [November 7, 2006, 11:06am UTC](https://www.ruby-forum.com/t/net-ldap-connection-semantics-problem-and-nested-blocks/74628/4 "2006-11-07T11:06:22Z")

</div>

On 11/5/06, Luke D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> may be to update the name details for a particular user in domain a,  
> the next to update the phone number in domain b. Therefore opening  
> one connection using open() is not an option.

In regard to the design decision in the library: it’s essential to be  
able to document and depend on the network behavior of Net::LDAP.  
That’s more important than that it obey one semantics or another. The  
decision came from years of experience with the various  
Michigan-derived C implementations, which try to wrap the connection  
away from the API, which in turn leads to bizarre, hard-to-find bugs.

Why don’t you put your queue consumer inside the Net::LDAP#open block  
and let it run as long as it wants to? You can put multiple #open  
calls on different threads if you have to connect to more than one  
LDAP server. The only thing I would be concerned about is that the  
LDAP servers may time out your connections, but you can manage that by  
putting your own timeout in your Queue-query.
