Created
June 13, 2014 12:04
-
-
Save benbjohnson/a3e9e35f73dae8d15c49 to your computer and use it in GitHub Desktop.
Revisions
-
benbjohnson created this gist
Jun 13, 2014 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,68 @@ package store import ( "fmt" "github.com/boltdb/bolt" ) // reap removes sessions older than a given duration. // This function assumes that all session data is stored in a "sessions" bucket // and the data is organized so the key is the session id and the value is // laid out as: // // -8 bytes- --n bytes-- // timestamp + sessiondata // func reap(db *bolt.DB, duration time.Duration) error { // The batch size represents how many sessions we'll check at // a time for a given transaction. We don't want to check all the // sessions every time because that would lock the database for // too long if the sessions bucket gets too large. batchsz := 1000 var prev []byte for { // Get the current timestamp. now := time.Now() // Iterate over a subset of keys at a time and delete old ones. err := db.Update(func(tx *bolt.Tx) error { c := tx.Bucket([]byte("sessions")).Cursor() var i int for k, v := c.Seek(prev); ; k, v = c.Next() { // If we hit the end of our sessions then exit and start over next time. if k == nil { seek = nil return nil } // If we have iterated over our batch size then save our place // and we'll start from there next time. We need to copy over // the bytes in "k" because it's not guarenteed to exist there // after the transaction is over. if i == batchsz { seek = make([]byte, len(k)) copy(seek, k) return nil } // If we've made it this far then we can check if a session's // timestamp is older than our expiration "duration". If so // then we can delete the item in-place in the cursor. timestamp := time.Unix(int64(binary.BigEndian.Uint64(v)), 0) if now.Since(timestamp) > duration { if err := c.Delete(); err != nil { return fmt.Errorf("delete: %s", err) } } } }) if err != nil { return err } time.Sleep(1 * time.Second) } }