Skip to content

Commit 7e4ac2d

Browse files
Docs: add a design document for the Client
Add a document that states the requirements for the Client, and then proposes a design that fulfills them.
1 parent ac98986 commit 7e4ac2d

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

docs/client-design.md

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Tntcxx Client Design
2+
3+
## Scope
4+
5+
This document describes the design of the Tntcxx Client. First we state the
6+
requirements and use cases we have in mind, and then we propose a design that
7+
fulfills them.
8+
9+
## Requirements
10+
11+
### Functional Requirements
12+
13+
We envision Tntcxx to be used primarily as a part of network applications (e.g.,
14+
an HTTP server), the Tntcxx Client backing requests to Tarantool. Such
15+
applications are usually built around a central event processing loop, which is
16+
responsible for multiplexing network I/O.
17+
18+
#### Application Event Processing Loop Integration
19+
20+
The first and foremost requirement is that there must be a convenient
21+
way to integrate the Tntcxx Client into the event processing loop used by the
22+
application. Moreover, the Tntcxx Client must never run the event processing
23+
loop itself.
24+
25+
At the same time, since event processing loops are inherently single threaded,
26+
we do expect the Tntcxx Client to be used in a multithreaded environment, i.e.,
27+
when connections and reqeust futures are in different threads. So we do not aim
28+
to design the Tntcxx Client to be thread-safe.
29+
30+
#### Asynchronous Request Processing
31+
32+
Since the Tntcxx Client is constrained from running the event processing loop,
33+
the Tntcxx Client must support asynchronous request processing through
34+
application-provided callbacks, futures or scatter-gather. The Tntcxx Client
35+
must only be responsible for posting requests — the responses must be processed
36+
and returned to the application as they arrive, i.e., asynchronously.
37+
38+
#### Connection Status
39+
40+
The application must be able to check the status of a Tntcxx Client.
41+
42+
#### Request Status
43+
44+
The application must be able to check the status of a Tntcxx Client request.
45+
46+
#### Request Cancelling
47+
48+
The application must be able to cancel a Tntcxx Client request.
49+
50+
#### Error Handling
51+
52+
There must be a convenient exception-safe way for the application to handle
53+
errors arising throughout the Tntcxx Client request lifecycle. A request error
54+
returned either through the callback, or through the future.
55+
56+
#### Request Handling
57+
58+
In order for the application to be able to manage a request, a request handle is
59+
always returned. The application can check the request status, cancel the
60+
request, handle request errors and retrieve the response through this handle
61+
(only once). However, if the response was retrieved by other means (either
62+
returned through a callback or collected through scatter-gather), the handle
63+
cannot return the response.
64+
65+
#### Request Timeout
66+
67+
Since the Tntcxx Client does not have control over the application's event
68+
processing loop, the application must implement its own request timeouts. The
69+
application can cancel stale requests.
70+
71+
#### Response Lifetime
72+
73+
The response lifetime is managed implicitly and does not require any
74+
interference from the application. The response can be retrieved only once, and
75+
it is uniquely owned by the application (i.e., it is not copyable).
76+
77+
#### Request Retrying
78+
79+
Since the Tntcxx Client does not have control over the application's event
80+
processing loop, the application must implement its own request retrying.
81+
82+
#### Reconnection
83+
84+
The Tntcxx Client must support implicit reconnection with the same session
85+
settings it was created with.
86+
87+
#### Connection Pool
88+
89+
TBD.
90+
91+
#### Transactions
92+
93+
TBD.
94+
95+
#### Failover
96+
97+
TBD.
98+
99+
## Design
100+
101+
### Socket
102+
103+
```c++
104+
template<class Resource>
105+
class Socket {
106+
public:
107+
Resource get_resource();
108+
};
109+
```
110+
111+
### Network Provider
112+
113+
```c++
114+
template<class Socket, class Data *>
115+
class NetProvider {
116+
public:
117+
template<class Socket, class Data *>
118+
using read_ready_cb_f = void (*)(Socket sock, Data *data);
119+
120+
template<class Socket, class Data *>
121+
using write_ready_cb_f = void (*)(Socket sock, Data *data);
122+
123+
int register(Socket sock, Data *data, read_ready_cb_f read_ready_cb, write_ready_cb_f write_ready_cb);
124+
int unregister(Socket sock);
125+
};
126+
```
127+
128+
```c++
129+
template<class Socket, class Data *>
130+
class EpollNetProviderData {
131+
public:
132+
EpollNetProviderData(Socket sock, Data *data, read_ready_cb_f read_ready_cb, write_ready_cb_f write_ready_cb);
133+
134+
int type;
135+
136+
void read_ready();
137+
void write_ready();
138+
};
139+
```
140+
141+
### Connection
142+
143+
```c++
144+
struct ConnectionOptions {
145+
/* All existing options. */
146+
147+
static constexpr size_t DEFAULT_RECONNECTION_INTERVAL = 2;
148+
size_t reconnection_interval = DEFAULT_RECONNECTION_INTERVAL;
149+
};
150+
151+
template<class NetProvider>
152+
class Connection {
153+
public:
154+
using request_cb_f = void (*)(std::optional<RequestError> error, Response response, Connection &connection);
155+
156+
Connection(NetProvider net_provider, ConnectionOptions connection_options);
157+
158+
enum class ConnectionStatus status();
159+
160+
std::optional<ConnectionError> error();
161+
162+
/* An abstract request's interface. */
163+
Request some_request(/* options */);
164+
Request some_request(/* options */, request_cb_f request_cb);
165+
166+
template<class Container>
167+
void gather_responses(Container<Response> &responses);
168+
};
169+
```
170+
171+
### Request
172+
173+
```c++
174+
class Request {
175+
public:
176+
enum class RequestStatus status();
177+
178+
std::optional<RequestError> error();
179+
180+
void cancel();
181+
182+
std::optional<Response> get_response();
183+
};
184+
```

0 commit comments

Comments
 (0)