Search in sources :

Example 1 with Assignment

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

the class FunctionRuntimeManager method findAssignment.

private Assignment findAssignment(String tenant, String namespace, String functionName, int instanceId) {
    String fullyQualifiedInstanceId = Utils.getFullyQualifiedInstanceId(tenant, namespace, functionName, instanceId);
    for (Map.Entry<String, Map<String, Assignment>> entry : this.workerIdToAssignments.entrySet()) {
        Map<String, Assignment> assignmentMap = entry.getValue();
        Assignment existingAssignment = assignmentMap.get(fullyQualifiedInstanceId);
        if (existingAssignment != null) {
            return existingAssignment;
        }
    }
    return null;
}
Also used : Assignment(org.apache.pulsar.functions.proto.Function.Assignment) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Example 2 with Assignment

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

the class RoundRobinScheduler method schedule.

@Override
public List<Assignment> schedule(List<Instance> unassignedFunctionInstances, List<Assignment> currentAssignments, List<String> workers) {
    Map<String, List<Assignment>> workerIdToAssignment = new HashMap<>();
    for (String workerId : workers) {
        workerIdToAssignment.put(workerId, new LinkedList<>());
    }
    for (Assignment existingAssignment : currentAssignments) {
        workerIdToAssignment.get(existingAssignment.getWorkerId()).add(existingAssignment);
    }
    for (Instance unassignedFunctionInstance : unassignedFunctionInstances) {
        String workerId = findNextWorker(workerIdToAssignment);
        Assignment newAssignment = Assignment.newBuilder().setInstance(unassignedFunctionInstance).setWorkerId(workerId).build();
        workerIdToAssignment.get(workerId).add(newAssignment);
    }
    List<Assignment> assignments = workerIdToAssignment.entrySet().stream().flatMap(entry -> entry.getValue().stream()).collect(Collectors.toList());
    return assignments;
}
Also used : Assignment(org.apache.pulsar.functions.proto.Function.Assignment) List(java.util.List) Map(java.util.Map) HashMap(java.util.HashMap) Assignment(org.apache.pulsar.functions.proto.Function.Assignment) Instance(org.apache.pulsar.functions.proto.Function.Instance) LinkedList(java.util.LinkedList) Collectors(java.util.stream.Collectors) HashMap(java.util.HashMap) Instance(org.apache.pulsar.functions.proto.Function.Instance) List(java.util.List) LinkedList(java.util.LinkedList)

Example 3 with Assignment

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

the class FunctionRuntimeManager method getAllFunctionStatus.

/**
 * Get statuses of all function instances.
 * @param tenant the tenant the function belongs to
 * @param namespace the namespace the function belongs to
 * @param functionName the function name
 * @return a list of function statuses
 */
public InstanceCommunication.FunctionStatusList getAllFunctionStatus(String tenant, String namespace, String functionName) {
    Collection<Assignment> assignments = this.findFunctionAssignments(tenant, namespace, functionName);
    InstanceCommunication.FunctionStatusList.Builder functionStatusListBuilder = InstanceCommunication.FunctionStatusList.newBuilder();
    if (assignments.isEmpty()) {
        return functionStatusListBuilder.build();
    }
    for (Assignment assignment : assignments) {
        InstanceCommunication.FunctionStatus functionStatus = this.getFunctionInstanceStatus(assignment.getInstance().getFunctionMetaData().getFunctionConfig().getTenant(), assignment.getInstance().getFunctionMetaData().getFunctionConfig().getNamespace(), assignment.getInstance().getFunctionMetaData().getFunctionConfig().getName(), assignment.getInstance().getInstanceId());
        functionStatusListBuilder.addFunctionStatusList(functionStatus);
    }
    return functionStatusListBuilder.build();
}
Also used : Assignment(org.apache.pulsar.functions.proto.Function.Assignment) InstanceCommunication(org.apache.pulsar.functions.proto.InstanceCommunication)

Example 4 with Assignment

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

the class FunctionRuntimeManager method getFunctionInstanceStatus.

/**
 * Get status of a function instance.  If this worker is not running the function instance,
 * @param tenant the tenant the function belongs to
 * @param namespace the namespace the function belongs to
 * @param functionName the function name
 * @param instanceId the function instance id
 * @return the function status
 */
public InstanceCommunication.FunctionStatus getFunctionInstanceStatus(String tenant, String namespace, String functionName, int instanceId) {
    String workerId = this.workerConfig.getWorkerId();
    Assignment assignment = this.findAssignment(tenant, namespace, functionName, instanceId);
    if (assignment == null) {
        InstanceCommunication.FunctionStatus.Builder functionStatusBuilder = InstanceCommunication.FunctionStatus.newBuilder();
        functionStatusBuilder.setRunning(false);
        functionStatusBuilder.setFailureException("Function has not been scheduled");
        return functionStatusBuilder.build();
    }
    InstanceCommunication.FunctionStatus functionStatus = null;
    // If I am running worker
    if (assignment.getWorkerId().equals(workerId)) {
        FunctionRuntimeInfo functionRuntimeInfo = this.getFunctionRuntimeInfo(Utils.getFullyQualifiedInstanceId(assignment.getInstance()));
        RuntimeSpawner runtimeSpawner = functionRuntimeInfo.getRuntimeSpawner();
        if (runtimeSpawner != null) {
            try {
                functionStatus = functionRuntimeInfo.getRuntimeSpawner().getFunctionStatus().get();
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }
        } else {
            InstanceCommunication.FunctionStatus.Builder functionStatusBuilder = InstanceCommunication.FunctionStatus.newBuilder();
            functionStatusBuilder.setRunning(false);
            functionStatusBuilder.setInstanceId(String.valueOf(instanceId));
            if (functionRuntimeInfo.getStartupException() != null) {
                functionStatusBuilder.setFailureException(functionRuntimeInfo.getStartupException().getMessage());
            }
            functionStatus = functionStatusBuilder.build();
        }
    } else {
        // query other worker
        List<MembershipManager.WorkerInfo> workerInfoList = this.membershipManager.getCurrentMembership();
        MembershipManager.WorkerInfo workerInfo = null;
        for (MembershipManager.WorkerInfo entry : workerInfoList) {
            if (assignment.getWorkerId().equals(entry.getWorkerId())) {
                workerInfo = entry;
            }
        }
        if (workerInfo == null) {
            InstanceCommunication.FunctionStatus.Builder functionStatusBuilder = InstanceCommunication.FunctionStatus.newBuilder();
            functionStatusBuilder.setRunning(false);
            functionStatusBuilder.setInstanceId(String.valueOf(instanceId));
            functionStatusBuilder.setFailureException("Function has not been scheduled");
            return functionStatusBuilder.build();
        }
        Client client = ClientBuilder.newClient();
        // TODO: implement authentication/authorization
        String jsonResponse = client.target(String.format("http://%s:%d/admin/functions/%s/%s/%s/%d/status", workerInfo.getWorkerHostname(), workerInfo.getPort(), tenant, namespace, functionName, instanceId)).request(MediaType.TEXT_PLAIN).get(String.class);
        InstanceCommunication.FunctionStatus.Builder functionStatusBuilder = InstanceCommunication.FunctionStatus.newBuilder();
        try {
            org.apache.pulsar.functions.utils.Utils.mergeJson(jsonResponse, functionStatusBuilder);
        } catch (IOException e) {
            log.warn("Got invalid function status response from {}", workerInfo, e);
            throw new RuntimeException(e);
        }
        functionStatus = functionStatusBuilder.build();
    }
    return functionStatus;
}
Also used : IOException(java.io.IOException) Assignment(org.apache.pulsar.functions.proto.Function.Assignment) InstanceCommunication(org.apache.pulsar.functions.proto.InstanceCommunication) ExecutionException(java.util.concurrent.ExecutionException) Client(javax.ws.rs.client.Client) PulsarClient(org.apache.pulsar.client.api.PulsarClient) RuntimeSpawner(org.apache.pulsar.functions.runtime.RuntimeSpawner)

Example 5 with Assignment

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

the class FunctionRuntimeManager method processAssignmentUpdate.

/**
 * Process an assignment update from the assignment topic
 * @param messageId the message id of the update assignment
 * @param assignmentsUpdate the assignment update
 */
public synchronized void processAssignmentUpdate(MessageId messageId, AssignmentsUpdate assignmentsUpdate) {
    if (assignmentsUpdate.getVersion() > this.currentAssignmentVersion) {
        Map<String, Assignment> assignmentMap = new HashMap<>();
        for (Assignment assignment : assignmentsUpdate.getAssignmentsList()) {
            assignmentMap.put(Utils.getFullyQualifiedInstanceId(assignment.getInstance()), assignment);
        }
        Map<String, Assignment> existingAssignmentMap = new HashMap<>();
        for (Map<String, Assignment> entry : this.workerIdToAssignments.values()) {
            existingAssignmentMap.putAll(entry);
        }
        Map<String, Assignment> assignmentsToAdd = diff(assignmentMap, existingAssignmentMap);
        Map<String, Assignment> assignmentsToDelete = diff(existingAssignmentMap, assignmentMap);
        Map<String, Assignment> existingAssignments = inCommon(assignmentMap, existingAssignmentMap);
        // functions to add
        for (Map.Entry<String, Assignment> assignmentEntry : assignmentsToAdd.entrySet()) {
            String fullyQualifiedInstanceId = assignmentEntry.getKey();
            Assignment assignment = assignmentEntry.getValue();
            // add new function
            this.setAssignment(assignment);
            // Assigned to me
            if (assignment.getWorkerId().equals(workerConfig.getWorkerId())) {
                if (!this.functionRuntimeInfoMap.containsKey(fullyQualifiedInstanceId)) {
                    this.setFunctionRuntimeInfo(fullyQualifiedInstanceId, new FunctionRuntimeInfo().setFunctionInstance(assignment.getInstance()));
                } else {
                    // Somehow this function is already started
                    log.warn("Function {} already running. Going to restart function.", this.functionRuntimeInfoMap.get(fullyQualifiedInstanceId));
                    this.insertStopAction(this.functionRuntimeInfoMap.get(fullyQualifiedInstanceId));
                }
                FunctionRuntimeInfo functionRuntimeInfo = this.functionRuntimeInfoMap.get(fullyQualifiedInstanceId);
                this.insertStartAction(functionRuntimeInfo);
            }
        }
        // functions to delete
        for (Map.Entry<String, Assignment> assignmentEntry : assignmentsToDelete.entrySet()) {
            String fullyQualifiedInstanceId = assignmentEntry.getKey();
            Assignment assignment = assignmentEntry.getValue();
            FunctionRuntimeInfo functionRuntimeInfo = this.functionRuntimeInfoMap.get(fullyQualifiedInstanceId);
            if (functionRuntimeInfo != null) {
                this.insertStopAction(functionRuntimeInfo);
                this.deleteFunctionRuntimeInfo(fullyQualifiedInstanceId);
            }
            this.deleteAssignment(assignment);
        }
        // functions to update
        for (Map.Entry<String, Assignment> assignmentEntry : existingAssignments.entrySet()) {
            String fullyQualifiedInstanceId = assignmentEntry.getKey();
            Assignment assignment = assignmentEntry.getValue();
            Assignment existingAssignment = this.findAssignment(assignment);
            // potential updates need to happen
            if (!existingAssignment.equals(assignment)) {
                FunctionRuntimeInfo functionRuntimeInfo = this.functionRuntimeInfoMap.get(fullyQualifiedInstanceId);
                // stop function
                if (functionRuntimeInfo != null) {
                    this.insertStopAction(functionRuntimeInfo);
                }
                // still assigned to me, need to restart
                if (assignment.getWorkerId().equals(this.workerConfig.getWorkerId())) {
                    // start again
                    FunctionRuntimeInfo newFunctionRuntimeInfo = new FunctionRuntimeInfo();
                    newFunctionRuntimeInfo.setFunctionInstance(assignment.getInstance());
                    this.insertStartAction(newFunctionRuntimeInfo);
                    this.setFunctionRuntimeInfo(fullyQualifiedInstanceId, newFunctionRuntimeInfo);
                    this.setAssignment(assignment);
                }
            }
        }
        // set as current assignment
        this.currentAssignmentVersion = assignmentsUpdate.getVersion();
    } else {
        log.debug("Received out of date assignment update: {}", assignmentsUpdate);
    }
}
Also used : Assignment(org.apache.pulsar.functions.proto.Function.Assignment) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap)

Aggregations

Assignment (org.apache.pulsar.functions.proto.Function.Assignment)6 HashMap (java.util.HashMap)4 Map (java.util.Map)4 LinkedList (java.util.LinkedList)2 List (java.util.List)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 ExecutionException (java.util.concurrent.ExecutionException)2 Collectors (java.util.stream.Collectors)2 PulsarClient (org.apache.pulsar.client.api.PulsarClient)2 InstanceCommunication (org.apache.pulsar.functions.proto.InstanceCommunication)2 IOException (java.io.IOException)1 Iterator (java.util.Iterator)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 ExecutorService (java.util.concurrent.ExecutorService)1 Future (java.util.concurrent.Future)1 LinkedBlockingQueue (java.util.concurrent.LinkedBlockingQueue)1 ThreadPoolExecutor (java.util.concurrent.ThreadPoolExecutor)1 TimeUnit (java.util.concurrent.TimeUnit)1 Client (javax.ws.rs.client.Client)1 Setter (lombok.Setter)1