Cap'n Proto 和 promise 流水线
Cap'n Proto and promise pipelining
我想尝试使用 Cap'n Proto C++ RPC 进行 promise 流水线操作,但我不知道该怎么做。
这是我的架构:
interface Test {
getInt @0 () -> (intResult :Int32);
increment @1 (intParam :Int32) -> (intResult :Int32);
}
这是我想做的(伪代码):
increment(getInt());
我试过那样做:
auto request1 = test.getIntRequest();
auto promise = request1.send();
auto request2 = test.incrementRequest();
request2.setIntParam(promise.getIntResult()) // HERE IS THE PROBLEM
auto promise2 = request2.send();
但这不是使用 promise 的好方法。
我希望你明白我想做什么。
谢谢。
编辑:另一个问题:如何在服务器上实现这些方法?
我写了这段代码:
#include <kj/debug.h>
#include <capnp/ez-rpc.h>
#include <capnp/message.h>
#include <iostream>
#include "test.capnp.h"
using namespace std;
class TestI : virtual public Test::Server
{
public:
TestI() {}
::kj::Promise<void> getInt(GetIntContext context)
{
// ????
}
::kj::Promise<void> increment(IncrementContext context)
{
// ????
}
};
class Int32BoxI : virtual public Int32Box::Server
{
private:
int val = 12;
public:
Int32BoxI(int value): val(value) {}
::kj::Promise<void> get(GetContext context)
{
context.getResults().setValue(this->val);
return kj::READY_NOW;
}
}
但是我不知道如何实现getInt()和increment()。
这里的问题是您试图对 int 进行流水线处理,但流水线处理仅适用于对象引用。您可以通过将 int 包装在一个对象中来解决这个问题,如下所示:
interface Int32Box {
get @0 () -> (value :Int32);
}
interface Test {
getInt @0 () -> (intResult :Int32Box);
increment @1 (intParam :Int32Box) -> (intResult :Int32Box);
}
现在您的代码将按编写的方式运行。
当然,现在您必须在最后的 Int32Box
上额外调用 .get()
才能读取该值。不过幸运的是,您可以通过管道传输此调用,这样它就不需要任何额外的网络往返。
auto request1 = test.getIntRequest();
auto promise = request1.send();
auto request2 = test.incrementRequest();
request2.setIntParam(promise.getIntResult());
auto promise2 = request2.send();
auto request3 = promise2.getIntResult().getRequest();
auto promise3 = request3.send();
// This is the only wait!
int finalResult = promise3.wait().getValue();
以上序列只执行一次网络往返。
我想尝试使用 Cap'n Proto C++ RPC 进行 promise 流水线操作,但我不知道该怎么做。
这是我的架构:
interface Test {
getInt @0 () -> (intResult :Int32);
increment @1 (intParam :Int32) -> (intResult :Int32);
}
这是我想做的(伪代码):
increment(getInt());
我试过那样做:
auto request1 = test.getIntRequest();
auto promise = request1.send();
auto request2 = test.incrementRequest();
request2.setIntParam(promise.getIntResult()) // HERE IS THE PROBLEM
auto promise2 = request2.send();
但这不是使用 promise 的好方法。 我希望你明白我想做什么。
谢谢。
编辑:另一个问题:如何在服务器上实现这些方法?
我写了这段代码:
#include <kj/debug.h>
#include <capnp/ez-rpc.h>
#include <capnp/message.h>
#include <iostream>
#include "test.capnp.h"
using namespace std;
class TestI : virtual public Test::Server
{
public:
TestI() {}
::kj::Promise<void> getInt(GetIntContext context)
{
// ????
}
::kj::Promise<void> increment(IncrementContext context)
{
// ????
}
};
class Int32BoxI : virtual public Int32Box::Server
{
private:
int val = 12;
public:
Int32BoxI(int value): val(value) {}
::kj::Promise<void> get(GetContext context)
{
context.getResults().setValue(this->val);
return kj::READY_NOW;
}
}
但是我不知道如何实现getInt()和increment()。
这里的问题是您试图对 int 进行流水线处理,但流水线处理仅适用于对象引用。您可以通过将 int 包装在一个对象中来解决这个问题,如下所示:
interface Int32Box {
get @0 () -> (value :Int32);
}
interface Test {
getInt @0 () -> (intResult :Int32Box);
increment @1 (intParam :Int32Box) -> (intResult :Int32Box);
}
现在您的代码将按编写的方式运行。
当然,现在您必须在最后的 Int32Box
上额外调用 .get()
才能读取该值。不过幸运的是,您可以通过管道传输此调用,这样它就不需要任何额外的网络往返。
auto request1 = test.getIntRequest();
auto promise = request1.send();
auto request2 = test.incrementRequest();
request2.setIntParam(promise.getIntResult());
auto promise2 = request2.send();
auto request3 = promise2.getIntResult().getRequest();
auto promise3 = request3.send();
// This is the only wait!
int finalResult = promise3.wait().getValue();
以上序列只执行一次网络往返。