Permalink
Please sign in to comment.
Browse files
Merge pull request #6028 from babbageclunk/update-mgo
Update mgo dependency This version includes the fixes for the duplicate key error on upsert, which means we don't need the patch any more. [go-mgo/mgo#291](go-mgo/mgo#291) [go-mgo/mgo#316](go-mgo/mgo#316) Add a readme to keep the patches directory alive and explain its use. mgz has made a change to apply_patches.py to ignore any files with a different extension. (Review request: http://reviews.vapour.ws/r/5477/)
- Loading branch information...
Showing
with
14 additions
and 107 deletions.
- +1 −1 dependencies.tsv
- +0 −106 patches/001-mgo.v2-issue-277-fix.diff
- +13 −0 patches/README.md
| @@ -1,106 +0,0 @@ | ||
| -diff --git a/session.go b/session.go | ||
| -index a8ad115..75cb838 100644 | ||
| - | ||
| -This applies the minimal changes to fix the mgo duplicate key error, | ||
| -see https://github.com/go-mgo/mgo/pull/291 and https://github.com/go-mgo/mgo/pull/302 | ||
| - | ||
| -It also includes logging so we can see that the patch is applied. | ||
| - | ||
| -Diff on github: https://github.com/go-mgo/mgo/compare/v2...babbageclunk:fix-277-v2-minimal?expand=1 | ||
| -Generated with "git diff v2..fix-277-v2-minimal" | ||
| - | ||
| -Apply from $GOPATH/src with: patch -p1 < github.com/juju/juju/patches/001-mgo.v2-issue-277-fix.diff | ||
| - | ||
| ---- a/gopkg.in/mgo.v2/session.go | ||
| -+++ b/gopkg.in/mgo.v2/session.go | ||
| -@@ -41,6 +41,7 @@ import ( | ||
| - "sync" | ||
| - "time" | ||
| - | ||
| -+ "github.com/juju/loggo" | ||
| - "gopkg.in/mgo.v2/bson" | ||
| - ) | ||
| - | ||
| -@@ -144,9 +145,18 @@ type Iter struct { | ||
| - var ( | ||
| - ErrNotFound = errors.New("not found") | ||
| - ErrCursor = errors.New("invalid cursor") | ||
| -+ | ||
| -+ logPatchedOnce sync.Once | ||
| -+ logger = loggo.GetLogger("mgo") | ||
| - ) | ||
| - | ||
| --const defaultPrefetch = 0.25 | ||
| -+const ( | ||
| -+ defaultPrefetch = 0.25 | ||
| -+ | ||
| -+ // How many times we will retry an upsert if it produces duplicate | ||
| -+ // key errors. | ||
| -+ maxUpsertRetries = 5 | ||
| -+) | ||
| - | ||
| - // Dial establishes a new session to the cluster identified by the given seed | ||
| - // server(s). The session will enable communication with all of the servers in | ||
| -@@ -410,6 +420,16 @@ func (addr *ServerAddr) TCPAddr() *net.TCPAddr { | ||
| - | ||
| - // DialWithInfo establishes a new session to the cluster identified by info. | ||
| - func DialWithInfo(info *DialInfo) (*Session, error) { | ||
| -+ // This is using loggo because that can be done here in a | ||
| -+ // localised patch, while using mgo's logging would need a change | ||
| -+ // in Juju to call mgo.SetLogger. It's in this short-lived patch | ||
| -+ // as a stop-gap because it's proving difficult to tell if the | ||
| -+ // patch is applied in a running system. If you see it in | ||
| -+ // committed code then something has gone very awry - please | ||
| -+ // complain loudly! (babbageclunk) | ||
| -+ logPatchedOnce.Do(func() { | ||
| -+ logger.Debugf("duplicate key error patch applied") | ||
| -+ }) | ||
| - addrs := make([]string, len(info.Addrs)) | ||
| - for i, addr := range info.Addrs { | ||
| - p := strings.LastIndexAny(addr, "]:") | ||
| -@@ -2478,7 +2498,16 @@ func (c *Collection) Upsert(selector interface{}, update interface{}) (info *Cha | ||
| - Flags: 1, | ||
| - Upsert: true, | ||
| - } | ||
| -- lerr, err := c.writeOp(&op, true) | ||
| -+ var lerr *LastError | ||
| -+ // <= to allow for the first attempt (not a retry). | ||
| -+ for i := 0; i <= maxUpsertRetries; i++ { | ||
| -+ lerr, err = c.writeOp(&op, true) | ||
| -+ // Retry duplicate key errors on upserts. | ||
| -+ // https://docs.mongodb.com/v3.2/reference/method/db.collection.update/#use-unique-indexes | ||
| -+ if !IsDup(err) { | ||
| -+ break | ||
| -+ } | ||
| -+ } | ||
| - if err == nil && lerr != nil { | ||
| - info = &ChangeInfo{} | ||
| - if lerr.UpdatedExisting { | ||
| -@@ -4208,13 +4237,22 @@ func (q *Query) Apply(change Change, result interface{}) (info *ChangeInfo, err | ||
| - session.SetMode(Strong, false) | ||
| - | ||
| - var doc valueResult | ||
| -- err = session.DB(dbname).Run(&cmd, &doc) | ||
| -- if err != nil { | ||
| -- if qerr, ok := err.(*QueryError); ok && qerr.Message == "No matching object found" { | ||
| -- return nil, ErrNotFound | ||
| -+ for retries := 0; ; retries++ { | ||
| -+ err = session.DB(dbname).Run(&cmd, &doc) | ||
| -+ if err != nil { | ||
| -+ if qerr, ok := err.(*QueryError); ok && qerr.Message == "No matching object found" { | ||
| -+ return nil, ErrNotFound | ||
| -+ } | ||
| -+ if change.Upsert && IsDup(err) && retries < maxUpsertRetries { | ||
| -+ // Retry duplicate key errors on upserts. | ||
| -+ // https://docs.mongodb.com/v3.2/reference/method/db.collection.update/#use-unique-indexes | ||
| -+ continue | ||
| -+ } | ||
| -+ return nil, err | ||
| - } | ||
| -- return nil, err | ||
| -+ break // No error, so don't retry. | ||
| - } | ||
| -+ | ||
| - if doc.LastError.N == 0 { | ||
| - return nil, ErrNotFound | ||
| - } |
| @@ -0,0 +1,13 @@ | ||
| +Emergency patches for dependencies | ||
| +================================== | ||
| + | ||
| +Files in this directory named `*.patch` or `*.diff` will be applied to | ||
| +the source tree before building Juju for release. The expectation is | ||
| +that these should be changes that will be accepted upstream, but that | ||
| +we need to apply sooner. | ||
| + | ||
| +They're applied with `$GOPATH/src` as the current directory, and with | ||
| +`-p1` to strip one component off the start of the file path. | ||
| + | ||
| +For more details, see `lp:juju-release-tools/apply_patches.py` or ask | ||
| +babbageclunk or mgz in IRC. |
0 comments on commit
5ac0e25