12
12
import com .azure .cosmos .implementation .FeedOperationState ;
13
13
import com .azure .cosmos .implementation .ImplementationBridgeHelpers ;
14
14
import com .azure .cosmos .models .FeedResponse ;
15
+ import org .slf4j .Logger ;
16
+ import org .slf4j .LoggerFactory ;
15
17
import reactor .core .publisher .Flux ;
16
18
17
19
import java .time .Duration ;
18
20
import java .time .Instant ;
21
+ import java .util .concurrent .atomic .AtomicInteger ;
19
22
import java .util .concurrent .atomic .AtomicLong ;
20
23
import java .util .concurrent .atomic .AtomicReference ;
21
24
import java .util .function .Consumer ;
36
39
* @see FeedResponse
37
40
*/
38
41
final class CosmosPagedFluxDefaultImpl <T > extends CosmosPagedFlux <T > {
42
+ private static final Logger LOGGER = LoggerFactory .getLogger (CosmosPagedFluxStaticListImpl .class );
39
43
private static final ImplementationBridgeHelpers .CosmosDiagnosticsContextHelper .CosmosDiagnosticsContextAccessor ctxAccessor =
40
44
ImplementationBridgeHelpers .CosmosDiagnosticsContextHelper .getCosmosDiagnosticsContextAccessor ();
41
45
42
46
private final Function <CosmosPagedFluxOptions , Flux <FeedResponse <T >>> optionsFluxFunction ;
43
- private final Consumer <FeedResponse <T >> feedResponseConsumer ;
44
- private final int defaultPageSize ;
47
+ private final AtomicReference < Consumer <FeedResponse <T > >> feedResponseConsumer ;
48
+ private final AtomicInteger defaultPageSize ;
45
49
46
50
CosmosPagedFluxDefaultImpl (Function <CosmosPagedFluxOptions , Flux <FeedResponse <T >>> optionsFluxFunction ) {
47
51
this (optionsFluxFunction , null , -1 );
@@ -57,8 +61,8 @@ final class CosmosPagedFluxDefaultImpl<T> extends CosmosPagedFlux<T> {
57
61
int defaultPageSize ) {
58
62
super ();
59
63
this .optionsFluxFunction = optionsFluxFunction ;
60
- this .feedResponseConsumer = feedResponseConsumer ;
61
- this .defaultPageSize = defaultPageSize ;
64
+ this .feedResponseConsumer = new AtomicReference <>( feedResponseConsumer ) ;
65
+ this .defaultPageSize = new AtomicInteger ( defaultPageSize ) ;
62
66
}
63
67
64
68
/**
@@ -68,18 +72,39 @@ final class CosmosPagedFluxDefaultImpl<T> extends CosmosPagedFlux<T> {
68
72
* @return CosmosPagedFlux instance with attached handler
69
73
*/
70
74
public CosmosPagedFlux <T > handle (Consumer <FeedResponse <T >> newFeedResponseConsumer ) {
71
- if (this .feedResponseConsumer != null ) {
72
- return new CosmosPagedFluxDefaultImpl <>(
73
- this .optionsFluxFunction ,
74
- this .feedResponseConsumer .andThen (newFeedResponseConsumer ));
75
- } else {
76
- return new CosmosPagedFluxDefaultImpl <>(this .optionsFluxFunction , newFeedResponseConsumer );
75
+ int i = 0 ;
76
+ while (true ) {
77
+ Consumer <FeedResponse <T >> feedResponseConsumerSnapshot = this .feedResponseConsumer .get ();
78
+ i ++;
79
+ if (feedResponseConsumerSnapshot != null ) {
80
+
81
+ if (this .feedResponseConsumer .compareAndSet (
82
+ feedResponseConsumerSnapshot , feedResponseConsumerSnapshot .andThen (newFeedResponseConsumer ))) {
83
+
84
+ break ;
85
+ }
86
+ } else {
87
+ if (this .feedResponseConsumer .compareAndSet (
88
+ null ,
89
+ newFeedResponseConsumer )) {
90
+
91
+ break ;
92
+ }
93
+ }
94
+
95
+ if (i > 10 ) {
96
+ LOGGER .warn ("Highly concurrent calls to CosmosPagedFlux.handle "
97
+ + "are not expected and can result in perf regressions. Avoid this by reducing concurrency." );
98
+ }
77
99
}
100
+
101
+ return this ;
78
102
}
79
103
80
104
@ Override
81
105
CosmosPagedFlux <T > withDefaultPageSize (int pageSize ) {
82
- return new CosmosPagedFluxDefaultImpl <>(this .optionsFluxFunction , this .feedResponseConsumer , pageSize );
106
+ this .defaultPageSize .set (pageSize );
107
+ return this ;
83
108
}
84
109
85
110
@ Override
@@ -113,8 +138,9 @@ public Flux<FeedResponse<T>> byPage(String continuationToken, int preferredPageS
113
138
private CosmosPagedFluxOptions createCosmosPagedFluxOptions () {
114
139
CosmosPagedFluxOptions cosmosPagedFluxOptions = new CosmosPagedFluxOptions ();
115
140
116
- if (this .defaultPageSize > 0 ) {
117
- cosmosPagedFluxOptions .setMaxItemCount (this .defaultPageSize );
141
+ int defaultPageSizeSnapshot = this .defaultPageSize .get ();
142
+ if (defaultPageSizeSnapshot > 0 ) {
143
+ cosmosPagedFluxOptions .setMaxItemCount (defaultPageSizeSnapshot );
118
144
}
119
145
120
146
return cosmosPagedFluxOptions ;
@@ -137,7 +163,7 @@ private Flux<FeedResponse<T>> wrapWithTracingIfEnabled(CosmosPagedFluxOptions p
137
163
case ON_COMPLETE :
138
164
case ON_NEXT :
139
165
DiagnosticsProvider .recordFeedResponse (
140
- feedResponseConsumer ,
166
+ feedResponseConsumer . get () ,
141
167
pagedFluxOptions .getFeedOperationState (),
142
168
() ->pagedFluxOptions .getSamplingRateSnapshot (),
143
169
tracerProvider ,
@@ -169,7 +195,7 @@ private Flux<FeedResponse<T>> wrapWithTracingIfEnabled(CosmosPagedFluxOptions p
169
195
case ON_COMPLETE :
170
196
if (response != null ) {
171
197
DiagnosticsProvider .recordFeedResponse (
172
- feedResponseConsumer ,
198
+ feedResponseConsumer . get () ,
173
199
pagedFluxOptions .getFeedOperationState (),
174
200
() ->pagedFluxOptions .getSamplingRateSnapshot (),
175
201
tracerProvider ,
@@ -193,7 +219,7 @@ private Flux<FeedResponse<T>> wrapWithTracingIfEnabled(CosmosPagedFluxOptions p
193
219
break ;
194
220
case ON_NEXT :
195
221
DiagnosticsProvider .recordFeedResponse (
196
- feedResponseConsumer ,
222
+ feedResponseConsumer . get () ,
197
223
pagedFluxOptions .getFeedOperationState (),
198
224
() ->pagedFluxOptions .getSamplingRateSnapshot (),
199
225
tracerProvider ,
0 commit comments