Search in sources :

Example 1 with FunctionConfig

use of org.apache.pulsar.functions.proto.Function.FunctionConfig in project incubator-pulsar by apache.

the class FunctionsImpl method getFunction.

@Override
public FunctionConfig getFunction(String tenant, String namespace, String function) throws PulsarAdminException {
    try {
        Response response = request(functions.path(tenant).path(namespace).path(function)).get();
        if (!response.getStatusInfo().equals(Response.Status.OK)) {
            throw new ClientErrorException(response);
        }
        String jsonResponse = response.readEntity(String.class);
        FunctionConfig.Builder functionConfigBuilder = FunctionConfig.newBuilder();
        Utils.mergeJson(jsonResponse, functionConfigBuilder);
        return functionConfigBuilder.build();
    } catch (Exception e) {
        throw getApiException(e);
    }
}
Also used : Response(javax.ws.rs.core.Response) FunctionConfig(org.apache.pulsar.functions.proto.Function.FunctionConfig) ClientErrorException(javax.ws.rs.ClientErrorException) PulsarAdminException(org.apache.pulsar.client.admin.PulsarAdminException) ClientErrorException(javax.ws.rs.ClientErrorException)

Example 2 with FunctionConfig

use of org.apache.pulsar.functions.proto.Function.FunctionConfig in project incubator-pulsar by apache.

the class FunctionApiV2ResourceTest method testGetFunctionSuccess.

@Test
public void testGetFunctionSuccess() throws Exception {
    when(mockedManager.containsFunction(eq(tenant), eq(namespace), eq(function))).thenReturn(true);
    FunctionConfig functionConfig = FunctionConfig.newBuilder().setClassName(className).putCustomSerdeInputs(inputTopic, inputSerdeClassName).setOutputSerdeClassName(outputSerdeClassName).setName(function).setNamespace(namespace).setProcessingGuarantees(FunctionConfig.ProcessingGuarantees.ATMOST_ONCE).setOutput(outputTopic).setTenant(tenant).setParallelism(parallelism).build();
    FunctionMetaData metaData = FunctionMetaData.newBuilder().setCreateTime(System.currentTimeMillis()).setFunctionConfig(functionConfig).setPackageLocation(PackageLocationMetaData.newBuilder().setPackagePath("/path/to/package")).setVersion(1234).build();
    when(mockedManager.getFunctionMetaData(eq(tenant), eq(namespace), eq(function))).thenReturn(metaData);
    Response response = getDefaultFunctionInfo();
    assertEquals(Status.OK.getStatusCode(), response.getStatus());
    assertEquals(org.apache.pulsar.functions.utils.Utils.printJson(functionConfig), response.getEntity());
}
Also used : FunctionConfig(org.apache.pulsar.functions.proto.Function.FunctionConfig) FunctionMetaData(org.apache.pulsar.functions.proto.Function.FunctionMetaData) Response(javax.ws.rs.core.Response) Test(org.testng.annotations.Test) PrepareForTest(org.powermock.core.classloader.annotations.PrepareForTest)

Example 3 with FunctionConfig

use of org.apache.pulsar.functions.proto.Function.FunctionConfig in project incubator-pulsar by apache.

the class FunctionApiV2ResourceTest method testRegisterFunctionMissingArguments.

private void testRegisterFunctionMissingArguments(String tenant, String namespace, String function, InputStream inputStream, FormDataContentDisposition details, String outputTopic, String inputTopic, String inputSerdeClassName, String outputSerdeClassName, String className, Integer parallelism, String missingFieldName) throws IOException {
    FunctionConfig.Builder functionConfigBuilder = FunctionConfig.newBuilder();
    if (tenant != null) {
        functionConfigBuilder.setTenant(tenant);
    }
    if (namespace != null) {
        functionConfigBuilder.setNamespace(namespace);
    }
    if (function != null) {
        functionConfigBuilder.setName(function);
    }
    if (outputTopic != null) {
        functionConfigBuilder.setOutput(outputTopic);
    }
    if (inputTopic != null && inputSerdeClassName != null) {
        functionConfigBuilder.putCustomSerdeInputs(inputTopic, inputSerdeClassName);
    }
    if (outputSerdeClassName != null) {
        functionConfigBuilder.setOutputSerdeClassName(outputSerdeClassName);
    }
    if (className != null) {
        functionConfigBuilder.setClassName(className);
    }
    if (parallelism != null) {
        functionConfigBuilder.setParallelism(parallelism);
    }
    FunctionConfig functionConfig = functionConfigBuilder.build();
    Response response = resource.registerFunction(tenant, namespace, function, inputStream, details, org.apache.pulsar.functions.utils.Utils.printJson(functionConfig));
    assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
    if (missingFieldName.equals("parallelism")) {
        Assert.assertEquals(new ErrorData("Parallelism needs to be set to a positive number").reason, ((ErrorData) response.getEntity()).reason);
    } else {
        Assert.assertEquals(new ErrorData(missingFieldName + " is not provided").reason, ((ErrorData) response.getEntity()).reason);
    }
}
Also used : FunctionConfig(org.apache.pulsar.functions.proto.Function.FunctionConfig) Response(javax.ws.rs.core.Response) ErrorData(org.apache.pulsar.common.policies.data.ErrorData)

Example 4 with FunctionConfig

use of org.apache.pulsar.functions.proto.Function.FunctionConfig in project incubator-pulsar by apache.

the class FunctionsImpl method validateUpdateRequestParams.

private FunctionConfig validateUpdateRequestParams(String tenant, String namespace, String functionName, InputStream uploadedInputStream, FormDataContentDisposition fileDetail, String functionConfigJson) throws IllegalArgumentException {
    if (tenant == null) {
        throw new IllegalArgumentException("Tenant is not provided");
    }
    if (namespace == null) {
        throw new IllegalArgumentException("Namespace is not provided");
    }
    if (functionName == null) {
        throw new IllegalArgumentException("Function Name is not provided");
    }
    if (uploadedInputStream == null || fileDetail == null) {
        throw new IllegalArgumentException("Function Package is not provided");
    }
    if (functionConfigJson == null) {
        throw new IllegalArgumentException("FunctionConfig is not provided");
    }
    try {
        FunctionConfig.Builder functionConfigBuilder = FunctionConfig.newBuilder();
        org.apache.pulsar.functions.utils.Utils.mergeJson(functionConfigJson, functionConfigBuilder);
        FunctionConfig functionConfig = functionConfigBuilder.build();
        List<String> missingFields = new LinkedList<>();
        if (functionConfig.getTenant() == null || functionConfig.getTenant().isEmpty()) {
            missingFields.add("Tenant");
        }
        if (functionConfig.getNamespace() == null || functionConfig.getNamespace().isEmpty()) {
            missingFields.add("Namespace");
        }
        if (functionConfig.getName() == null || functionConfig.getName().isEmpty()) {
            missingFields.add("Name");
        }
        if (functionConfig.getClassName() == null || functionConfig.getClassName().isEmpty()) {
            missingFields.add("ClassName");
        }
        if (functionConfig.getInputsCount() == 0 && functionConfig.getCustomSerdeInputsCount() == 0) {
            missingFields.add("Input");
        }
        if (!missingFields.isEmpty()) {
            String errorMessage = StringUtils.join(missingFields, ",");
            throw new IllegalArgumentException(errorMessage + " is not provided");
        }
        if (functionConfig.getParallelism() <= 0) {
            throw new IllegalArgumentException("Parallelism needs to be set to a positive number");
        }
        return functionConfig;
    } catch (IllegalArgumentException ex) {
        throw ex;
    } catch (Exception ex) {
        throw new IllegalArgumentException("Invalid FunctionConfig");
    }
}
Also used : FunctionConfig(org.apache.pulsar.functions.proto.Function.FunctionConfig) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException)

Example 5 with FunctionConfig

use of org.apache.pulsar.functions.proto.Function.FunctionConfig in project incubator-pulsar by apache.

the class FunctionsImpl method triggerFunction.

@POST
@Path("/{tenant}/{namespace}/{functionName}/trigger")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response triggerFunction(@PathParam("tenant") final String tenant, @PathParam("namespace") final String namespace, @PathParam("name") final String functionName, @FormDataParam("data") final String input, @FormDataParam("dataStream") final InputStream uploadedInputStream) {
    FunctionConfig functionConfig;
    // validate parameters
    try {
        validateTriggerRequestParams(tenant, namespace, functionName, input, uploadedInputStream);
    } catch (IllegalArgumentException e) {
        log.error("Invalid trigger function request @ /{}/{}/{}", tenant, namespace, functionName, e);
        return Response.status(Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON).entity(new ErrorData(e.getMessage())).build();
    }
    FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
    if (!functionMetaDataManager.containsFunction(tenant, namespace, functionName)) {
        log.error("Function in getFunction does not exist @ /{}/{}/{}", tenant, namespace, functionName);
        return Response.status(Status.NOT_FOUND).type(MediaType.APPLICATION_JSON).entity(new ErrorData(String.format("Function %s doesn't exist", functionName))).build();
    }
    FunctionMetaData functionMetaData = functionMetaDataManager.getFunctionMetaData(tenant, namespace, functionName);
    String inputTopicToWrite;
    if (functionMetaData.getFunctionConfig().getInputsList().size() > 0) {
        inputTopicToWrite = functionMetaData.getFunctionConfig().getInputsList().get(0);
    } else {
        inputTopicToWrite = functionMetaData.getFunctionConfig().getCustomSerdeInputs().entrySet().iterator().next().getKey();
    }
    String outputTopic = functionMetaData.getFunctionConfig().getOutput();
    Reader reader = null;
    Producer producer = null;
    try {
        if (outputTopic != null && !outputTopic.isEmpty()) {
            reader = worker().getClient().newReader().topic(outputTopic).startMessageId(MessageId.latest).create();
        }
        producer = worker().getClient().newProducer().topic(inputTopicToWrite).create();
        byte[] targetArray;
        if (uploadedInputStream != null) {
            targetArray = new byte[uploadedInputStream.available()];
            uploadedInputStream.read(targetArray);
        } else {
            targetArray = input.getBytes();
        }
        MessageId msgId = producer.send(targetArray);
        if (reader == null) {
            return Response.status(Status.OK).build();
        }
        long curTime = System.currentTimeMillis();
        long maxTime = curTime + 1000;
        while (curTime < maxTime) {
            Message msg = reader.readNext(10000, TimeUnit.MILLISECONDS);
            if (msg == null)
                break;
            if (msg.getProperties().containsKey("__pfn_input_msg_id__") && msg.getProperties().containsKey("__pfn_input_topic__")) {
                MessageId newMsgId = MessageId.fromByteArray(Base64.getDecoder().decode((String) msg.getProperties().get("__pfn_input_msg_id__")));
                if (msgId.equals(newMsgId) && msg.getProperties().get("__pfn_input_topic__").equals(inputTopicToWrite)) {
                    return Response.status(Status.OK).entity(msg.getData()).build();
                }
            }
            curTime = System.currentTimeMillis();
        }
        return Response.status(Status.REQUEST_TIMEOUT).build();
    } catch (Exception e) {
        return Response.status(Status.INTERNAL_SERVER_ERROR).build();
    } finally {
        if (reader != null) {
            reader.closeAsync();
        }
        if (producer != null) {
            producer.closeAsync();
        }
    }
}
Also used : FunctionConfig(org.apache.pulsar.functions.proto.Function.FunctionConfig) FunctionMetaData(org.apache.pulsar.functions.proto.Function.FunctionMetaData) Message(org.apache.pulsar.client.api.Message) Reader(org.apache.pulsar.client.api.Reader) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) Producer(org.apache.pulsar.client.api.Producer) FunctionMetaDataManager(org.apache.pulsar.functions.worker.FunctionMetaDataManager) ErrorData(org.apache.pulsar.common.policies.data.ErrorData) MessageId(org.apache.pulsar.client.api.MessageId) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes)

Aggregations

FunctionConfig (org.apache.pulsar.functions.proto.Function.FunctionConfig)17 Test (org.testng.annotations.Test)9 Message (org.apache.pulsar.client.api.Message)8 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)8 ExecutorService (java.util.concurrent.ExecutorService)7 Cleanup (lombok.Cleanup)7 MessageId (org.apache.pulsar.client.api.MessageId)7 MessageIdImpl (org.apache.pulsar.client.impl.MessageIdImpl)7 Matchers.anyString (org.mockito.Matchers.anyString)7 ErrorData (org.apache.pulsar.common.policies.data.ErrorData)5 Response (javax.ws.rs.core.Response)4 FunctionMetaData (org.apache.pulsar.functions.proto.Function.FunctionMetaData)4 ExecutionException (java.util.concurrent.ExecutionException)3 Consumes (javax.ws.rs.Consumes)3 Path (javax.ws.rs.Path)3 FunctionMetaDataManager (org.apache.pulsar.functions.worker.FunctionMetaDataManager)3 IOException (java.io.IOException)2 POST (javax.ws.rs.POST)2 PackageLocationMetaData (org.apache.pulsar.functions.proto.Function.PackageLocationMetaData)2 Gson (com.google.gson.Gson)1