Open mirza-ali-ctct opened 2 years ago
As of now, there's no method implemented for connection pooling. You can setup a simple connection pool yourself with just an array or even a channel.
The one thing that it hard to manage is to determine when a connection has been abandoned by the directory server. On Active Directory for example, when enabled the server can simply close the underyling TCP connection. This ends the reader
loop, which then triggers the deferred function to call conn.Close()
.
To put it simply: Before using a pooled connection, run conn.IsClosing()
to see if the connection is already rendered unusable. Here's a very simple, untested way you could try:
package main
import (
"fmt"
"github.com/go-ldap/ldap"
"log"
"sync"
)
// This channel will later hold all pooled connections
// 1024 is the max. number of objects the channel can hold
// until it blocks.
var connectionPool = make(chan *ldap.Conn, 1024)
func getConnection(dialURL string) (conn *ldap.Conn, err error) {
select {
case conn = <-connectionPool:
if conn.IsClosing() {
// The connection is already closing and unusable at this point
// Retry one more time
return getConnection(dialURL)
}
default:
// When there's no object to retrieve from the channel, create
// a new one
conn, err = ldap.DialURL(dialURL)
}
return
}
func putConnection(conn *ldap.Conn) {
select {
case connectionPool <- conn:
// Try to put the connection back into the pool
default:
// Connection pool is full, close and discard connection
fmt.Println("Connection closed since pool is full")
conn.Close()
}
}
func main() {
wg := &sync.WaitGroup{}
wg.Add(5)
for n := 0; n < 5; n++ {
go func(n int) {
for i := 0; i < 1024; i++ {
search()
}
wg.Done()
}(n)
}
wg.Wait()
log.Printf("%#v len: %d", connectionPool, len(connectionPool))
}
func search() {
conn, err := getConnection("ldap://192.168.1.1:389")
if err != nil {
log.Fatalln(err)
}
defer putConnection(conn)
conn.Bind("administrator@pusch.local", "")
type User struct {
DN string `ldap:"dn"`
CN string `ldap:"cn"`
UserAccountControl int `ldap:"userAccountControl"`
}
result, err := conn.Search(&ldap.SearchRequest{
BaseDN: "dc=pusch,dc=local",
Scope: ldap.ScopeWholeSubtree,
DerefAliases: ldap.NeverDerefAliases,
Filter: "(mail=john.doe@pusch.local)",
Attributes: []string{"cn", "mail", "userAccountControl"},
})
if err != nil {
log.Fatalln(err)
}
targetUser := &User{}
if err = result.Entries[0].Unmarshal(targetUser); err != nil {
log.Fatalln(err)
}
}
Looking forward to progress in this regard
Thanks @eryajf . You can close this request
You can close this request
Is there any elegant plan?
@mirza-ali-ctct Now, you can try this. https://github.com/eryajf/ldapool
Is it possible to allow connection in the
Dial
call or is there an equivalent function for connection pooling when making ldap calls?