-
Notifications
You must be signed in to change notification settings - Fork 127
add ldappool module #582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add ldappool module #582
Conversation
2dca347
to
665dc81
Compare
@droideck Hi sorry to bother you. The tests fail with I double checked and I am not referencing any shebang interpreter so I wonder what can I do to get the unittests run, fix them until everything show's successs to get the PR finally discussed and worth being considered ? All the best and kind regards |
Hi! Regarding this PR, could you share a bit about the motivation behind adding this new |
Sure, I did want to put up that for the discussion but I am sure it's also good to have it in here. The motivation for the module is coming from an application which utilizes the LDAP connections in an context manner when objects are created. With adding an connection pool, the behavior can be changed in a manner of avoiding cost-intensive LDAP(s) connection being created over and over and with the builtin lock-authenticate-unlock method the waste of adding yet another connection to verify user authentication is granted. The ldappool module shall abstract the burdens of connection handling, prewarming, ondemand creation as well as basic authentication of users when search by a generic binddn. For some numbers, the application I am talking about does provide a docker v2 API and calling 100 failing docker auth requests ends up with ~900+ LDAP connections being created and dropped. The module shows that this can also be done with a fixed set of connections avoiding session/connection limits and improving the duration for such events (not talking about the fail delay response for secrutiy obfuscation) from tcp/tls connection establish point of view. I also decided to not use threading Queues as they do not give the possibility to choose a Hope it helps solving other similar issues in the python-ldap world |
@michaelalang, thanks for the great write-up! It makes sense, and I think it can be useful for many cases! @mistotebe could you please check the idea too, please? I think you worked on connection wrappers at some point (not exactly like this one, but still, we need your point of view here...) |
From my experience with the OpenLDAP load balancer interacting with various pooling implementations, the following are useful when you need a connection pool:
Also think the implementation could be greatly simplified if the |
He @mistotebe thanks for your input and support, in regards to
I am not trying to add yet another LDAPObject. The methods implemented are for the specific use case of utilizing one connection with a search principal and and authentication principal. All the other methods should only relate to the Pool. The other points you mentioned are a I also wouldn't see how this should be working out as a pool retuned connection with server controls set on paging will not reset if someone just does a simple_s on it ... Anyways, thanks again for the great input. From the code I submitted, what exactly would you change in regards to the mentioned points ? (@droideck I think that question is for you unless @mistotebe wants to answer too) |
@droideck anything I can do to help getting a go or no go decision ? Not talking about merging but if no go, we would need to look for alternatives of the concept somehow ... |
@mistotebe anything I can do to get this PR progressing ? |
@droideck @mistotebe any way to get an update on the request ? |
After reviewing the code and thinking more on the subject, I don't think this should be added to python-ldap in its current form. It covers one specific use case, which is valid but niche. And to cover a lot of pooling cases for different kinds of applications, it will be enormous work (and it will require a lot of support from us). To name a few: toggble connection affinity support, batch processors need long-lived connections, async applications might need completely different approaches, etc. There are other alternatives already for some cases, as far as I know (django-ldap, flask-ldapconn, HAProxy as an external force) Could we make something simple like this below, maybe? class PoolableLDAPObject(LDAPObject):
"""Base class that makes LDAPObject pooling-friendly"""
def reset_session_state(self):
"""Reset any session-specific state for pool reuse"""
# Abandon pending operations
# Clear controls
# Reset to base bind
pass
def validate_connection(self):
"""Check if connection is still valid"""
try:
self.whoami_s()
return True
except:
return False This would let users build their own pooling while python-ldap stays focused on the things it does best. @michaelalang @mistotebe What do you think? |
@droideck I am not sure to understand what you mean with it covers one use case ? ... I am fine with this PR being rejected it's just annoying that it takes 8 months to get to such a conclusion ... |
@michaelalang sorry, I have not had much time to review in more detail. My concerns (if this were to be considered):
|
I didn't mean you in particular with my frustration on the timing ...
because the Connection should be what is put into
sorry, if that's confusing I can change that to normal calls ... just find that more convinient if no parameters are expected on a method anyway.
the locking only ensure's authentication calls are not being interrupted like Event though the context should return the connections to the pool, let's just assume someone did not use a context and had connection 3 grabbed. Sharing is not meant in a one simple_s call on one thread and the next thread calls simple_s on the same connection but within/from a different context.
more than fine to remove that ... was more convenient to handle response
not sure what you mean by that ...
I think that merges with the does this help ? And for the |
I'm also sorry that we didn't spend enough time with the PR sooner. I can see you've learned a lot through this process, and that kind of exploration is valuable for the community even when the code doesn't land in core. Regarding the topic, connection pooling is indeed valuable, but it's a complex topic that requires a lot of testing, iteration, and correct application. And this PR needs a lot of work as noted by @mistotebe (I'll leave it to him to answer your replies, as he has more experience on the subject). I'd suggest (if you are interested in the topic) to develop this as a separate package (perhaps
Once it's battle-tested and widely used, we could revisit integration or at least recommend it in our documentation. For python-ldap itself, we might consider adding minimal pooling-friendly features (like a |
all good and understand ... please close the PR accordingly :) |
No you're right, sorry, my wires got crossed and somehow thought that a
A lock on the pool to not hand out the same connection twice makes sense (but I thought the interpreter concurrency model shouldn't really make it possible?) However your code has locks on the connection as well? Just like I feel the pool management code should be part of the pool class (e.g.
Looking at your code, I'm not sure how that's achieved, since
Sure, but to have a pool (with reusable connections) you want a way to signal to the code this needs to be done. Unless you're doing it unconditionally for all case, would happen either as you're asking for a new connection (like having different endpoints |
I would like to add ldappooling capability to the library.
LDAP Pooling example
entries as dict
changing the connection or credentials for the pool