[RFC] rpc: optional context.Context in methods #8038

Merged
merged 2 commits into from Nov 10, 2017

Conversation

Projects
None yet
4 participants
Member

axw commented Nov 8, 2017

Description of change

This PR adds the capability to include a context.Context parameter in methods exposed via a juju/rpc connection. When the connection is closed or the request completes normally, the context will be cancelled.

The singular/leadership API calls are updated to use the context to cancel lease/leadership claims, rather than relying on the lease managers in state being killed. State.KillWorkers is removed. This change paves the way for moving the API server to the dependency engine, reducing the number of active MongoDB connections we maintain, and simplifying how we thread the state pool through to the introspection worker.

This change will also enable us to introduce OpenTracing calls to the API server, and later the API client.

QA steps

  1. juju bootstrap localhost
  2. juju enable-ha
    (wait)
  3. juju upgrade-juju -m controller --build-agent (forces agents to restart gracefully, exercising server shutdown code)

Documentation changes

None.

Bug reference

None.

Member

axw commented Nov 8, 2017

NOTE: this will not be landing until after we branch for 2.3. I'm not concerned about breakage, but it's an unnecessary risk and can wait.

LGTM in general, modulo a few comments and suggestions. A lot of the changes look to me like they could be made in a separate PR - if this one only had the rpc package changes, things would be clearer, I think.

const friendlyErrMsg = "error blocking on leadership release"
var result params.ErrorResult
+ // TODO(axw) make it possible to plumb a context.Context
@rogpeppe

rogpeppe Nov 8, 2017

Owner

I'm not sure that making it possible to cancel arbitrary requests is a good idea. It would complicate the RPC protocol considerably (9p had cancellation, and it was by far the hardest part of the protocol to get right).

When we have the need for cancellation, it's possible to do what the watchers do - return a separate handle that can be blocked on and cancelled explicitly.

For the time being, perhaps just run the facade call in a separate goroutine and abandon it if we get cancelled - the amount of resources consumed is likely to be pretty small (even smaller on the client side if we resurrected net/rpc's Go method).

@axw

axw Nov 9, 2017

Member

That sounds fine, though I don't see why it would be that hard? Send a message to say "cancel request N", which will just cancel the context for that request. The client doesn't necessarily need to wait for it to be cancelled, just for the request to be acknowledged.

Haven't thought about it too deeply. I'll reword the TODO to be less prescriptive.

@@ -176,6 +182,7 @@ func (conn *Conn) Start() {
conn.mutex.Lock()
@rogpeppe

rogpeppe Nov 8, 2017

Owner

Wouldn't it be more appropriate for this method to take a Context as an argument rather than creating one from scratch? (or perhaps pass the context into NewConn)

@axw

axw Nov 9, 2017

Member

Yes, I'll update to pass it into Start.

+ // request returns.
+ //
+ // TODO(axw) provide a means for clients to cancel a request.
+ ctx, cancel := context.WithCancel(conn.context)
@rogpeppe

rogpeppe Nov 8, 2017

Owner

I wonder if this might not be better inside methodCaller.Call, which would cancel the context a little sooner.

@axw

axw Nov 9, 2017

Member

We're dealing with a MethodCaller interface here, so it would have to be as well as, not instead of. I'll add cancellation in there too.

I like the principal behind this. It looks sound but hard to know of subtle breakages. Would be good to address Rog's comments and land into fb and we can perform some more extensive testing.

axw added some commits Nov 1, 2017

rpc: pass context to methods
Methods may have an optional first parameter of a type
to which context.Context is assignable.

The RPC server has a context which is cancelled when
the connection is closed. We then create a child context
for each new request, which is cancelled when the request
completes.

In future we will want to extend the client so it can
accept a Context to Conn.Call, and send a message to the
server to cancel the request. This will also give us a
way of propagating OpenTracing data.
all: make lease/leadership calls cancellable
We currently rely on a hack to prevent blocking
API calls (waiting for lease/leadership to unblock)
from stopping the API server exiting cleanly. The
hack is to kill all of the workers run inside State.

Ideally we would move the workers outside of State,
but that's easier said than done. This gets us a
little closer to untangling the workers, since this
change will enable the API server to run as a manifold,
taking in the StateTracker's State, without too many
contortions.

@axw axw changed the base branch from develop to state-controller-refactor Nov 10, 2017

Member

axw commented Nov 10, 2017

Rog's comments have been addressed. Retargeted to feature branch, so we can keep progressing this and land after branching for 2.3.

Member

axw commented Nov 10, 2017

$$merge$$

Contributor

jujubot commented Nov 10, 2017

Status: merge request accepted. Url: http://ci.jujucharms.com/job/github-merge-juju

@jujubot jujubot merged commit 9c517c9 into juju:state-controller-refactor Nov 10, 2017

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