use of net.morimekta.providence.PServiceCall in project providence by morimekta.
the class SocketServer method process.
@SuppressWarnings("unchecked")
private void process(long startTime, Socket socket) {
try (Socket ignore = socket;
BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
BufferedOutputStream out = new BufferedOutputStream(socket.getOutputStream());
IOMessageReader reader = new IOMessageReader(in, serializer);
IOMessageWriter writer = new IOMessageWriter(out, serializer)) {
while (socket.isConnected()) {
AtomicReference<PServiceCall> callRef = new AtomicReference<>();
AtomicReference<PServiceCall> responseRef = new AtomicReference<>();
try {
DefaultProcessorHandler handler = new DefaultProcessorHandler(new WrappedProcessor(processor, (c, p) -> {
callRef.set(c);
responseRef.set(p.handleCall(c));
return responseRef.get();
}));
handler.process(reader, writer);
out.flush();
long endTime = System.nanoTime();
double duration = ((double) (endTime - startTime)) / NS_IN_MILLIS;
try {
instrumentation.onComplete(duration, callRef.get(), responseRef.get());
} catch (Throwable th) {
LOGGER.error("Exception in service instrumentation", th);
}
} catch (IOException e) {
long endTime = System.nanoTime();
double duration = ((double) (endTime - startTime)) / NS_IN_MILLIS;
try {
instrumentation.onTransportException(e, duration, callRef.get(), responseRef.get());
} catch (Throwable th) {
LOGGER.error("Exception in service instrumentation", th);
}
throw new UncheckedIOException(e.getMessage(), e);
}
in.mark(1);
if (in.read() < 0) {
return;
}
in.reset();
startTime = System.nanoTime();
}
} catch (IOException e) {
throw new UncheckedIOException(e.getMessage(), e);
}
}
use of net.morimekta.providence.PServiceCall in project providence by morimekta.
the class HttpClientHandlerTest method testBadResponse.
@Test
@SuppressWarnings("unchecked")
public void testBadResponse() throws IOException, Failure {
TestService.Iface client = new TestService.Client(new HttpClientHandler(this::html));
try {
client.test(new Request("request"));
fail("no exception");
} catch (PApplicationException e) {
assertThat(e.getMessage(), is("Unknown content-type in response: text/html;charset=utf-8"));
assertThat(e.getId(), is(PApplicationExceptionType.INVALID_PROTOCOL));
}
client = new TestService.Client(new HttpClientHandler(this::response));
reply.set(new PServiceCall("foo", PServiceCallType.REPLY, 1, new TestServiceBypass().testResponse("foo")));
try {
client.test(new Request("request"));
fail("no exception");
} catch (SerializerException e) {
assertThat(e.getMessage(), is("No such method foo on client.TestService"));
assertThat(e.getExceptionType(), is(PApplicationExceptionType.UNKNOWN_METHOD));
assertThat(e.getMethodName(), is("foo"));
assertThat(e.getSequenceNo(), is(1));
}
reply.set(new PServiceCall("test", PServiceCallType.CALL, 2, new TestServiceBypass().testResponse("bar")));
try {
client.test(new Request("request"));
fail("no exception");
} catch (PApplicationException e) {
assertThat(e.getMessage(), is("Reply with invalid call type: CALL"));
assertThat(e.getId(), is(PApplicationExceptionType.INVALID_MESSAGE_TYPE));
}
reply.set(new PServiceCall("test", PServiceCallType.REPLY, 100, new TestServiceBypass().testResponse("baz")));
try {
client.test(new Request("request"));
fail("no exception");
} catch (PApplicationException e) {
assertThat(e.getMessage(), is("Reply sequence out of order: call = 2, reply = 100"));
assertThat(e.getId(), is(PApplicationExceptionType.BAD_SEQUENCE_ID));
}
reply.set(new PServiceCall("test", PServiceCallType.REPLY, 4, new PApplicationException("foo", PApplicationExceptionType.INTERNAL_ERROR)));
try {
client.test(new Request("request"));
fail("no exception");
} catch (SerializerException e) {
assertThat(e.getMessage(), is("Wrong type string(11) for client.TestService.test.response.fail, should be struct(12)"));
assertThat(e.getExceptionType(), is(PApplicationExceptionType.PROTOCOL_ERROR));
assertThat(e.getMethodName(), is("test"));
assertThat(e.getSequenceNo(), is(4));
}
}
use of net.morimekta.providence.PServiceCall in project providence by morimekta.
the class DefaultProcessorHandler method process.
@Override
@SuppressWarnings("unchecked")
public void process(MessageReader reader, MessageWriter writer) throws IOException {
PServiceCall call, reply;
try {
call = reader.read(processor.getDescriptor());
} catch (SerializerException e) {
if (e.getMethodName() != null) {
LOGGER.error("Error when reading service call " + processor.getDescriptor().getName() + "." + e.getMethodName() + "()", e);
} else {
LOGGER.error("Error when reading service call " + processor.getDescriptor().getName(), e);
}
try {
PApplicationException oe = new PApplicationException(e.getMessage(), e.getExceptionType());
reply = new PServiceCall<>(e.getMethodName(), PServiceCallType.EXCEPTION, e.getSequenceNo(), oe);
writer.write(reply);
return;
} catch (Exception e2) {
e.addSuppressed(e2);
throw e;
}
}
if (call.getType() == PServiceCallType.REPLY || call.getType() == PServiceCallType.EXCEPTION) {
try {
PApplicationException oe = new PApplicationException("Invalid service request call type: " + call.getType(), PApplicationExceptionType.INVALID_MESSAGE_TYPE);
reply = new PServiceCall(call.getMethod(), PServiceCallType.EXCEPTION, call.getSequence(), oe);
writer.write(reply);
return;
} catch (Exception e) {
throw new IOException("Unable to write error response", e);
}
}
try {
reply = processor.handleCall(call);
} catch (Exception e) {
LOGGER.error("Error when handling service call " + processor.getDescriptor().getName() + "." + call.getMethod() + "()", e);
try {
PApplicationException oe = new PApplicationException(e.getMessage(), PApplicationExceptionType.INTERNAL_ERROR);
reply = new PServiceCall<>(call.getMethod(), PServiceCallType.EXCEPTION, call.getSequence(), oe);
writer.write(reply);
return;
} catch (Exception e2) {
e.addSuppressed(e2);
throw e;
}
}
if (reply != null) {
try {
writer.write(reply);
} catch (SerializerException e) {
LOGGER.error("Error when replying to service call " + processor.getDescriptor().getName() + "." + call.getMethod() + "()", e);
try {
PApplicationException oe = new PApplicationException(e.getMessage(), e.getExceptionType());
reply = new PServiceCall<>(call.getMethod(), PServiceCallType.EXCEPTION, call.getSequence(), oe);
writer.write(reply);
} catch (Exception e2) {
e.addSuppressed(e2);
throw e;
}
}
}
}
use of net.morimekta.providence.PServiceCall in project providence by morimekta.
the class RPC method run.
@SuppressWarnings("unchecked")
void run(String... args) {
try {
ArgumentParser cli = options.getArgumentParser("pvdrpc", "Providence RPC Tool");
try {
cli.parse(args);
if (options.showHelp()) {
System.out.println("Providence RPC Tool - " + getVersionString());
System.out.println("Usage: " + cli.getSingleLineUsage());
System.out.println();
System.out.println("Example code to run:");
System.out.println("$ cat call.json | pvdrpc -I thrift/ -s cal.Calculator http://localhost:8080/service");
System.out.println("$ pvdrpc -i binary,file:my.data -f json_protocol -I thrift/ -s cal.Calculator http://localhost:8080/service");
System.out.println();
cli.printUsage(System.out);
System.out.println();
System.out.println("Available formats are:");
for (Format format : Format.values()) {
System.out.println(String.format(" - %-20s : %s", format.name(), format.desc));
}
return;
} else if (options.showVersion()) {
System.out.println("Providence RPC Tool - " + getVersionString());
return;
}
cli.validate();
MessageReader in = options.getInput();
MessageWriter out = options.getOutput();
PService service = options.getDefinition();
PServiceCallHandler handler = options.getHandler();
PServiceCall call = in.read(service);
in.close();
PServiceCall resp = handler.handleCall(call, service);
out.write(resp);
out.separator();
out.close();
if (options.out.base64mime && options.out.file == null) {
System.out.println();
}
return;
} catch (ConnectException e) {
System.out.flush();
System.err.format("Unable to connect to %s: %s%n", options.endpoint, e.getMessage());
if (options.verbose()) {
System.err.println();
e.printStackTrace();
}
} catch (HttpResponseException e) {
System.out.flush();
System.err.println("Received " + e.getStatusCode() + " " + e.getStatusMessage());
System.err.println(" - from: " + options.endpoint);
if (options.verbose()) {
System.err.println();
e.printStackTrace();
}
} catch (ArgumentException e) {
System.out.flush();
System.err.println(e.getMessage());
System.err.println("Usage: " + cli.getSingleLineUsage());
System.err.println();
System.err.println("Run $ pvdrpc --help # for available options.");
} catch (SerializerException e) {
System.out.flush();
System.err.println("Serializer error: " + e.asString());
if (options.verbose()) {
System.err.println();
e.printStackTrace();
}
} catch (UncheckedIOException | IOException e) {
System.out.flush();
System.err.println("I/O error: " + e.getMessage());
if (options.verbose()) {
System.out.flush();
e.printStackTrace();
}
} catch (IllegalArgumentException e) {
System.out.flush();
System.err.println("Internal Error: " + e.getMessage());
if (options.verbose()) {
System.err.println();
e.printStackTrace();
}
}
} catch (RuntimeException | IOException e) {
System.out.flush();
System.err.println("Unchecked exception: " + e.getMessage());
if (options.verbose()) {
System.out.flush();
e.printStackTrace();
}
}
System.err.flush();
exit(1);
}
use of net.morimekta.providence.PServiceCall in project providence by morimekta.
the class PrettySerializer method deserialize.
@Nonnull
@Override
@SuppressWarnings("unchecked")
public <Message extends PMessage<Message, Field>, Field extends PField> PServiceCall<Message, Field> deserialize(@Nonnull InputStream input, @Nonnull PService service) throws IOException {
String methodName = null;
int sequence = 0;
PServiceCallType callType = null;
try {
// pretty printed service calls cannot be chained-serialized, so this should be totally safe.
Tokenizer tokenizer = new Tokenizer(input);
Token token = tokenizer.expect("Sequence or type");
if (token.isInteger()) {
sequence = (int) token.parseInteger();
tokenizer.expectSymbol("Sequence type sep", Token.kKeyValueSep);
token = tokenizer.expectIdentifier("Call Type");
}
callType = PServiceCallType.findByName(token.asString().toUpperCase(Locale.US));
if (callType == null) {
throw new TokenizerException(token, "No such call type %s", token.asString()).setLine(tokenizer.getLine()).setExceptionType(PApplicationExceptionType.INVALID_MESSAGE_TYPE);
}
token = tokenizer.expectIdentifier("method name");
methodName = token.asString();
PServiceMethod method = service.getMethod(methodName);
if (method == null) {
throw new TokenizerException(token, "no such method %s on service %s", methodName, service.getQualifiedName()).setLine(tokenizer.getLine()).setExceptionType(PApplicationExceptionType.UNKNOWN_METHOD);
}
tokenizer.expectSymbol("call params start", Token.kParamsStart);
Message message;
switch(callType) {
case CALL:
case ONEWAY:
message = (Message) readMessage(tokenizer, method.getRequestType(), true);
break;
case REPLY:
message = (Message) readMessage(tokenizer, method.getResponseType(), true);
break;
case EXCEPTION:
message = (Message) readMessage(tokenizer, PApplicationException.kDescriptor, true);
break;
default:
throw new IllegalStateException("Unreachable code reached");
}
return new PServiceCall<>(methodName, callType, sequence, message);
} catch (TokenizerException e) {
e.setCallType(callType).setSequenceNo(sequence).setMethodName(methodName);
throw e;
} catch (IOException e) {
throw new SerializerException(e, e.getMessage()).setCallType(callType).setSequenceNo(sequence).setMethodName(methodName);
}
}
Aggregations