A new release of the mgo MongoDB driver for Go has just been made
available. In addition to improvements and fixes, this release brings
in significant changes to the API in a clean-up to accompain the
upcoming Go 1 release. Such wide changes are not expected to be seen
again anytime soon. The release is compatible with the latest weekly
release (2012-01-20) onwards.
Project details are available at:
The following changes were made in this release. Given that the API
is being broken in a few ways, please pay special attention this
time around.
- The bson package has been moved. Imports of
must be replaced by
Since the package name hasn't changed, no code has to be fixed in
addition to the import line.
New documentation URL:
- Collection, Database and GridFS are now referenced as pointers
everywhere, since the reasons for the prevoius design are gone with
the recent changes in Go. Session's DB method and Database's C
method will also return pointers to a Database and to a Collection,
respectively.
Special attention should be taken with logic such as:
db.Session = db.Session.Clone()
Since DB returns a pointer now, this may be mutating the original
database value, and might have unintended consequences.
Documentation:
http://goneat.org/lp/mgo#Session.DB
http://goneat.org/lp/mgo#Database.C
http://goneat.org/lp/mgo#Database.GridFS
- Collection.DB field was renamed to Database for consistency with
field names everywhere. Documentation:
http://goneat.org/lp/mgo#Collection
- New Database.With and Collection.With methods. These return a
copy of the respective value with the provided session. E.g.:
newc := collection.With(session)
Documentation:
http://goneat.org/lp/mgo#Database.With
http://goneat.org/lp/mgo#Collection.With
- The Mongo function has been replaced by a new Dial function with
improved behavior. Where one has
session, err := mgo.Mongo(mongourl)
it may now be
session, err := mgo.Dial(mongourl)
Even though Dial has the same interface as Mongo, the new function
waits for a server to be available before returning. This avoids the
surprise of a Dial function returning without errors when no servers
were reached yet, and might never be (e.g. wrong url).
Dial waits up to 10 seconds for a server to be reachable before
timing out, and the returned session will by default wait up to one
minute for the availablity of a server on any operation. To
customize the timeout at dial time, a new DialWithTimeout function
was introduced that sets both the dial timeout and the session
timeout. To customize the timeout after dialing, the SetSyncTimeout
may still be used.
The original behavior of the Mongo function was similar to:
session, err := mgo.DialWithTimeout(mongourl, 0)
But it's not exactly equivalent because the logic above will still
block for as long as necessary until a server is reachable, while
the Mongo function would simply return and block at a further
point where communication was attempted.
Documentation:
http://goneat.org/lp/mgo#Dial
http://goneat.org/lp/mgo#DialWithTimeout
- The SetSyncTimeout function now takes a time.Duration rather than
a nanoseconds value. Replace:
session.SetSyncTimeout(10e9)
by one of
session.SetSyncTimeout(10e9 * time.Nanosecond)
session.SetSyncTimeout(10 * time.Second)
Forcing the session to not timeout is still done by:
session.SetSyncTimeout(0)
Note that if you forget to replace an old call, the code will
compile fine, and will actually work correctly due to how the
time.Duration is internally implemented. That said, converting
to the above form is advised for readability.
Documentation:
http://goneat.org/lp/mgo#Session.SetSyncTimeout
- The parameter of Iter's Tail method is now a time.Duration.
A call such as
err := query.Tail(5)
must necessarily be replaced by
err := query.Tail(5 * time.Second)
WARNING: This change requires special attention. The parameter was
previously the number of *seconds* to wait for. If you were using a
call like iter.Tail(5) before, this will still compile, but will do
the wrong thing now. time.Duration is internally maintained as
nanoseconds, so the constant will mean 5 nanoseconds. If you're
using Tail, make sure to review your code rather than simply
attempting to compile.
Documentation:
http://goneat.org/lp/mgo#Query.Tail
- New Find and OpenNext methods on GridFS for comfortable iteration
over a list of files. For example:
iter := gfs.Find(nil).Iter()
var f *mgo.GridFile
for gfs.OpenNext(iter, &f) {
fmt.Printf("Filename: %s\n", f.Name())
}
if iter.Err() != nil {
panic(iter.Err())
}
Documentation:
http://goneat.org/lp/mgo#GridFS.Find
http://goneat.org/lp/mgo#GridFS.OpenNext
- The methods GetInfo and SetInfo of GridFile have been renamed to
GetMeta and SetMeta, to better reflect the field name they're
stored under in the underlying document.
Documentation:
http://goneat.org/lp/mgo#GridFile.GetMeta
http://goneat.org/lp/mgo#GridFile.SetMeta
- The FindRef methods now take a pointer to a DBRef rather than the
value itself, and DBRef's field names have changed to more clearly
indicate their meaning. More details in the documentation:
http://goneat.org/lp/mgo#DBRef
http://goneat.org/lp/mgo#Session.FindRef
http://goneat.org/lp/mgo#Database.FindRef
- Fixed unsafe concurrent access to data in server synchronization
logic as detected by Dmitry Vyukov while using ThreadSanitizer.
- License terms have been fixed in the code. As pointed out in the web
site, the intention was actually simplified BSD (2 clause) rather
than Modified BSD (3 clause).
--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/plus
http://niemeyer.net/twitter
http://niemeyer.net/blog
-- I'm not absolutely sure of anything.
Cheers,
Mathieu
Agreed, that'd be easy enough to setup, and it crossed my mind
actually. I haven't done that because the time window I had for the
release wasn't enough to do all the changes plus all the gofixes for
them. I focused on doing as many of the changes I had in the pipeline
as I could instead, to make sure we don't keep breaking things in
follow up releases, let alone when Go 1 comes out.
I hope the migration isn't too painful. Feedback appreciated when
you go through it.
It actually has a finalize, so I don't think it's a bad idea to have
it per se. That said, I do think it's a bad idea for you to trust it
to be there, for a few different reasons.
For instance, you can't trust the GC to do that for you in a timely
manner, so your program may actually explode because of that
(really!). With that in mind, this is not part of the promises mgo
offers you. It's an internal implementation detail, and may go away
without notice.
So please do Close your sessions appropriately.
As a minor, this change has touched an ambiguity in the way goinstall
handled Launchpad URLs that may cause errors in some cases. This
problem was fixed in the "go get" command that is available in the
latest weekly release, so if you find any issues please use "go get"
instead of goinstall.
Sorry for the trouble.