   go []
 
 sendMessage :: req -> Rpc req resp ()
-sendMessage o = do
-  crw <- askCrw
+sendMessage req = do
+  abortIfStatus
   encoder <- askEncoder
-  x <- joinReply =<< liftIO (encoder o)
-  joinReply =<< liftIO (clientWrite crw x)
+  bs <- joinReply =<< liftIO (encoder req)
+  joinClientRWOp (\crw -> clientWrite crw bs)
 
 sendHalfClose :: Rpc req resp ()
 sendHalfClose = do
-  crw <- askCrw
-  joinReply =<< liftIO (clientSendHalfClose crw)
+  abortIfStatus
+  joinClientRWOp clientSendHalfClose
 
 closeCall :: Rpc req resp ()
-closeCall = do
-  crw <- askCrw
-  liftIO (clientClose crw)
+closeCall =
+  clientRWOp clientClose
 
 data RpcReply a
   = RpcOk a


clientWaitForStatus :: ClientReaderWriter -> IO (RpcReply RpcStatus)
clientWaitForStatus crw@(ClientReaderWriter{..}) = do
  status <- readIORef statusFromServer
  case status of
    Nothing -> do
      recvStatusOp <- opRecvStatusOnClient crw

  callMVar_ :: MVar Call,
  initialMDRef :: !(IORef (Maybe [Metadata])),
  trailingMDRef :: !(IORef (Maybe [Metadata])),
  statusFromServer :: !(MVar RpcStatus)
}

newClientReaderWriter :: ClientContext -> MVar Call -> IO ClientReaderWriter
newClientReaderWriter ctx mcall = do
  initMD <- newIORef Nothing
  trailMD <- newIORef Nothing
  status <- newEmptyMVar
  return (ClientReaderWriter ctx mcall initMD trailMD status)

data OpX = forall t. OpX (OpT t)
