Do not use global sessions #361

Merged
merged 9 commits into from Jul 23, 2014

Conversation

Projects
None yet
4 participants
Owner

wallyworld commented Jul 23, 2014

Each time a mongo interaction is performed, the session is copied using session.Copy() to ensure a fresh socket is used if needed. The basis of the change is to remove the "global" mongo collections on state.State and refresh each time one is used. A similar approach is used with the transaction runner.

The changes essentially follow the mgo driver guidelines:
newSession := session.Copy()
defer newSession.Close()

During bootstrap, state.State is created using a session that has not had Login() called. For this case, the session is not copied as there are no stored credentials yet. An authenticated bool is added to state.State for this purpose.

mongo/collections.go
+import "labix.org/v2/mgo"
+
+// CollectionFromName returns a named collection on the specified database,
+// initialised with a new session. Also returned is a close function which is
@davecheney

davecheney Jul 23, 2014

Contributor

is or must be called ? What happens if we fail. Should you use a finalizer to catch failures to call session.Close ?

@wallyworld

wallyworld Jul 23, 2014

Owner

In our test suites, if there are active sockets still around when the tests complete, the test/suite teardown fails with an error. So this catches failures to call close.

replicaset/replicaset_test.go
@@ -181,6 +181,15 @@ func (s *MongoSuite) assertAddRemoveSet(c *gc.C, root *gitjujutesting.MgoInstanc
// two copies of root in the replica set
members = append(members, Member{Address: getAddr(root), Tags: initialTags})
+ // We allow for up to 2m per operation, since Add, Set, etc. call
@davecheney

davecheney Jul 23, 2014

Contributor

2m ? two meters, two million, two minutes ? Please don't abbreviate here

@wallyworld

wallyworld Jul 23, 2014

Owner

'twas a copy and paste, but fixed.

@@ -80,7 +80,7 @@ func (s *stateSuite) TestClientNoNeedToPing(c *gc.C) {
c.Assert(err, gc.IsNil)
}
-func (s *stateSuite) TestAgentConnectionShutsDownWithNoPing(c *gc.C) {
+func (s *pingerSuite) TestAgentConnectionShutsDownWithNoPing(c *gc.C) {
s.PatchValue(apiserver.MaxClientPingInterval, time.Duration(0))
st, _ := s.OpenAPIAsNewMachine(c)
@davecheney

davecheney Jul 23, 2014

Contributor

please handle the error here

@wallyworld

wallyworld Jul 23, 2014

Owner

It's not an error value, but a machine

state/presence/presence.go
+ return
+ }
+ err = fmt.Errorf("%v", v)
+ return
@davecheney

davecheney Jul 23, 2014

Contributor

return is unnecessary here

state/state.go
+ statusesC = "statuses"
+ stateServersC = "stateServers"
+ openedPortsC = "openedPorts"
+ // These collections are used by the mgo transaction runner.
@davecheney

davecheney Jul 23, 2014

Contributor

nit: newline before comment please.

state/state.go
+// If st has been authenticated by having it's database logged in,
+// a new mgo.Session is used.
+func (st *State) txnRunner() (_ jujutxn.Runner, closer func()) {
+ closer = func() {}
@davecheney

davecheney Jul 23, 2014

Contributor

suggestion,

func emptycloser() {}

then return this rather than a function literal.

This may be important because any stack trace or printing of this value will return its name, not _anonfunc_00001 or something unhelpful.

@wallyworld

wallyworld Jul 23, 2014

Owner

Great idea, done.

Contributor

davecheney commented Jul 23, 2014

LGTM. Some minor comments which you can ignore if they are unhelpful

Member

axw commented Jul 23, 2014

LGTM

Owner

wallyworld commented Jul 23, 2014

$$merge$$

Contributor

jujubot commented Jul 23, 2014

Status: merge request accepted. Url: http://juju-ci.vapour.ws:8080/job/github-merge-juju

Contributor

jujubot commented Jul 23, 2014

Build failed: Tests failed
build url: http://juju-ci.vapour.ws:8080/job/github-merge-juju/90

Owner

wallyworld commented Jul 23, 2014

$$merge$$

Contributor

jujubot commented Jul 23, 2014

Status: merge request accepted. Url: http://juju-ci.vapour.ws:8080/job/github-merge-juju

jujubot added a commit that referenced this pull request Jul 23, 2014

Merge pull request #361 from wallyworld/copy-session
Do not use global sessions

Each time a mongo interaction is performed, the session is copied using session.Copy() to ensure a fresh socket is used if needed. The basis of the change is to remove the "global" mongo collections on state.State and refresh each time one is used. A similar approach is used with the transaction runner.

The changes essentially follow the mgo driver guidelines:
newSession := session.Copy()
defer newSession.Close()
<do stuff with newSession>

During bootstrap, state.State is created using a session that has not had Login() called. For this case, the session is not copied as there are no stored credentials yet. An authenticated bool is added to state.State for this purpose.

@jujubot jujubot merged commit b98a000 into juju:master Jul 23, 2014

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment