16
16
package org .springframework .data .couchbase .core ;
17
17
18
18
import static com .couchbase .client .java .kv .GetAndTouchOptions .getAndTouchOptions ;
19
+ import static com .couchbase .client .java .kv .GetAndLockOptions .getAndLockOptions ;
19
20
import static com .couchbase .client .java .transactions .internal .ConverterUtil .makeCollectionIdentifier ;
20
21
22
+ import com .couchbase .client .java .kv .GetAndLockOptions ;
21
23
import reactor .core .publisher .Flux ;
22
24
import reactor .core .publisher .Mono ;
23
25
26
28
import java .util .Arrays ;
27
29
import java .util .Collection ;
28
30
import java .util .List ;
31
+ import java .util .Optional ;
29
32
30
33
import org .slf4j .Logger ;
31
34
import org .slf4j .LoggerFactory ;
45
48
* {@link ReactiveFindByIdOperation} implementations for Couchbase.
46
49
*
47
50
* @author Michael Reiche
51
+ * @author Tigran Babloyan
48
52
*/
49
53
public class ReactiveFindByIdOperationSupport implements ReactiveFindByIdOperation {
50
54
@@ -58,7 +62,7 @@ public class ReactiveFindByIdOperationSupport implements ReactiveFindByIdOperati
58
62
@ Override
59
63
public <T > ReactiveFindById <T > findById (Class <T > domainType ) {
60
64
return new ReactiveFindByIdSupport <>(template , domainType , OptionsBuilder .getScopeFrom (domainType ),
61
- OptionsBuilder .getCollectionFrom (domainType ), null , null , null , template .support ());
65
+ OptionsBuilder .getCollectionFrom (domainType ), null , null , null , null , template .support ());
62
66
}
63
67
64
68
static class ReactiveFindByIdSupport <T > implements ReactiveFindById <T > {
@@ -71,11 +75,12 @@ static class ReactiveFindByIdSupport<T> implements ReactiveFindById<T> {
71
75
private final List <String > fields ;
72
76
private final ReactiveTemplateSupport support ;
73
77
private final Duration expiry ;
78
+ private final Duration lockDuration ;
74
79
75
80
private Duration expiryToUse ;
76
81
77
82
ReactiveFindByIdSupport (ReactiveCouchbaseTemplate template , Class <T > domainType , String scope , String collection ,
78
- CommonOptions <?> options , List <String > fields , Duration expiry , ReactiveTemplateSupport support ) {
83
+ CommonOptions <?> options , List <String > fields , Duration expiry , Duration lockDuration , ReactiveTemplateSupport support ) {
79
84
this .template = template ;
80
85
this .domainType = domainType ;
81
86
this .scope = scope ;
@@ -84,6 +89,7 @@ static class ReactiveFindByIdSupport<T> implements ReactiveFindById<T> {
84
89
this .fields = fields ;
85
90
this .expiry = expiry ;
86
91
this .support = support ;
92
+ this .lockDuration = lockDuration ;
87
93
}
88
94
89
95
@ Override
@@ -99,8 +105,12 @@ public Mono<T> one(final Object id) {
99
105
100
106
Mono <T > reactiveEntity = TransactionalSupport .checkForTransactionInThreadLocalStorage ().flatMap (ctxOpt -> {
101
107
if (!ctxOpt .isPresent ()) {
102
- if (pArgs .getOptions () instanceof GetAndTouchOptions ) {
103
- return rc .getAndTouch (id .toString (), expiryToUse , (GetAndTouchOptions ) pArgs .getOptions ())
108
+ if (pArgs .getOptions () instanceof GetAndTouchOptions options ) {
109
+ return rc .getAndTouch (id .toString (), expiryToUse , options )
110
+ .flatMap (result -> support .decodeEntity (id , result .contentAs (String .class ), result .cas (), domainType ,
111
+ pArgs .getScope (), pArgs .getCollection (), null , null ));
112
+ } else if (pArgs .getOptions () instanceof GetAndLockOptions options ) {
113
+ return rc .getAndLock (id .toString (), Optional .of (lockDuration ).orElse (Duration .ZERO ), options )
104
114
.flatMap (result -> support .decodeEntity (id , result .contentAs (String .class ), result .cas (), domainType ,
105
115
pArgs .getScope (), pArgs .getCollection (), null , null ));
106
116
} else {
@@ -132,6 +142,9 @@ public Mono<T> one(final Object id) {
132
142
}
133
143
134
144
private void rejectInvalidTransactionalOptions () {
145
+ if (this .lockDuration != null ) {
146
+ throw new IllegalArgumentException ("withLock is not supported in a transaction" );
147
+ }
135
148
if (this .expiry != null ) {
136
149
throw new IllegalArgumentException ("withExpiry is not supported in a transaction" );
137
150
}
@@ -151,39 +164,53 @@ public Flux<? extends T> all(final Collection<String> ids) {
151
164
@ Override
152
165
public FindByIdInScope <T > withOptions (final GetOptions options ) {
153
166
Assert .notNull (options , "Options must not be null." );
154
- return new ReactiveFindByIdSupport <>(template , domainType , scope , collection , options , fields , expiry , support );
167
+ return new ReactiveFindByIdSupport <>(template , domainType , scope , collection , options , fields , expiry ,
168
+ lockDuration , support );
155
169
}
156
170
157
171
@ Override
158
172
public FindByIdWithOptions <T > inCollection (final String collection ) {
159
173
return new ReactiveFindByIdSupport <>(template , domainType , scope ,
160
- collection != null ? collection : this .collection , options , fields , expiry , support );
174
+ collection != null ? collection : this .collection , options , fields , expiry , lockDuration , support );
161
175
}
162
176
163
177
@ Override
164
178
public FindByIdInCollection <T > inScope (final String scope ) {
165
179
return new ReactiveFindByIdSupport <>(template , domainType , scope != null ? scope : this .scope , collection ,
166
- options , fields , expiry , support );
180
+ options , fields , expiry , lockDuration , support );
167
181
}
168
182
169
183
@ Override
170
184
public FindByIdInCollection <T > project (String ... fields ) {
171
185
Assert .notNull (fields , "Fields must not be null" );
172
186
return new ReactiveFindByIdSupport <>(template , domainType , scope , collection , options , Arrays .asList (fields ),
173
- expiry , support );
187
+ expiry , lockDuration , support );
174
188
}
175
189
176
190
@ Override
177
191
public FindByIdWithProjection <T > withExpiry (final Duration expiry ) {
178
- return new ReactiveFindByIdSupport <>(template , domainType , scope , collection , options , fields , expiry , support );
192
+ return new ReactiveFindByIdSupport <>(template , domainType , scope , collection , options , fields , expiry ,
193
+ lockDuration , support );
194
+ }
195
+
196
+ @ Override
197
+ public FindByIdWithExpiry <T > withLock (final Duration lockDuration ) {
198
+ return new ReactiveFindByIdSupport <>(template , domainType , scope , collection , options , fields , expiry ,
199
+ lockDuration , support );
179
200
}
180
201
181
202
private CommonOptions <?> initGetOptions () {
182
203
CommonOptions <?> getOptions ;
183
204
final CouchbasePersistentEntity <?> entity = template .getConverter ().getMappingContext ()
184
205
.getRequiredPersistentEntity (domainType );
185
206
Boolean isTouchOnRead = entity .isTouchOnRead ();
186
- if (expiry != null || isTouchOnRead || options instanceof GetAndTouchOptions ) {
207
+ if (lockDuration != null || options instanceof GetAndLockOptions ) {
208
+ GetAndLockOptions gOptions = options != null ? (GetAndLockOptions ) options : getAndLockOptions ();
209
+ if (gOptions .build ().transcoder () == null ) {
210
+ gOptions .transcoder (RawJsonTranscoder .INSTANCE );
211
+ }
212
+ getOptions = gOptions ;
213
+ } else if (expiry != null || isTouchOnRead || options instanceof GetAndTouchOptions ) {
187
214
if (expiry != null ) {
188
215
expiryToUse = expiry ;
189
216
} else if (isTouchOnRead ) {
0 commit comments