feat: [OCISDEV-1031] add opt-in LDAP connection pool#658
Conversation
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
|
@kobergj I copied over the stubbed methods from |
|
ai review |
|
Some additional things: Why are we trying to use a LDAP connection pool as a regular LDAP client?. I'm pretty sure this will end up causing problems. There are several unimplemented methods in the pool that will return errors. This is fine, but the problem is that the client that will be used (either the "real" client or the pool) is set in one place and used in another. Whoever will use the client won't know if he's using the "real" client or the pool, and as such won't know what methods aren't implemented. Why not use the LDAP pool as a pool? Either use a regular LDAP client, or use the LDAP pool, but don't try to use one as another because the behavior is naturally different. You can use a LDAP pool with only one slot if you want (assuming everything works fine) There is a lack of The last thing is that blocking calls aren't common, so they should be explicitly documented to prevent possible issues in the future. It's true that those call are private, but they could be used internally in other places if we need to add new functionality. It would also help to document the expected behavior. |
|
One more point, this epic pointed to 8.0.7. We should work with the fork from |
This is per the acceptance criteria in the ticket:
I followed the same approach here as is done with the existing reconnect implementation. |
|
Does it makes more sense that the checkout and release use a counter instead of slots? You might want to check https://pkg.go.dev/golang.org/x/sync/semaphore as it seems more aligned to what you're trying to do. There is also the |
Add GetLDAPClientWithPool, a bounded pool of authenticated LDAP connections, as a drop-in alternative to the existing single, long-lived reconnecting connection used by the auth/user/group LDAP managers. Connections are dialed and bound lazily on checkout, unhealthy connections are discarded and lazily re-dialed rather than eagerly reconnected, and checkout blocks with a configurable timeout once the pool is exhausted. Disabled by default; enable per backend via pool_enabled (plus pool_size and pool_checkout_timeout) on the LDAP connection config. Signed-off-by: Lukas Hirt <info@hirt.cz>
Retry once on a network error in ConnPool.do, mirroring ConnWithReconnect's existing retry behavior: idle pooled connections aren't health-checked before use, so a connection that went stale while idle would otherwise fail the caller's first operation instead of being transparently recovered. Also: stop leaking the checkout() timer when the semaphore wins the select, simplify GetLastError to not check out a connection just to read a value that's meaningless for a pool, and wire a real logger into GetLDAPClientWithPool so pool dial/checkout debug logging isn't silently discarded. Signed-off-by: Lukas Hirt <info@hirt.cz>
…pool Move Config to its own file, document the pool-size/checkout-timeout defaults, name the dial callback type and document what it does, require the logger at construction instead of via a mutable setter, replace the closed-flag mutex with an atomic bool, log Close() errors on evicted/idle connections, and add GetLDAPClientFromConfig so the auth/user/group LDAP managers no longer duplicate the pool-vs-reconnect branch. Signed-off-by: Lukas Hirt <info@hirt.cz>
ff34346 to
5a9b1a3
Compare
Collapse the TLS/non-TLS DialURL branch in dialLDAP and ConnWithReconnect.ldapConnect into a single call: DialWithTLSConfig(nil) is equivalent to omitting the option, since crypto/tls treats a nil *tls.Config as the zero configuration. Replace ConnPool's channel-based semaphore with golang.org/x/sync/semaphore.Weighted (already a repo dependency), using context.WithTimeout for the checkout deadline instead of a manual timer. Signed-off-by: Lukas Hirt <info@hirt.cz>
Switched Separately, re-surfacing your earlier point about retries not respecting request cancellation (2026-07-16): that's intentionally out of scope for OCISDEV-1031 — retry/backoff behavior (including making it context-aware) is covered by the sibling story OCISDEV-1032, so I'd rather not grow this PR's scope to cover it. Flagging it explicitly here so it doesn't read as an oversight. |
|
Code looks good, but need to fix the tests. 👍 |
wg.Go (sync.WaitGroup.Go) needs go1.25; this branch is rebased onto stable-8.0, which pins go1.24.0 in go.mod, so CI's unit-tests job failed to build the test binary. Use wg.Add/Done with a plain goroutine instead. Signed-off-by: Lukas Hirt <info@hirt.cz>
Add GetLDAPClientWithPool, a bounded pool of authenticated LDAP connections, as a drop-in alternative to the existing single, long-lived reconnecting connection used by the auth/user/group LDAP managers. Connections are dialed and bound lazily on checkout, unhealthy connections are discarded and lazily re-dialed rather than eagerly reconnected, and checkout blocks with a configurable timeout once the pool is exhausted.
Disabled by default; enable per backend via pool_enabled (plus pool_size and pool_checkout_timeout) on the LDAP connection config.