Skip to content

Commit 2030688

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 2030688

File tree

21 files changed

+742
-38
lines changed

21 files changed

+742
-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: 39 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,28 @@ 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(Long timeout, Long streamId, Consumer<IProtoRequest> timeoutHandler, Map<String, Object> options) {
5768
this.options = options;
5869

5970
this.timeout = timeout;
6071
this.streamId = streamId;
72+
this.timeoutHandler = timeoutHandler;
6173
}
6274

6375
/**
@@ -99,6 +111,16 @@ public Map<String, Object> getOptions() {
99111
return Collections.unmodifiableMap(options);
100112
}
101113

114+
/**
115+
* Returns timeout handler for operation.
116+
*
117+
* @return null - if {@link #timeoutHandler} is null, otherwise - {@link #timeoutHandler} value.
118+
*/
119+
@Override
120+
public Consumer<IProtoRequest> getTimeoutHandler() {
121+
return this.timeoutHandler;
122+
}
123+
102124
/**
103125
* Builder class for {@link OnlyKeyValueOptions}.
104126
*
@@ -115,6 +137,9 @@ public static class Builder {
115137
/** See also: {@link OnlyKeyValueOptions#streamId}. */
116138
private Long streamId;
117139

140+
/** See also: {@link OnlyKeyValueOptions#timeoutHandler}. */
141+
private Consumer<IProtoRequest> timeoutHandler;
142+
118143
/**
119144
* Sets value of {@link #timeout} option. Timeout parameter should be greater than 0.
120145
*
@@ -179,14 +204,26 @@ public Builder withOption(String optionName, Object optionValue) {
179204
return this;
180205
}
181206

207+
/**
208+
* Sets the {@link OnlyKeyValueOptions#timeoutHandler} parameter when constructing an instance of a
209+
* builder class.
210+
*
211+
* @param timeoutHandler see {@link OnlyKeyValueOptions#timeoutHandler} field.
212+
* @return {@link OnlyKeyValueOptions.Builder} object.
213+
*/
214+
public Builder withTimeoutHandler(Consumer<IProtoRequest> timeoutHandler) {
215+
this.timeoutHandler = timeoutHandler;
216+
return this;
217+
}
218+
182219
/**
183220
* Builds object of {@link OnlyKeyValueOptions} class.
184221
*
185222
* @return {@link OnlyKeyValueOptions} object
186223
* @see OnlyKeyValueOptions
187224
*/
188225
public OnlyKeyValueOptions build() {
189-
return new OnlyKeyValueOptions(timeout, streamId, options);
226+
return new OnlyKeyValueOptions(timeout, streamId, timeoutHandler, options);
190227
}
191228
}
192229
}

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: 40 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,27 @@ 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(long timeout, Long streamId, Consumer<IProtoRequest> timeoutHandler, int indexId, String indexName) {
8191
this.timeout = timeout;
8292
this.streamId = streamId;
93+
this.timeoutHandler = timeoutHandler;
8394
this.indexId = indexId;
8495
this.indexName = indexName;
8596
}
@@ -130,6 +141,16 @@ public String getIndexName() {
130141
return indexName;
131142
}
132143

144+
/**
145+
* Returns timeout handler for operation.
146+
*
147+
* @return null - if {@link DeleteOptions#timeoutHandler} is null, otherwise - {@link
148+
* DeleteOptions#timeoutHandler} value.
149+
*/
150+
public Consumer<IProtoRequest> getTimeoutHandler() {
151+
return this.timeoutHandler;
152+
}
153+
133154
/** A specific builder for {@link DeleteOptions} class. */
134155
public static class Builder {
135156

@@ -153,6 +174,11 @@ public static class Builder {
153174
*/
154175
private String indexName;
155176

177+
/**
178+
* @see DeleteOptions#timeoutHandler
179+
*/
180+
private Consumer<IProtoRequest> timeoutHandler;
181+
156182
/**
157183
* Sets the {@link DeleteOptions#timeout} parameter (in milliseconds) when constructing an
158184
* instance of a builder class. The following example creates a {@link DeleteOptions} object
@@ -311,13 +337,25 @@ public Builder withIndex(String indexName) {
311337
return this;
312338
}
313339

340+
/**
341+
* Sets the {@link DeleteOptions#timeoutHandler} parameter when constructing an instance of a
342+
* builder class.
343+
*
344+
* @param timeoutHandler see {@link DeleteOptions#timeoutHandler} field.
345+
* @return {@link DeleteOptions.Builder} object.
346+
*/
347+
public Builder withTimeoutHandler(Consumer<IProtoRequest> timeoutHandler) {
348+
this.timeoutHandler = timeoutHandler;
349+
return this;
350+
}
351+
314352
/**
315353
* Builds specific {@link DeleteOptions} class instance with parameters.
316354
*
317355
* @return {@link DeleteOptions} object.
318356
*/
319357
public DeleteOptions build() {
320-
return new DeleteOptions(timeout, streamId, indexId, indexName);
358+
return new DeleteOptions(timeout, streamId, timeoutHandler, indexId, indexName);
321359
}
322360
}
323361
}

0 commit comments

Comments
 (0)