I want to close an mgo session after it' fully streamed to the client. At first, I thought this might work, but it seems the defer
just waits until the the func begins to return or something.
func (c App) OpenFile(fileId string) revel.Result {
// convert string to bson.ObjectId
objId := bson.ObjectIdHex(fileId)
file, session := OpenFile(objId)
defer session.Close()
// memfile io.Reader, filename string, delivery ContentDisposition, modtime time.Time
var now = time.Now()
return c.RenderBinary(file, "filename", "inline", now)
}
I have no idea what your OpenFile
function doing but I assume it using Mongo's GridFS to access the file. You are right defer session.Close()
is called right before the return. If you use file Revel closes it automatically but in your case, you also want to close the session.
The only one way around it is to make custom Reader that can be used by Revel in RenderBinary
. Something like:
package main
import (
"io"
"os"
"gopkg.in/mgo.v2"
)
type MongoReader struct {
io.Reader
File *os.File
Session *mgo.Session
}
func (mr *MongoReader) Read(p []byte) (n int, e error) {
return mr.File.Read(p)
}
func (mr *MongoReader) Close() {
mr.File.Close()
mr.Session.Close()
}
func main() {
mr := MongoReader{}
mr.Session, mr.File = OpenFile("abababa")
return c.RenderBinary(mr, "filename", "inline", now)
}
I didn't test it on Revel but as code is quite simple I think it should work. Maybe you will need some os.File
specific methods.