Skip to content

Commit 6415305

Browse files
authored
Remove APIs for separate init and connect of async cluster contexts (#165)
Embed a `valkeyClusterContext` in a created `valkeyClusterAsyncContext` to be able to cast between these types. This enables users to access the async context in an event callback without using `privdata`, and we can remove the APIs previously kept just for this scenario: valkeyClusterAsyncContext *valkeyClusterAsyncContextInit(const valkeyClusterOptions *options); int valkeyClusterAsyncConnect(valkeyClusterAsyncContext *acc); int valkeyClusterAsyncSetEventCallback(valkeyClusterAsyncContext *acc, void(fn)(const valkeyClusterContext *cc, int event, void *privdata), Also removing the testcase based on `clusterclient_reconnect_async.c` since it was using the removed APIs. There is now a symmetry to how standalone contexts works, i.e. `valkeyAsyncContext` embeds the `valkeyContext`. Signed-off-by: Björn Svensson <[email protected]>
1 parent 4e41608 commit 6415305

14 files changed

+154
-393
lines changed

docs/cluster.md

Lines changed: 11 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,9 @@ The callback is called with `event` set to one of the following values:
193193
* `VALKEYCLUSTER_EVENT_SLOTMAP_UPDATED` when the slot mapping has been updated;
194194
* `VALKEYCLUSTER_EVENT_READY` when the slot mapping has been fetched for the first
195195
time and the client is ready to accept commands, useful when initiating the
196-
client with `valkeyClusterAsyncConnect` where a client is not immediately
197-
ready after a successful call;
196+
client using `valkeyClusterAsyncConnectWithOptions` without enabling the option
197+
`VALKEY_OPT_BLOCKING_INITIAL_UPDATE` where a client is not immediately ready
198+
after a successful call;
198199
* `VALKEYCLUSTER_EVENT_FREE_CONTEXT` when the cluster context is being freed, so
199200
that the user can free the event `privdata`.
200201
@@ -255,26 +256,6 @@ When enabled `valkeyClusterAsyncConnectWithOptions` will initially connect to th
255256
Any command sent by the user thereafter will create a new non-blocking connection, unless a non-blocking connection already exists to the destination.
256257
The function returns a pointer to a newly created `valkeyClusterAsyncContext` struct and its `err` field should be checked to make sure the initial slot map update was successful.
257258
258-
There is also a separate API to perform the context initiation and initial connect in separate steps.
259-
This is useful when there is a need to provide an event callback with the current `valkeyClusterAsyncContext`.
260-
The context is first initiated using `valkeyClusterAsyncContextInit` and then `valkeyClusterAsyncConnect` will initiate connection attempts.
261-
262-
```c
263-
valkeyClusterOptions options = {
264-
.initial_nodes = "127.0.0.1:7000";
265-
};
266-
valkeyClusterOptionsUseLibev(&options, EV_DEFAULT);
267-
268-
// Initiate the context.
269-
valkeyClusterAsyncContext *acc = valkeyClusterAsyncContextInit(&options);
270-
271-
// Set the event callback using the context as privdata.
272-
valkeyClusterAsyncSetEventCallback(acc, eventCallback, acc);
273-
274-
// Start connecting to the initial nodes.
275-
valkeyClusterAsyncConnect(acc)
276-
```
277-
278259
### Connection options
279260
280261
There is a variety of options you can specify using the `valkeyClusterOptions` struct when connecting to a cluster.
@@ -339,9 +320,14 @@ After this, the disconnection callback is executed with the `VALKEY_OK` status a
339320
340321
Use [`event_callback` in `valkeyClusterOptions`](#events-per-cluster-context) to get notified when certain events occur.
341322
342-
When the callback function requires the current `valkeyClusterAsyncContext` it can be provided in the `privdata`.
343-
In this case initiate the context using `valkeyClusterAsyncContextInit`, set the callback and `privdata` using `valkeyClusterAsyncSetEventCallback`,
344-
and initiate connection attempts using `valkeyClusterAsyncConnect` as described under the [Connecting](#connecting-1) section.
323+
When the callback function requires the current `valkeyClusterAsyncContext`, it can typecast the given `valkeyClusterContext` to a `valkeyClusterAsyncContext`.
324+
The `valkeyClusterAsyncContext` struct is an extension of the `valkeyClusterContext` struct.
325+
326+
```c
327+
void eventCallback(const valkeyClusterContext *cc, int event, void *privdata) {
328+
valkeyClusterAsyncContext *acc = (valkeyClusterAsyncContext *)cc;
329+
}
330+
```
345331

346332
#### Events per connection
347333

docs/migration-guide.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ The type `sds` is removed from the public API.
3636
initiation examples that might be helpful.
3737
* The default command to update the internal slot map is changed to `CLUSTER SLOTS`.
3838
`CLUSTER NODES` can be re-enabled through options using `VALKEY_OPT_USE_CLUSTER_NODES`.
39+
* A `valkeyClusterAsyncContext` now embeds a `valkeyClusterContext` instead of
40+
holding a pointer to it. Replace any use of `acc->cc` with `&acc->cc` or similar.
3941

4042
### Renamed API functions
4143

@@ -61,10 +63,13 @@ The type `sds` is removed from the public API.
6163
* `redisClusterSetOptionConnectNonBlock` removed since it was deprecated.
6264
* `redisClusterSetOptionConnectTimeout` removed, use `valkeyClusterOptions.connect_timeout`.
6365
* `redisClusterSetOptionMaxRetry` removed, use `valkeyClusterOptions.max_retry`.
64-
* `redisClusterSetOptionParseSlaves` removed, use `valkeyClusterOptions.flags` and `VALKEY_OPT_USE_REPLICAS`.
66+
* `redisClusterSetOptionParseSlaves` removed, use `valkeyClusterOptions.options` and `VALKEY_OPT_USE_REPLICAS`.
6567
* `redisClusterSetOptionPassword` removed, use `valkeyClusterOptions.password`.
66-
* `redisClusterSetOptionRouteUseSlots` removed, the use of `CLUSTER SLOTS` is enabled by default.
68+
* `redisClusterSetOptionRouteUseSlots` removed, `CLUSTER SLOTS` is used by default.
6769
* `redisClusterSetOptionUsername` removed, use `valkeyClusterOptions.username`.
70+
* `redisClusterAsyncConnect` removed, use `valkeyClusterAsyncConnectWithOptions` with options flag `VALKEY_OPT_BLOCKING_INITIAL_UPDATE`.
71+
* `redisClusterAsyncConnect2` removed, use `valkeyClusterAsyncConnectWithOptions`.
72+
* `redisClusterAsyncContextInit` removed, `valkeyClusterAsyncConnectWithOptions` will initiate the context.
6873
* `redisClusterAsyncSetConnectCallback` removed, but `valkeyClusterOptions.async_connect_callback` can be used which accepts a non-const callback function prototype.
6974
* `redisClusterAsyncSetConnectCallbackNC` removed, use `valkeyClusterOptions.async_connect_callback`.
7075
* `redisClusterAsyncSetDisconnectCallback` removed, use `valkeyClusterOptions.async_disconnect_callback`.

examples/cluster-clientside-caching-async.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ void connectCallback(valkeyAsyncContext *ac, int status) {
3636
commands. A reply is expected via a call to 'setCallback()' */
3737
void eventCallback(const valkeyClusterContext *cc, int event, void *privdata) {
3838
(void)cc;
39-
valkeyClusterAsyncContext *acc = (valkeyClusterAsyncContext *)privdata;
39+
(void)privdata;
40+
/* Get the async context by a simple cast since in the Async API a
41+
* valkeyClusterAsyncContext is an extension of the valkeyClusterContext. */
42+
valkeyClusterAsyncContext *acc = (valkeyClusterAsyncContext *)cc;
4043

4144
/* We send our commands when the client is ready to accept commands. */
4245
if (event == VALKEYCLUSTER_EVENT_READY) {
@@ -145,17 +148,14 @@ int main(int argc, char **argv) {
145148
options.initial_nodes = CLUSTER_NODE;
146149
options.async_connect_callback = connectCallback;
147150
options.async_disconnect_callback = disconnectCallback;
151+
options.event_callback = eventCallback;
148152
valkeyClusterOptionsUseLibevent(&options, base);
149153

150-
valkeyClusterAsyncContext *acc = valkeyClusterAsyncContextInit(&options);
151-
assert(acc);
152-
153-
int status;
154-
status = valkeyClusterAsyncSetEventCallback(acc, eventCallback, acc);
155-
assert(status == VALKEY_OK);
156-
157-
status = valkeyClusterAsyncConnect(acc);
158-
assert(status == VALKEY_OK);
154+
valkeyClusterAsyncContext *acc = valkeyClusterAsyncConnectWithOptions(&options);
155+
if (acc == NULL || acc->err != 0) {
156+
printf("Connect error: %s\n", acc ? acc->errstr : "OOM");
157+
exit(2);
158+
}
159159

160160
event_base_dispatch(base);
161161

include/valkey/cluster.h

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,13 @@ typedef struct valkeyClusterContext {
115115

116116
/* Context for accessing a Valkey Cluster asynchronously */
117117
typedef struct valkeyClusterAsyncContext {
118-
valkeyClusterContext *cc;
118+
/* Hold the regular context. */
119+
valkeyClusterContext cc;
119120

120-
int err; /* Error flags, 0 when there is no error */
121-
char errstr[128]; /* String representation of error when applicable */
121+
int err; /* Error flag, 0 when there is no error,
122+
* a copy of cc->err for convenience. */
123+
char *errstr; /* String representation of error when applicable,
124+
* always pointing to cc->errstr[] */
122125

123126
int64_t lastSlotmapUpdateAttempt; /* Timestamp */
124127

@@ -289,17 +292,6 @@ valkeyClusterAsyncContext *valkeyClusterAsyncConnectWithOptions(const valkeyClus
289292
void valkeyClusterAsyncDisconnect(valkeyClusterAsyncContext *acc);
290293
void valkeyClusterAsyncFree(valkeyClusterAsyncContext *acc);
291294

292-
/* Initiate and connect as separate steps. */
293-
valkeyClusterAsyncContext *valkeyClusterAsyncContextInit(const valkeyClusterOptions *options);
294-
int valkeyClusterAsyncConnect(valkeyClusterAsyncContext *acc);
295-
296-
/* Callback option configurable after a context initiation, enabling that the
297-
* valkeyClusterAsyncContext pointer can be given as privdata in the callback. */
298-
int valkeyClusterAsyncSetEventCallback(valkeyClusterAsyncContext *acc,
299-
void(fn)(const valkeyClusterContext *cc,
300-
int event, void *privdata),
301-
void *privdata);
302-
303295
/* Commands */
304296
int valkeyClusterAsyncCommand(valkeyClusterAsyncContext *acc,
305297
valkeyClusterCallbackFn *fn, void *privdata,

0 commit comments

Comments
 (0)