com.couchbase.client.core.io.netty.view.ViewChunkResponseParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-io Show documentation
Show all versions of core-io Show documentation
The official Couchbase JVM Core IO Library
/*
* Copyright (c) 2019 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.couchbase.client.core.io.netty.view;
import com.couchbase.client.core.error.CouchbaseException;
import com.couchbase.client.core.error.context.ViewErrorContext;
import com.couchbase.client.core.error.ViewNotFoundException;
import com.couchbase.client.core.io.netty.HttpProtocol;
import com.couchbase.client.core.io.netty.chunk.BaseChunkResponseParser;
import com.couchbase.client.core.json.stream.JsonStreamParser;
import com.couchbase.client.core.msg.ResponseStatus;
import com.couchbase.client.core.msg.view.ViewChunkHeader;
import com.couchbase.client.core.msg.view.ViewChunkRow;
import com.couchbase.client.core.msg.view.ViewChunkTrailer;
import com.couchbase.client.core.msg.view.ViewError;
import java.util.Optional;
/**
* Parses the individual response http chunks for a view request.
*/
public class ViewChunkResponseParser
extends BaseChunkResponseParser {
/**
* If present in non-reduce results, holds the total rows.
*/
private long totalRows;
/**
* If enabled at request time, holds detailed debug information.
*/
private Optional debug;
/**
* If an error happened during server request handling, will hold this error.
*/
private Optional error;
private final JsonStreamParser.Builder parserBuilder = JsonStreamParser.builder()
.doOnValue("/debug_info", v -> debug = Optional.of(v.readBytes()))
.doOnValue("/total_rows", v -> {
markHeaderComplete();
totalRows = v.readLong();
})
.doOnValue("/rows/-", v -> {
markHeaderComplete();
emitRow(new ViewChunkRow(v.readBytes()));
})
.doOnValue("/error", v -> {
markHeaderComplete();
String data = v.readString();
ViewError current = error.orElse(new ViewError(null, null));
error = Optional.of(new ViewError(data, current.reason()));
})
.doOnValue("/reason", v -> {
String data = v.readString();
ViewError current = error.orElse(new ViewError(null, null));
error = Optional.of(new ViewError(current.error(), data));
});
@Override
protected JsonStreamParser.Builder parserBuilder() {
return parserBuilder;
}
@Override
protected void doCleanup() {
totalRows = 0;
debug = Optional.empty();
error = Optional.empty();
}
@Override
public Optional header(boolean lastChunk) {
return isHeaderComplete() || lastChunk
? Optional.of(new ViewChunkHeader(totalRows, debug))
: Optional.empty();
}
@Override
public Optional error() {
return error.map(e -> {
int httpStatus = responseHeader().status().code();
ResponseStatus responseStatus = HttpProtocol.decodeStatus(responseHeader().status());
ViewErrorContext errorContext = new ViewErrorContext(responseStatus, requestContext(), e, httpStatus);
if (responseStatus == ResponseStatus.NOT_FOUND || e.error().equals("not_found") || e.reason().contains("not_found")) {
return new ViewNotFoundException(errorContext);
}
return new CouchbaseException("Unknown view error: " + e.toString(), errorContext);
});
}
@Override
public void signalComplete() {
Optional maybeError = error();
if (maybeError.isPresent()) {
failRows(maybeError.get());
} else {
completeRows();
}
completeTrailer(new ViewChunkTrailer(error));
}
}