0

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)
}
pward
  • 1,049
  • 1
  • 8
  • 17

1 Answers1

0

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.

CrazyCrow
  • 4,125
  • 1
  • 28
  • 39