Mercurial > gemma
changeset 201:80dc7bbe97db
Persistent session store: Implemented Do.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Sun, 22 Jul 2018 09:34:45 +0200 |
parents | 8426a92fda00 |
children | dba50c51cda7 |
files | auth/persistent.go |
diffstat | 1 files changed, 75 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/auth/persistent.go Sun Jul 22 09:25:25 2018 +0200 +++ b/auth/persistent.go Sun Jul 22 09:34:45 2018 +0200 @@ -167,9 +167,82 @@ return r.newToken, r.err } +func (pcp *PersistentConnectionPool) trim(conn *Connection) { + + conn.refCount-- + + for { + least := time.Now() + var count int + var oldest *Connection + + for _, con := range pcp.conns { + if con.db != nil && con.refCount <= 0 { + if last := con.last(); last.Before(least) { + least = last + oldest = con + } + count++ + } + } + if count <= maxOpen { + break + } + oldest.close() + } +} + func (pcp *PersistentConnectionPool) Do(token string, fn func(*sql.DB) error) error { - log.Println("Do: Not implemented, yet.") - return nil + + type result struct { + con *Connection + err error + } + + res := make(chan result) + + pcp.cmds <- func(pcp *PersistentConnectionPool) { + con := pcp.conns[token] + if con == nil { + res <- result{err: ErrNoSuchToken} + return + } + con.touch() + // store the session here. The ref counting for + // open db connections is irrelevant for persistence + // as they all come up closed when the system reboots. + pcp.store(token, con) + + if con.db != nil { + con.refCount++ + res <- result{con: con} + return + } + + session := con.session + db, err := opendb(session.User, session.Password) + if err != nil { + res <- result{err: err} + return + } + con.db = db + con.refCount++ + res <- result{con: con} + } + + r := <-res + + if r.err != nil { + return r.err + } + + defer func() { + pcp.cmds <- func(pcp *PersistentConnectionPool) { + pcp.trim(r.con) + } + }() + + return fn(r.con.db) } func (pcp *PersistentConnectionPool) Session(token string) *Session {