diff options
Diffstat (limited to 'vespaclient-container-plugin')
2 files changed, 84 insertions, 30 deletions
diff --git a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java index 7f940e5695a..26ef157c5ae 100644 --- a/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java +++ b/vespaclient-container-plugin/src/main/java/com/yahoo/document/restapi/resource/DocumentV1ApiHandler.java @@ -20,7 +20,6 @@ import com.yahoo.document.DocumentUpdate; import com.yahoo.document.FixedBucketSpaces; import com.yahoo.document.TestAndSetCondition; import com.yahoo.document.config.DocumentmanagerConfig; -import com.yahoo.document.fieldset.AllFields; import com.yahoo.document.fieldset.DocIdOnly; import com.yahoo.document.fieldset.DocumentOnly; import com.yahoo.document.idstring.IdIdString; @@ -169,6 +168,7 @@ public class DocumentV1ApiHandler extends AbstractRequestHandler { private static final String STREAM = "stream"; private static final String SLICES = "slices"; private static final String SLICE_ID = "sliceId"; + private static final String DRY_RUN = "dryRun"; private final Clock clock; private final Duration handlerTimeout; @@ -442,6 +442,11 @@ public class DocumentV1ApiHandler extends AbstractRequestHandler { private ContentChannel postDocument(HttpRequest request, DocumentPath path, ResponseHandler rawHandler) { ResponseHandler handler = new MeasuringResponseHandler(rawHandler, com.yahoo.documentapi.metrics.DocumentOperationType.PUT, clock.instant()); + if (getProperty(request, DRY_RUN, booleanParser).orElse(false)) { + handleFeedOperation(path, handler, new com.yahoo.documentapi.Response(-1)); + return ignoredContent; + } + return new ForwardingContentChannel(in -> { enqueueAndDispatch(request, handler, () -> { DocumentPut put = parser.parsePut(in, path.id().toString()); @@ -459,6 +464,11 @@ public class DocumentV1ApiHandler extends AbstractRequestHandler { private ContentChannel putDocument(HttpRequest request, DocumentPath path, ResponseHandler rawHandler) { ResponseHandler handler = new MeasuringResponseHandler(rawHandler, com.yahoo.documentapi.metrics.DocumentOperationType.UPDATE, clock.instant()); + if (getProperty(request, DRY_RUN, booleanParser).orElse(false)) { + handleFeedOperation(path, handler, new com.yahoo.documentapi.Response(-1)); + return ignoredContent; + } + return new ForwardingContentChannel(in -> { enqueueAndDispatch(request, handler, () -> { DocumentUpdate update = parser.parseUpdate(in, path.id().toString()); @@ -477,6 +487,11 @@ public class DocumentV1ApiHandler extends AbstractRequestHandler { private ContentChannel deleteDocument(HttpRequest request, DocumentPath path, ResponseHandler rawHandler) { ResponseHandler handler = new MeasuringResponseHandler(rawHandler, com.yahoo.documentapi.metrics.DocumentOperationType.REMOVE, clock.instant()); + if (getProperty(request, DRY_RUN, booleanParser).orElse(false)) { + handleFeedOperation(path, handler, new com.yahoo.documentapi.Response(-1)); + return ignoredContent; + } + enqueueAndDispatch(request, handler, () -> { DocumentRemove remove = new DocumentRemove(path.id()); getProperty(request, CONDITION).map(TestAndSetCondition::new).ifPresent(remove::setCondition); @@ -1062,19 +1077,19 @@ public class DocumentV1ApiHandler extends AbstractRequestHandler { private void updatePutMetrics(Outcome outcome) { switch (outcome) { - case SUCCESS: metric.add(MetricNames.SUCCEEDED, 1, null); break; - case CONDITION_FAILED: metric.add(MetricNames.CONDITION_NOT_MET, 1, null); break; - default: metric.add(MetricNames.FAILED, 1, null); break; + case SUCCESS -> metric.add(MetricNames.SUCCEEDED, 1, null); + case CONDITION_FAILED -> metric.add(MetricNames.CONDITION_NOT_MET, 1, null); + default -> metric.add(MetricNames.FAILED, 1, null); } } private void updateUpdateMetrics(Outcome outcome, boolean create) { if (create && outcome == Outcome.NOT_FOUND) outcome = Outcome.SUCCESS; // >_< switch (outcome) { - case SUCCESS: metric.add(MetricNames.SUCCEEDED, 1, null); break; - case NOT_FOUND: metric.add(MetricNames.NOT_FOUND, 1, null); break; - case CONDITION_FAILED: metric.add(MetricNames.CONDITION_NOT_MET, 1, null); break; - default: metric.add(MetricNames.FAILED, 1, null); break; + case SUCCESS -> metric.add(MetricNames.SUCCEEDED, 1, null); + case NOT_FOUND -> metric.add(MetricNames.NOT_FOUND, 1, null); + case CONDITION_FAILED -> metric.add(MetricNames.CONDITION_NOT_MET, 1, null); + default -> metric.add(MetricNames.FAILED, 1, null); } } diff --git a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/DocumentV1ApiTest.java b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/DocumentV1ApiTest.java index 74a86b6a7b7..baedae5f580 100644 --- a/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/DocumentV1ApiTest.java +++ b/vespaclient-container-plugin/src/test/java/com/yahoo/document/restapi/resource/DocumentV1ApiTest.java @@ -524,6 +524,67 @@ public class DocumentV1ApiTest { "}", response.readAll()); assertEquals(404, response.getStatus()); + // POST with speedTest=true returns an immediate OK response + access.session.expect((__, ___) -> { + fail("Should not cause an actual feed operation"); + return null; + }); + response = driver.sendRequest("http://localhost/document/v1/space/music/number/1/two?dryRun=true", POST, + "NOT JSON, NOT PARSED"); + assertSameJson("{" + + " \"pathId\": \"/document/v1/space/music/number/1/two\"," + + " \"id\": \"id:space:music:n=1:two\"" + + "}", response.readAll()); + assertEquals(200, response.getStatus()); + + // PUT with speedTest=true returns an immediate OK response + access.session.expect((__, ___) -> { + fail("Should not cause an actual feed operation"); + return null; + }); + response = driver.sendRequest("http://localhost/document/v1/space/music/number/1/two?dryRun=true", PUT, + "NOT JSON, NOT PARSED"); + assertSameJson("{" + + " \"pathId\": \"/document/v1/space/music/number/1/two\"," + + " \"id\": \"id:space:music:n=1:two\"" + + "}", response.readAll()); + assertEquals(200, response.getStatus()); + + // DELETE with speedTest=true returns an immediate OK response + access.session.expect((__, ___) -> { + fail("Should not cause an actual feed operation"); + return null; + }); + response = driver.sendRequest("http://localhost/document/v1/space/music/number/1/two?dryRun=true", DELETE, + "NOT JSON, NOT PARSED"); + assertSameJson("{" + + " \"pathId\": \"/document/v1/space/music/number/1/two\"," + + " \"id\": \"id:space:music:n=1:two\"" + + "}", response.readAll()); + assertEquals(200, response.getStatus()); + + // PUT with a document update payload is a document update operation. + access.session.expect((update, parameters) -> { + DocumentUpdate expectedUpdate = new DocumentUpdate(doc3.getDataType(), doc3.getId()); + expectedUpdate.addFieldUpdate(FieldUpdate.createAssign(doc3.getField("artist"), new StringFieldValue("Lisa Ekdahl"))); + expectedUpdate.setCreateIfNonExistent(true); + assertEquals(expectedUpdate, update); + assertEquals(parameters(), parameters); + parameters.responseHandler().get().handleResponse(new UpdateResponse(0, true)); + return new Result(); + }); + response = driver.sendRequest("http://localhost/document/v1/space/music/group/a/three?create=true&timeout=1e1s&dryRun=false", PUT, + "{" + + " \"fields\": {" + + " \"artist\": { \"assign\": \"Lisa Ekdahl\" }" + + " }" + + "}"); + assertSameJson("{" + + " \"pathId\": \"/document/v1/space/music/group/a/three\"," + + " \"id\": \"id:space:music:g=a:three\"" + + "}", response.readAll()); + assertEquals(200, response.getStatus()); + // POST with a document payload is a document put operation. access.session.expect((put, parameters) -> { DocumentPut expectedPut = new DocumentPut(doc2); @@ -566,28 +627,6 @@ public class DocumentV1ApiTest { "}", response.readAll()); assertEquals(200, response.getStatus()); - // PUT with a document update payload is a document update operation. - access.session.expect((update, parameters) -> { - DocumentUpdate expectedUpdate = new DocumentUpdate(doc3.getDataType(), doc3.getId()); - expectedUpdate.addFieldUpdate(FieldUpdate.createAssign(doc3.getField("artist"), new StringFieldValue("Lisa Ekdahl"))); - expectedUpdate.setCreateIfNonExistent(true); - assertEquals(expectedUpdate, update); - assertEquals(parameters(), parameters); - parameters.responseHandler().get().handleResponse(new UpdateResponse(0, true)); - return new Result(); - }); - response = driver.sendRequest("http://localhost/document/v1/space/music/group/a/three?create=true&timeout=1e1s", PUT, - "{" + - " \"fields\": {" + - " \"artist\": { \"assign\": \"Lisa Ekdahl\" }" + - " }" + - "}"); - assertSameJson("{" + - " \"pathId\": \"/document/v1/space/music/group/a/three\"," + - " \"id\": \"id:space:music:g=a:three\"" + - "}", response.readAll()); - assertEquals(200, response.getStatus()); - // POST with no payload is a 400 access.session.expect((__, ___) -> { throw new AssertionError("Not supposed to happen"); }); response = driver.sendRequest("http://localhost/document/v1/space/music/number/1/two?condition=test%20it", POST, ""); |