Skip to content

Commit a31bda5

Browse files
authored
Merge pull request #1633 from marklogic/feature/revert-optic-update
Reverting usage of v1/rows/update
2 parents 2f0aacf + 8dd765f commit a31bda5

File tree

7 files changed

+106
-155
lines changed

7 files changed

+106
-155
lines changed

marklogic-client-api/src/main/java/com/marklogic/client/impl/RowManagerImpl.java

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@
3333
import com.fasterxml.jackson.databind.JsonNode;
3434
import com.fasterxml.jackson.databind.ObjectMapper;
3535
import com.fasterxml.jackson.databind.node.JsonNodeType;
36-
import com.marklogic.client.*;
3736
import com.marklogic.client.DatabaseClientFactory.HandleFactoryRegistry;
37+
import com.marklogic.client.MarkLogicBindingException;
38+
import com.marklogic.client.MarkLogicIOException;
39+
import com.marklogic.client.MarkLogicInternalException;
40+
import com.marklogic.client.Transaction;
3841
import com.marklogic.client.document.DocumentWriteSet;
3942
import com.marklogic.client.expression.PlanBuilder;
4043
import com.marklogic.client.expression.PlanBuilder.Plan;
@@ -59,7 +62,6 @@ public class RowManagerImpl
5962
private RowStructure rowStructureStyle = null;
6063
private Integer optimize;
6164
private String traceLabel;
62-
private boolean update;
6365

6466
public RowManagerImpl(RESTServices services) {
6567
super();
@@ -122,13 +124,7 @@ public void setOptimize(Integer value) {
122124
this.optimize = value;
123125
}
124126

125-
@Override
126-
public RowManager withUpdate(boolean update) {
127-
this.update = update;
128-
return this;
129-
}
130-
131-
@Override
127+
@Override
132128
public RawPlanDefinition newRawPlanDefinition(JSONWriteHandle handle) {
133129
return new RawPlanDefinitionImpl(handle);
134130
}
@@ -180,11 +176,7 @@ public <T extends StructureReadHandle> T resultDoc(Plan plan, T resultsHandle, T
180176
.withColumnTypes(getDatatypeStyle())
181177
.withOutput(getRowStructureStyle())
182178
.getRequestParameters();
183-
return services.postResource(requestLogger, determinePath(), transaction, params, astHandle, resultsHandle);
184-
}
185-
186-
private String determinePath() {
187-
return this.update ? "rows/update" : "rows";
179+
return services.postResource(requestLogger, "rows", transaction, params, astHandle, resultsHandle);
188180
}
189181

190182
@Override
@@ -299,9 +291,8 @@ public <T extends StructureReadHandle> T explain(Plan plan, T resultsHandle) {
299291
RequestParameters params = new RequestParameters();
300292
params.add("output", "explain");
301293

302-
return services.postResource(requestLogger, determinePath(), null, params, astHandle, resultsHandle);
294+
return services.postResource(requestLogger, "rows", null, params, astHandle, resultsHandle);
303295
}
304-
305296
@Override
306297
public <T> T explainAs(Plan plan, Class<T> as) {
307298
ContentHandle<T> handle = handleFor(as);
@@ -418,23 +409,11 @@ private <T extends AbstractReadHandle> String getRowFormat(T rowHandle) {
418409
private RESTServiceResultIterator submitPlan(PlanBuilderBaseImpl.RequestPlan requestPlan, RequestParameters params, Transaction transaction) {
419410
AbstractWriteHandle astHandle = requestPlan.getHandle();
420411
List<ContentParam> contentParams = requestPlan.getContentParams();
421-
final String path = determinePath();
422-
try {
423-
if (contentParams != null && !contentParams.isEmpty()) {
424-
contentParams.add(new ContentParam(new PlanBuilderBaseImpl.PlanParamBase("query"), astHandle, null));
425-
return services.postMultipartForm(requestLogger, path, transaction, params, contentParams);
426-
}
427-
return services.postIteratedResource(requestLogger, path, transaction, params, astHandle);
428-
} catch (FailedRequestException ex) {
429-
String message = ex.getMessage();
430-
if (message != null && message.contains("RESTAPI-UPDATEFROMQUERY")) {
431-
String betterMessage = "The Optic plan is attempting an update but was sent to the wrong REST API endpoint. " +
432-
"You must invoke `withUpdate(true)` on the instance of com.marklogic.client.row.RowManager that you " +
433-
"are using to submit the plan";
434-
throw new FailedRequestException(betterMessage, ex.getFailedRequest());
435-
}
436-
throw ex;
437-
}
412+
if (contentParams != null && !contentParams.isEmpty()) {
413+
contentParams.add(new ContentParam(new PlanBuilderBaseImpl.PlanParamBase("query"), astHandle, null));
414+
return services.postMultipartForm(requestLogger, "rows", transaction, params, contentParams);
415+
}
416+
return services.postIteratedResource(requestLogger, "rows", transaction, params, astHandle);
438417
}
439418

440419
private PlanBuilderBaseImpl.RequestPlan checkPlan(Plan plan) {

marklogic-client-api/src/main/java/com/marklogic/client/row/RowManager.java

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,18 +87,6 @@ public enum RowStructure{ARRAY, OBJECT}
8787
*/
8888
void setTraceLabel(String label);
8989

90-
/**
91-
* As of MarkLogic 11.2, the "v1/rows/update" endpoint must be used in order to submit an Optic plan that performs
92-
* an update. This method must be called with a value of {@code true} in order for that endpoint to be used instead
93-
* of "v1/rows". You may later call this method with a value of {@code false} in order to submit a plan that does
94-
* not perform an update.
95-
*
96-
* @param update set to {@code true} if submitting a plan that performs an update
97-
* @return the instance of this class
98-
* @since 6.5.0
99-
*/
100-
RowManager withUpdate(boolean update);
101-
10290
/**
10391
* @return the label that will be used for all log messages associated with the "optic" trace event
10492
*/

marklogic-client-api/src/test/java/com/marklogic/client/test/rows/AbstractOpticUpdateTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public void setup() {
4747
.evalAs(String.class);
4848

4949
Common.client = Common.newClientBuilder().withUsername("writer-no-default-permissions").build();
50-
rowManager = Common.client.newRowManager().withUpdate(true);
50+
rowManager = Common.client.newRowManager();
5151
op = rowManager.newPlanBuilder();
5252
}
5353

marklogic-client-api/src/test/java/com/marklogic/client/test/rows/FromDocDescriptorsTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public void insertDocsWithUserWithDefaultCollectionsAndPermissions() {
4646
mapper.createObjectNode().put("hello", "two")));
4747

4848
Common.client = Common.newClientBuilder().withUsername(USER_WITH_DEFAULT_COLLECTIONS_AND_PERMISSIONS).build();
49-
Common.client.newRowManager().withUpdate(true).execute(op
49+
Common.client.newRowManager().execute(op
5050
.fromDocDescriptors(op.docDescriptors(writeSet))
5151
.write());
5252

@@ -88,7 +88,7 @@ public void updateOnlyDocAsUserWithNoDefaults() {
8888
public void updateOnlyDocWithUserWithDefaultCollectionsAndPermissions() {
8989
// Set up client as user with default collections and permissions
9090
Common.client = Common.newClientBuilder().withUsername(USER_WITH_DEFAULT_COLLECTIONS_AND_PERMISSIONS).build();
91-
rowManager = Common.client.newRowManager().withUpdate(true);
91+
rowManager = Common.client.newRowManager();
9292
op = rowManager.newPlanBuilder();
9393

9494
verifyOnlyDocCanBeUpdatedWithoutLosingAnyMetadata();
Lines changed: 77 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.marklogic.client.test.rows;
22

33
import com.fasterxml.jackson.databind.node.ArrayNode;
4-
import com.marklogic.client.FailedRequestException;
54
import com.marklogic.client.expression.PlanBuilder;
65
import com.marklogic.client.io.DocumentMetadataHandle;
76
import com.marklogic.client.io.JacksonHandle;
@@ -13,105 +12,89 @@
1312

1413
import java.util.List;
1514

16-
import static org.junit.jupiter.api.Assertions.*;
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
import static org.junit.jupiter.api.Assertions.assertTrue;
1717

1818
@ExtendWith(RequiresML11.class)
1919
public class LockForUpdateTest extends AbstractOpticUpdateTest {
2020

21-
@Test
22-
public void basicTest() {
23-
final String uri = "/acme/doc1.json";
24-
25-
// Write a document
26-
rowManager.execute(op.fromDocDescriptors(
27-
op.docDescriptor(newWriteOp(uri, new JacksonHandle(mapper.createObjectNode().put("hello", "world")))))
28-
.write());
29-
verifyJsonDoc(uri, doc -> assertEquals("world", doc.get("hello").asText()));
30-
31-
// Construct a plan that will lock the URI and update its collection
32-
PlanBuilder.ModifyPlan plan = op
33-
.fromDocDescriptors(
34-
op.docDescriptor(newWriteOp(uri, new DocumentMetadataHandle().withCollections("optic1"), null))
35-
)
36-
.lockForUpdate()
37-
.write(op.docCols(null, op.xs.stringSeq("uri", "collections")));
38-
39-
// Run an eval that locks the URI and sleeps for 2 seconds, which will block the plan run below
40-
new Thread(() -> {
41-
Common.newServerAdminClient().newServerEval()
42-
.javascript(String.format("declareUpdate(); " +
43-
"xdmp.lockForUpdate('%s'); " +
44-
"xdmp.sleep(2000); " +
45-
"xdmp.documentSetCollections('%s', ['eval1']);", uri, uri))
46-
.evalAs(String.class);
47-
}).start();
48-
49-
// Immediately run a plan that updates the collections as well; this should be blocked while the eval thread
50-
// above completes
51-
long start = System.currentTimeMillis();
52-
rowManager.execute(plan);
53-
long duration = System.currentTimeMillis() - start;
54-
System.out.println("DUR: " + duration);
55-
56-
assertTrue(duration > 1500,
21+
@Test
22+
public void basicTest() {
23+
final String uri = "/acme/doc1.json";
24+
25+
// Write a document
26+
rowManager.execute(op.fromDocDescriptors(
27+
op.docDescriptor(newWriteOp(uri, new JacksonHandle(mapper.createObjectNode().put("hello", "world")))))
28+
.write());
29+
verifyJsonDoc(uri, doc -> assertEquals("world", doc.get("hello").asText()));
30+
31+
// Construct a plan that will lock the URI and update its collection
32+
PlanBuilder.ModifyPlan plan = op
33+
.fromDocDescriptors(
34+
op.docDescriptor(newWriteOp(uri, new DocumentMetadataHandle().withCollections("optic1"), null))
35+
)
36+
.lockForUpdate()
37+
.write(op.docCols(null, op.xs.stringSeq("uri", "collections")));
38+
39+
// Run an eval that locks the URI and sleeps for 2 seconds, which will block the plan run below
40+
new Thread(() -> {
41+
Common.newServerAdminClient().newServerEval()
42+
.javascript(String.format("declareUpdate(); " +
43+
"xdmp.lockForUpdate('%s'); " +
44+
"xdmp.sleep(2000); " +
45+
"xdmp.documentSetCollections('%s', ['eval1']);", uri, uri))
46+
.evalAs(String.class);
47+
}).start();
48+
49+
// Immediately run a plan that updates the collections as well; this should be blocked while the eval thread
50+
// above completes
51+
long start = System.currentTimeMillis();
52+
rowManager.execute(plan);
53+
long duration = System.currentTimeMillis() - start;
54+
System.out.println("DUR: " + duration);
55+
56+
assertTrue(duration > 1500,
5757
"Because the eval call slept for 2 seconds, the duration of the plan execution should be at least " +
5858
"1500ms, which is much longer than normal; it may not be at least 2 seconds due to the small delay in " +
5959
"the Java layer of executing the plan; duration: " + duration);
6060

61-
// Verify that the collections were set based on the plan, which should have run second
62-
verifyMetadata(uri, metadata -> {
63-
DocumentMetadataHandle.DocumentCollections colls = metadata.getCollections();
64-
assertEquals(1, colls.size());
65-
assertEquals("optic1", colls.iterator().next());
66-
});
67-
}
68-
69-
@Test
70-
void wrongEndpoint() {
71-
rowManager.withUpdate(false);
72-
FailedRequestException ex = assertThrows(
73-
FailedRequestException.class,
74-
() -> rowManager.execute(op.fromDocUris("/optic/test/musician1.json").lockForUpdate()),
75-
"Hoping to update this assertion to verify that the server message tells the user to hit v1/rows/update " +
76-
"instead; right now, it's mentioning using declareUpdate() which isn't applicable to a REST API user."
77-
);
78-
79-
assertTrue(ex.getMessage().contains(
80-
"The Optic plan is attempting an update but was sent to the wrong REST API endpoint. " +
81-
"You must invoke `withUpdate(true)` on the instance of com.marklogic.client.row.RowManager " +
82-
"that you are using to submit the plan."),
83-
"Unexpected message: " + ex.getMessage());
84-
}
85-
86-
@Test
87-
public void uriColumnSpecified() {
88-
List<RowRecord> rows = resultRows(op
89-
.fromDocUris("/optic/test/musician1.json")
90-
.lockForUpdate(op.col("uri")));
91-
assertEquals(1, rows.size());
92-
}
93-
94-
@Test
95-
public void fromParamWithCustomUriColumn() {
96-
ArrayNode paramValue = mapper.createArrayNode();
97-
paramValue.addObject().put("myUri", "/optic/test/musician1.json");
98-
99-
List<RowRecord> rows = resultRows(op
100-
.fromParam("bindingParam", "", op.colTypes(op.colType("myUri", "string")))
101-
.lockForUpdate(op.col("myUri"))
102-
.bindParam("bindingParam", new JacksonHandle(paramValue), null));
103-
assertEquals(1, rows.size());
104-
}
105-
106-
@Test
107-
public void fromParamWithQualifiedUriColumn() {
108-
ArrayNode paramValue = mapper.createArrayNode();
109-
paramValue.addObject().put("myUri", "/optic/test/musician1.json");
110-
111-
List<RowRecord> rows = resultRows(op
112-
.fromParam("bindingParam", "myQualifier", op.colTypes(op.colType("myUri", "string")))
113-
.lockForUpdate(op.viewCol("myQualifier", "myUri"))
114-
.bindParam("bindingParam", new JacksonHandle(paramValue), null));
115-
assertEquals(1, rows.size());
116-
}
61+
// Verify that the collections were set based on the plan, which should have run second
62+
verifyMetadata(uri, metadata -> {
63+
DocumentMetadataHandle.DocumentCollections colls = metadata.getCollections();
64+
assertEquals(1, colls.size());
65+
assertEquals("optic1", colls.iterator().next());
66+
});
67+
}
68+
69+
@Test
70+
public void uriColumnSpecified() {
71+
List<RowRecord> rows = resultRows(op
72+
.fromDocUris("/optic/test/musician1.json")
73+
.lockForUpdate(op.col("uri")));
74+
assertEquals(1, rows.size());
75+
}
76+
77+
@Test
78+
public void fromParamWithCustomUriColumn() {
79+
ArrayNode paramValue = mapper.createArrayNode();
80+
paramValue.addObject().put("myUri", "/optic/test/musician1.json");
81+
82+
List<RowRecord> rows = resultRows(op
83+
.fromParam("bindingParam", "", op.colTypes(op.colType("myUri", "string")))
84+
.lockForUpdate(op.col("myUri"))
85+
.bindParam("bindingParam", new JacksonHandle(paramValue), null));
86+
assertEquals(1, rows.size());
87+
}
88+
89+
@Test
90+
public void fromParamWithQualifiedUriColumn() {
91+
ArrayNode paramValue = mapper.createArrayNode();
92+
paramValue.addObject().put("myUri", "/optic/test/musician1.json");
93+
94+
List<RowRecord> rows = resultRows(op
95+
.fromParam("bindingParam", "myQualifier", op.colTypes(op.colType("myUri", "string")))
96+
.lockForUpdate(op.viewCol("myQualifier", "myUri"))
97+
.bindParam("bindingParam", new JacksonHandle(paramValue), null));
98+
assertEquals(1, rows.size());
99+
}
117100
}

marklogic-client-api/src/test/java/com/marklogic/client/test/rows/ResultRowsWithTimestampTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ void deleteNewMusician() {
3232

3333
@Test
3434
void testResultRowsWithPointInTimeQueryTimestamp() {
35-
rowManager.withUpdate(false);
36-
3735
final RawQueryDSLPlan plan = rowManager.newRawQueryDSLPlan(new StringHandle("op.fromView('opticUnitTest', 'musician_ml10')"));
3836

3937
JacksonHandle result = new JacksonHandle();

0 commit comments

Comments
 (0)