Search in sources :

Example 6 with PServiceCall

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);
    }
}
Also used : ThreadFactoryBuilder(com.google.common.util.concurrent.ThreadFactoryBuilder) Socket(java.net.Socket) BufferedInputStream(java.io.BufferedInputStream) DefaultProcessorHandler(net.morimekta.providence.server.DefaultProcessorHandler) LoggerFactory(org.slf4j.LoggerFactory) BinarySerializer(net.morimekta.providence.serializer.BinarySerializer) AtomicReference(java.util.concurrent.atomic.AtomicReference) IOMessageWriter(net.morimekta.providence.mio.IOMessageWriter) BufferedOutputStream(java.io.BufferedOutputStream) ServerSocket(java.net.ServerSocket) PProcessor(net.morimekta.providence.PProcessor) SocketTimeoutException(java.net.SocketTimeoutException) NS_IN_MILLIS(net.morimekta.providence.util.ServiceCallInstrumentation.NS_IN_MILLIS) WrappedProcessor(net.morimekta.providence.server.WrappedProcessor) ThreadFactory(java.util.concurrent.ThreadFactory) Nonnull(javax.annotation.Nonnull) ExecutorService(java.util.concurrent.ExecutorService) Serializer(net.morimekta.providence.serializer.Serializer) Logger(org.slf4j.Logger) IOException(java.io.IOException) InetSocketAddress(java.net.InetSocketAddress) ServiceCallInstrumentation(net.morimekta.providence.util.ServiceCallInstrumentation) Executors(java.util.concurrent.Executors) UncheckedIOException(java.io.UncheckedIOException) TimeUnit(java.util.concurrent.TimeUnit) PServiceCall(net.morimekta.providence.PServiceCall) IOMessageReader(net.morimekta.providence.mio.IOMessageReader) DefaultProcessorHandler(net.morimekta.providence.server.DefaultProcessorHandler) IOMessageReader(net.morimekta.providence.mio.IOMessageReader) AtomicReference(java.util.concurrent.atomic.AtomicReference) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) IOMessageWriter(net.morimekta.providence.mio.IOMessageWriter) BufferedInputStream(java.io.BufferedInputStream) WrappedProcessor(net.morimekta.providence.server.WrappedProcessor) PServiceCall(net.morimekta.providence.PServiceCall) BufferedOutputStream(java.io.BufferedOutputStream) Socket(java.net.Socket) ServerSocket(java.net.ServerSocket)

Example 7 with PServiceCall

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));
    }
}
Also used : TestService(net.morimekta.test.providence.client.TestService) PApplicationException(net.morimekta.providence.PApplicationException) PServiceCall(net.morimekta.providence.PServiceCall) HttpServletRequest(javax.servlet.http.HttpServletRequest) Request(net.morimekta.test.providence.client.Request) SerializerException(net.morimekta.providence.serializer.SerializerException) Test(org.junit.Test)

Example 8 with PServiceCall

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;
            }
        }
    }
}
Also used : PServiceCall(net.morimekta.providence.PServiceCall) PApplicationException(net.morimekta.providence.PApplicationException) IOException(java.io.IOException) SerializerException(net.morimekta.providence.serializer.SerializerException) PApplicationException(net.morimekta.providence.PApplicationException) IOException(java.io.IOException) SerializerException(net.morimekta.providence.serializer.SerializerException)

Example 9 with PServiceCall

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);
}
Also used : MessageReader(net.morimekta.providence.mio.MessageReader) HttpResponseException(com.google.api.client.http.HttpResponseException) UncheckedIOException(java.io.UncheckedIOException) IOException(java.io.IOException) UncheckedIOException(java.io.UncheckedIOException) ArgumentParser(net.morimekta.console.args.ArgumentParser) SerializerException(net.morimekta.providence.serializer.SerializerException) Format(net.morimekta.providence.tools.common.formats.Format) PServiceCallHandler(net.morimekta.providence.PServiceCallHandler) PServiceCall(net.morimekta.providence.PServiceCall) MessageWriter(net.morimekta.providence.mio.MessageWriter) ArgumentException(net.morimekta.console.args.ArgumentException) PService(net.morimekta.providence.descriptor.PService) ConnectException(java.net.ConnectException)

Example 10 with PServiceCall

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);
    }
}
Also used : PMessage(net.morimekta.providence.PMessage) PServiceCallType(net.morimekta.providence.PServiceCallType) PServiceCall(net.morimekta.providence.PServiceCall) Token(net.morimekta.providence.serializer.pretty.Token) TokenizerException(net.morimekta.providence.serializer.pretty.TokenizerException) IOException(java.io.IOException) Tokenizer(net.morimekta.providence.serializer.pretty.Tokenizer) PServiceMethod(net.morimekta.providence.descriptor.PServiceMethod) Nonnull(javax.annotation.Nonnull)

Aggregations

PServiceCall (net.morimekta.providence.PServiceCall)19 IOException (java.io.IOException)13 PApplicationException (net.morimekta.providence.PApplicationException)12 PServiceCallType (net.morimekta.providence.PServiceCallType)7 PServiceMethod (net.morimekta.providence.descriptor.PServiceMethod)7 Nonnull (javax.annotation.Nonnull)6 PMessage (net.morimekta.providence.PMessage)6 SerializerException (net.morimekta.providence.serializer.SerializerException)6 UncheckedIOException (java.io.UncheckedIOException)5 PField (net.morimekta.providence.descriptor.PField)5 Test (org.junit.Test)5 PProcessor (net.morimekta.providence.PProcessor)4 PService (net.morimekta.providence.descriptor.PService)4 ByteArrayOutputStream (java.io.ByteArrayOutputStream)3 AtomicReference (java.util.concurrent.atomic.AtomicReference)3 ExecutionException (java.util.concurrent.ExecutionException)2 ExecutorService (java.util.concurrent.ExecutorService)2 TimeoutException (java.util.concurrent.TimeoutException)2 Nullable (javax.annotation.Nullable)2 PServiceCallHandler (net.morimekta.providence.PServiceCallHandler)2