To put some specifics on it, the internal TXN log watcher is started via:
state/workers.go:
ws.StartWorker(txnLogWorker, func() (worker.Worker, error) {
return watcher.New(st.getTxnLogCollection()), nil
})
But if you look at getTxnLogCollection:
func (st *State) getTxnLogCollection() *mgo.Collection {
return st.session.DB(jujuDB).C(txnLogC)
}
That uses a static "State.session" member. And I cannot find anywhere that calls
\.session.Refresh()
If we wanted to do something like:
func (st *State) getTxnLogCollection() *mgo.Collection {
session := st.session.Copy()
return session.DB(jujuDB).C(txnLogC)
}
We would still need to figure out the lifecycle of that connection, figure out who needs to close it, etc.
So it needs a bit of a rework internally to probably have the worker itself copy the session and/or refresh it if there is an error.
We're probably actually making this worse in 2.3 with the StatePool which ensures that we'll be using the same State objects for longer, and for more purposes. Which is good in the sense we don't redo lots of work, but bad in the sense that any fatal error ends up fatal forever.
To put some specifics on it, the internal TXN log watcher is started via: (txnLogWorker, func() (worker.Worker, error) { New(st. getTxnLogCollec tion()) , nil
state/workers.go:
ws.StartWorker
return watcher.
})
But if you look at getTxnLogCollec tion: tion() *mgo.Collection { DB(jujuDB) .C(txnLogC)
func (st *State) getTxnLogCollec
return st.session.
}
That uses a static "State.session" member. And I cannot find anywhere that calls
\.session.Refresh()
If we wanted to do something like: tion() *mgo.Collection { DB(jujuDB) .C(txnLogC)
func (st *State) getTxnLogCollec
session := st.session.Copy()
return session.
}
We would still need to figure out the lifecycle of that connection, figure out who needs to close it, etc.
So it needs a bit of a rework internally to probably have the worker itself copy the session and/or refresh it if there is an error.
We're probably actually making this worse in 2.3 with the StatePool which ensures that we'll be using the same State objects for longer, and for more purposes. Which is good in the sense we don't redo lots of work, but bad in the sense that any fatal error ends up fatal forever.