Skip to content

Commit 8f3fe1a

Browse files
ArtDuclaude
andcommitted
feat(timeout): add timeout handler callback for requests
Add Consumer<IProtoRequest> timeout handler that is called when a request times out. This allows users to track which requests timed out and handle them appropriately. Changes: - Add timeoutHandler field and getter to Options interface - Add withTimeoutHandler() builder method to BaseOptions - Add timeoutHandler support to all Options implementations - Add withTimeoutHandler() to IProtoRequestOpts - Call timeoutHandler in RequestStateMachine before killing the request - Update TarantoolClientImpl to propagate timeoutHandler - Add test for timeout handler with syncId verification Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ed7c898 commit 8f3fe1a

File tree

21 files changed

+815
-38
lines changed

21 files changed

+815
-38
lines changed

tarantool-client/src/main/java/io/tarantool/client/BaseOptions.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
package io.tarantool.client;
77

8+
import java.util.function.Consumer;
9+
10+
import io.tarantool.core.protocol.IProtoRequest;
11+
812
/**
913
* The class implements base options for operations.
1014
*
@@ -34,16 +38,25 @@ public class BaseOptions implements Options {
3438
*/
3539
private final Long streamId;
3640

41+
/**
42+
* Timeout handler for operation.
43+
*
44+
* <p>Default value: null.
45+
*/
46+
private final Consumer<IProtoRequest> timeoutHandler;
47+
3748
/**
3849
* This constructor creates options based on the passed parameters.
3950
*
4051
* @param timeout see also: {@link #timeout}.
4152
* @param streamId see also: {@link #streamId}.
53+
* @param timeoutHandler see also: {@link #timeoutHandler}.
4254
* @see BaseOptions.Builder#build()
4355
*/
44-
protected BaseOptions(long timeout, Long streamId) {
56+
protected BaseOptions(long timeout, Long streamId, Consumer<IProtoRequest> timeoutHandler) {
4557
this.timeout = timeout;
4658
this.streamId = streamId;
59+
this.timeoutHandler = timeoutHandler;
4760
}
4861

4962
/**
@@ -74,6 +87,16 @@ public Long getStreamId() {
7487
return this.streamId;
7588
}
7689

90+
/**
91+
* Returns timeout handler for operation.
92+
*
93+
* @return null - if {@link BaseOptions#timeoutHandler} is null, otherwise - {@link
94+
* BaseOptions#timeoutHandler} value.
95+
*/
96+
public Consumer<IProtoRequest> getTimeoutHandler() {
97+
return this.timeoutHandler;
98+
}
99+
77100
/** A specific builder for {@link BaseOptions} class. */
78101
public static class Builder {
79102

@@ -87,6 +110,11 @@ public static class Builder {
87110
*/
88111
private Long streamId;
89112

113+
/**
114+
* @see BaseOptions#timeoutHandler
115+
*/
116+
private Consumer<IProtoRequest> timeoutHandler;
117+
90118
/**
91119
* Sets the {@link BaseOptions#timeout} parameter (in milliseconds) when constructing an
92120
* instance of a builder class. The following example creates a {@link BaseOptions} object with
@@ -161,13 +189,38 @@ public Builder withStreamId(long streamId) {
161189
return this;
162190
}
163191

192+
/**
193+
* Sets the {@link BaseOptions#timeoutHandler} parameter when constructing an instance of a
194+
* builder class. The following example creates a {@link BaseOptions} object with a specified
195+
* {@link BaseOptions#timeoutHandler} parameter:
196+
*
197+
* <pre>{@code
198+
* BaseOptions options = BaseOptions
199+
* .builder()
200+
* .withTimeoutHandler(request -> {
201+
* System.out.println("Request timed out: " + request);
202+
* }) // OK!
203+
* .build();
204+
*
205+
*
206+
*
207+
* }</pre>
208+
*
209+
* @param timeoutHandler see {@link BaseOptions#timeoutHandler} field.
210+
* @return {@link BaseOptions.Builder} object.
211+
*/
212+
public Builder withTimeoutHandler(Consumer<IProtoRequest> timeoutHandler) {
213+
this.timeoutHandler = timeoutHandler;
214+
return this;
215+
}
216+
164217
/**
165218
* Builds specific {@link BaseOptions} class instance with parameters.
166219
*
167220
* @return {@link BaseOptions} object.
168221
*/
169222
public BaseOptions build() {
170-
return new BaseOptions(timeout, streamId);
223+
return new BaseOptions(timeout, streamId, timeoutHandler);
171224
}
172225
}
173226
}

tarantool-client/src/main/java/io/tarantool/client/OnlyKeyValueOptions.java

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,13 @@
88
import java.util.Collections;
99
import java.util.HashMap;
1010
import java.util.Map;
11+
import java.util.function.Consumer;
1112

1213
import org.slf4j.Logger;
1314
import org.slf4j.LoggerFactory;
1415

16+
import io.tarantool.core.protocol.IProtoRequest;
17+
1518
/** TODO: Rename this class to a more elegant name. */
1619
public class OnlyKeyValueOptions implements OptionsMap {
1720

@@ -45,19 +48,32 @@ public class OnlyKeyValueOptions implements OptionsMap {
4548
/** A map containing the correspondence between option names and their meanings. */
4649
private final Map<String, Object> options;
4750

51+
/**
52+
* Timeout handler for operation.
53+
*
54+
* <p>Default value: null.
55+
*/
56+
private final Consumer<IProtoRequest> timeoutHandler;
57+
4858
/**
4959
* Creates a {@link OnlyKeyValueOptions} object with the given parameters.
5060
*
5161
* @param timeout {@link #timeout}
5262
* @param streamId {@link #streamId}
63+
* @param timeoutHandler {@link #timeoutHandler}
5364
* @param options {@link #options}
5465
* @see OnlyKeyValueOptions
5566
*/
56-
public OnlyKeyValueOptions(Long timeout, Long streamId, Map<String, Object> options) {
67+
public OnlyKeyValueOptions(
68+
Long timeout,
69+
Long streamId,
70+
Consumer<IProtoRequest> timeoutHandler,
71+
Map<String, Object> options) {
5772
this.options = options;
5873

5974
this.timeout = timeout;
6075
this.streamId = streamId;
76+
this.timeoutHandler = timeoutHandler;
6177
}
6278

6379
/**
@@ -99,6 +115,16 @@ public Map<String, Object> getOptions() {
99115
return Collections.unmodifiableMap(options);
100116
}
101117

118+
/**
119+
* Returns timeout handler for operation.
120+
*
121+
* @return null - if {@link #timeoutHandler} is null, otherwise - {@link #timeoutHandler} value.
122+
*/
123+
@Override
124+
public Consumer<IProtoRequest> getTimeoutHandler() {
125+
return this.timeoutHandler;
126+
}
127+
102128
/**
103129
* Builder class for {@link OnlyKeyValueOptions}.
104130
*
@@ -115,6 +141,9 @@ public static class Builder {
115141
/** See also: {@link OnlyKeyValueOptions#streamId}. */
116142
private Long streamId;
117143

144+
/** See also: {@link OnlyKeyValueOptions#timeoutHandler}. */
145+
private Consumer<IProtoRequest> timeoutHandler;
146+
118147
/**
119148
* Sets value of {@link #timeout} option. Timeout parameter should be greater than 0.
120149
*
@@ -179,14 +208,26 @@ public Builder withOption(String optionName, Object optionValue) {
179208
return this;
180209
}
181210

211+
/**
212+
* Sets the {@link OnlyKeyValueOptions#timeoutHandler} parameter when constructing an instance
213+
* of a builder class.
214+
*
215+
* @param timeoutHandler see {@link OnlyKeyValueOptions#timeoutHandler} field.
216+
* @return {@link OnlyKeyValueOptions.Builder} object.
217+
*/
218+
public Builder withTimeoutHandler(Consumer<IProtoRequest> timeoutHandler) {
219+
this.timeoutHandler = timeoutHandler;
220+
return this;
221+
}
222+
182223
/**
183224
* Builds object of {@link OnlyKeyValueOptions} class.
184225
*
185226
* @return {@link OnlyKeyValueOptions} object
186227
* @see OnlyKeyValueOptions
187228
*/
188229
public OnlyKeyValueOptions build() {
189-
return new OnlyKeyValueOptions(timeout, streamId, options);
230+
return new OnlyKeyValueOptions(timeout, streamId, timeoutHandler, options);
190231
}
191232
}
192233
}

tarantool-client/src/main/java/io/tarantool/client/Options.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@
55

66
package io.tarantool.client;
77

8+
import java.util.function.Consumer;
9+
10+
import io.tarantool.core.protocol.IProtoRequest;
11+
812
/**
913
* Provides a contract for basic client options.
1014
*
@@ -26,4 +30,11 @@ public interface Options {
2630
* @return null - if stream id is null, otherwise - stream id value.
2731
*/
2832
Long getStreamId();
33+
34+
/**
35+
* Returns timeout handler for operation.
36+
*
37+
* @return null - if timeout handler is not set, otherwise - timeout handler.
38+
*/
39+
Consumer<IProtoRequest> getTimeoutHandler();
2940
}

tarantool-client/src/main/java/io/tarantool/client/box/options/DeleteOptions.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66
package io.tarantool.client.box.options;
77

88
import java.util.List;
9+
import java.util.function.Consumer;
910

1011
import com.fasterxml.jackson.core.type.TypeReference;
1112

1213
import io.tarantool.client.box.TarantoolBoxClient;
1314
import io.tarantool.client.box.TarantoolBoxSpace;
15+
import io.tarantool.core.protocol.IProtoRequest;
1416

1517
/**
1618
* The class implements options for the delete operation of the {@link TarantoolBoxClient
@@ -68,18 +70,32 @@ public class DeleteOptions implements OptionsWithIndex {
6870
/** Name of the index. */
6971
private final String indexName;
7072

73+
/**
74+
* Timeout handler for operation.
75+
*
76+
* <p>Default value: null.
77+
*/
78+
private final Consumer<IProtoRequest> timeoutHandler;
79+
7180
/**
7281
* Creates options based on the passed parameters.
7382
*
7483
* @param timeout see also: {@link DeleteOptions#timeout}.
7584
* @param streamId see also: {@link DeleteOptions#streamId}.
85+
* @param timeoutHandler see also: {@link DeleteOptions#timeoutHandler}.
7686
* @param indexId see also: {@link DeleteOptions#indexId}.
7787
* @param indexName see also: {@link DeleteOptions#indexName}.
7888
* @see Builder#build()
7989
*/
80-
private DeleteOptions(long timeout, Long streamId, int indexId, String indexName) {
90+
private DeleteOptions(
91+
long timeout,
92+
Long streamId,
93+
Consumer<IProtoRequest> timeoutHandler,
94+
int indexId,
95+
String indexName) {
8196
this.timeout = timeout;
8297
this.streamId = streamId;
98+
this.timeoutHandler = timeoutHandler;
8399
this.indexId = indexId;
84100
this.indexName = indexName;
85101
}
@@ -130,6 +146,16 @@ public String getIndexName() {
130146
return indexName;
131147
}
132148

149+
/**
150+
* Returns timeout handler for operation.
151+
*
152+
* @return null - if {@link DeleteOptions#timeoutHandler} is null, otherwise - {@link
153+
* DeleteOptions#timeoutHandler} value.
154+
*/
155+
public Consumer<IProtoRequest> getTimeoutHandler() {
156+
return this.timeoutHandler;
157+
}
158+
133159
/** A specific builder for {@link DeleteOptions} class. */
134160
public static class Builder {
135161

@@ -153,6 +179,11 @@ public static class Builder {
153179
*/
154180
private String indexName;
155181

182+
/**
183+
* @see DeleteOptions#timeoutHandler
184+
*/
185+
private Consumer<IProtoRequest> timeoutHandler;
186+
156187
/**
157188
* Sets the {@link DeleteOptions#timeout} parameter (in milliseconds) when constructing an
158189
* instance of a builder class. The following example creates a {@link DeleteOptions} object
@@ -311,13 +342,25 @@ public Builder withIndex(String indexName) {
311342
return this;
312343
}
313344

345+
/**
346+
* Sets the {@link DeleteOptions#timeoutHandler} parameter when constructing an instance of a
347+
* builder class.
348+
*
349+
* @param timeoutHandler see {@link DeleteOptions#timeoutHandler} field.
350+
* @return {@link DeleteOptions.Builder} object.
351+
*/
352+
public Builder withTimeoutHandler(Consumer<IProtoRequest> timeoutHandler) {
353+
this.timeoutHandler = timeoutHandler;
354+
return this;
355+
}
356+
314357
/**
315358
* Builds specific {@link DeleteOptions} class instance with parameters.
316359
*
317360
* @return {@link DeleteOptions} object.
318361
*/
319362
public DeleteOptions build() {
320-
return new DeleteOptions(timeout, streamId, indexId, indexName);
363+
return new DeleteOptions(timeout, streamId, timeoutHandler, indexId, indexName);
321364
}
322365
}
323366
}

0 commit comments

Comments
 (0)