|
1 | 1 | package com.marklogic.client.test.rows; |
2 | 2 |
|
3 | 3 | import com.fasterxml.jackson.databind.node.ArrayNode; |
4 | | -import com.marklogic.client.FailedRequestException; |
5 | 4 | import com.marklogic.client.expression.PlanBuilder; |
6 | 5 | import com.marklogic.client.io.DocumentMetadataHandle; |
7 | 6 | import com.marklogic.client.io.JacksonHandle; |
|
13 | 12 |
|
14 | 13 | import java.util.List; |
15 | 14 |
|
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; |
17 | 17 |
|
18 | 18 | @ExtendWith(RequiresML11.class) |
19 | 19 | public class LockForUpdateTest extends AbstractOpticUpdateTest { |
20 | 20 |
|
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, |
57 | 57 | "Because the eval call slept for 2 seconds, the duration of the plan execution should be at least " + |
58 | 58 | "1500ms, which is much longer than normal; it may not be at least 2 seconds due to the small delay in " + |
59 | 59 | "the Java layer of executing the plan; duration: " + duration); |
60 | 60 |
|
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 | + } |
117 | 100 | } |
0 commit comments