   initMD <- newIORef Nothing
   trailMD <- newIORef Nothing
   status <- newEmptyMVar
-  return (ClientReaderWriter ctx mcall initMD trailMD status)
+  statusEvent <- newEmptyMVar
+  return (ClientReaderWriter ctx mcall initMD trailMD status statusEvent)
 
 data OpX = forall t. OpX (OpT t)
 

  callBatch crw [ OpX sendCloseOp ]

clientCloseCall :: ClientReaderWriter -> IO ()
clientCloseCall ClientReaderWriter { callMVar_ = callMVar } =
  withMVar callMVar $ \call ->
  grpcCallDestroy call

type Rpc req resp a = ReaderT (Client req resp) (ExceptT RpcError IO) a


          QueueShutdown -> return (RpcError (Error "queue shutdown"))
      _ -> do
         return (RpcError (CallErrorStatus callStatus))

callBatchStatusOnClient :: ClientReaderWriter -> IO (RpcReply ())
callBatchStatusOnClient crw@ClientReaderWriter{..} = do
  tag <- tryReadMVar statusFromServerTag
  case tag of
    Just _ -> return (RpcOk ()) -- already did this before
    Nothing -> do
      statusOp <- opRecvStatusOnClient crw
      arr <- toArray [ OpX statusOp ]
      let onBatchComplete = opArrFinishAndFree arr
      eDesc <- CQ.allocateEvent (ccWorker context) onBatchComplete
      putMVar statusFromServerTag eDesc
      callStatus <- withMVar callMVar_ $ \call ->
        grpcCallStartBatch call (opArrPtr arr) (opArrLen arr) (CQ.eventTag eDesc) reservedPtr
      case callStatus of
        CallOk -> return (RpcOk ())
        _ -> return (RpcError (CallErrorStatus callStatus))

data OpT out = Op
  { opAdd    :: [Ptr GrpcOp -> IO ()]
