Search in sources :

Example 11 with ProgramRunStatus

use of io.cdap.cdap.proto.ProgramRunStatus in project cdap by cdapio.

the class ProgramNotificationSubscriberService method processNotification.

/**
 * Process a {@link Notification} received from TMS.
 *
 * @param programHeartbeatTable the {@link ProgramHeartbeatTable} for writing heart beats and program status
 * @param messageIdBytes the raw message id in the TMS for the notification
 * @param notification the {@link Notification} to process
 * @param context context to get the table for operations
 * @return a {@link List} of {@link Runnable} tasks to run after the transactional processing of the whole
 *         messages batch is completed
 * @throws Exception if failed to process the given notification
 */
private List<Runnable> processNotification(ProgramHeartbeatTable programHeartbeatTable, byte[] messageIdBytes, Notification notification, StructuredTableContext context) throws Exception {
    AppMetadataStore appMetadataStore = AppMetadataStore.create(context);
    Map<String, String> properties = notification.getProperties();
    // Required parameters
    String programRun = properties.get(ProgramOptionConstants.PROGRAM_RUN_ID);
    String programStatusStr = properties.get(ProgramOptionConstants.PROGRAM_STATUS);
    String clusterStatusStr = properties.get(ProgramOptionConstants.CLUSTER_STATUS);
    // Ignore notifications which specify an invalid ProgramRunId, which shouldn't happen
    if (programRun == null) {
        LOG.warn("Ignore notification that misses program run state information, {}", notification);
        return Collections.emptyList();
    }
    ProgramRunId programRunId = GSON.fromJson(programRun, ProgramRunId.class);
    ProgramRunStatus programRunStatus = null;
    if (programStatusStr != null) {
        try {
            programRunStatus = ProgramRunStatus.valueOf(programStatusStr);
        } catch (IllegalArgumentException e) {
            LOG.warn("Ignore notification with invalid program run status {} for program {}, {}", programStatusStr, programRun, notification);
            return Collections.emptyList();
        }
    }
    ProgramRunClusterStatus clusterStatus = null;
    if (clusterStatusStr != null) {
        try {
            clusterStatus = ProgramRunClusterStatus.valueOf(clusterStatusStr);
        } catch (IllegalArgumentException e) {
            LOG.warn("Ignore notification with invalid program run cluster status {} for program {}", clusterStatusStr, programRun);
            return Collections.emptyList();
        }
    }
    if (notification.getNotificationType().equals(Notification.Type.PROGRAM_HEART_BEAT)) {
        RunRecordDetail runRecordMeta = appMetadataStore.getRun(programRunId);
        long heartBeatTimeInSeconds = TimeUnit.MILLISECONDS.toSeconds(Long.parseLong(properties.get(ProgramOptionConstants.HEART_BEAT_TIME)));
        writeToHeartBeatTable(runRecordMeta, heartBeatTimeInSeconds, programHeartbeatTable);
        // we can return after writing to heart beat table
        return Collections.emptyList();
    }
    List<Runnable> result = new ArrayList<>();
    if (programRunStatus != null) {
        handleProgramEvent(programRunId, programRunStatus, notification, messageIdBytes, appMetadataStore, programHeartbeatTable, result);
    }
    if (clusterStatus == null) {
        return result;
    }
    handleClusterEvent(programRunId, clusterStatus, notification, messageIdBytes, appMetadataStore, context).ifPresent(result::add);
    return result;
}
Also used : AppMetadataStore(io.cdap.cdap.internal.app.store.AppMetadataStore) RunRecordDetail(io.cdap.cdap.internal.app.store.RunRecordDetail) ArrayList(java.util.ArrayList) ProgramRunClusterStatus(io.cdap.cdap.proto.ProgramRunClusterStatus) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId)

Example 12 with ProgramRunStatus

use of io.cdap.cdap.proto.ProgramRunStatus in project cdap by cdapio.

the class AppMetadataStore method recordProgramSuspendResume.

private RunRecordDetail recordProgramSuspendResume(ProgramRunId programRunId, byte[] sourceId, RunRecordDetail existing, String action, long timestamp) throws IOException {
    ProgramRunStatus toStatus = ProgramRunStatus.SUSPENDED;
    if (action.equals("resume")) {
        toStatus = ProgramRunStatus.RUNNING;
    }
    // Delete the old run record
    delete(existing);
    List<Field<?>> key = getProgramRunInvertedTimeKey(TYPE_RUN_RECORD_ACTIVE, programRunId, existing.getStartTs());
    RunRecordDetail.Builder builder = RunRecordDetail.builder(existing).setStatus(toStatus).setSourceId(sourceId);
    if (timestamp != -1) {
        if (action.equals("resume")) {
            builder.setResumeTime(timestamp);
        } else {
            builder.setSuspendTime(timestamp);
        }
    }
    RunRecordDetail meta = builder.build();
    writeToRunRecordTableWithPrimaryKeys(key, meta);
    LOG.trace("Recorded {} for program {}", toStatus, programRunId);
    return meta;
}
Also used : Field(io.cdap.cdap.spi.data.table.field.Field) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus)

Example 13 with ProgramRunStatus

use of io.cdap.cdap.proto.ProgramRunStatus in project cdap by cdapio.

the class DefaultStore method getRuns.

@Override
public List<ProgramHistory> getRuns(Collection<ProgramId> programs, ProgramRunStatus status, long startTime, long endTime, int limitPerProgram) {
    return TransactionRunners.run(transactionRunner, context -> {
        List<ProgramHistory> result = new ArrayList<>(programs.size());
        AppMetadataStore appMetadataStore = getAppMetadataStore(context);
        Set<ProgramId> existingPrograms = appMetadataStore.filterProgramsExistence(programs);
        for (ProgramId programId : programs) {
            if (!existingPrograms.contains(programId)) {
                result.add(new ProgramHistory(programId, Collections.emptyList(), new ProgramNotFoundException(programId)));
                continue;
            }
            List<RunRecord> runs = appMetadataStore.getRuns(programId, status, startTime, endTime, limitPerProgram, null).values().stream().map(record -> RunRecord.builder(record).build()).collect(Collectors.toList());
            result.add(new ProgramHistory(programId, runs, null));
        }
        return result;
    });
}
Also used : TransactionRunners(io.cdap.cdap.spi.data.transaction.TransactionRunners) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) Inject(com.google.inject.Inject) LoggerFactory(org.slf4j.LoggerFactory) WorkflowNode(io.cdap.cdap.api.workflow.WorkflowNode) ScanApplicationsRequest(io.cdap.cdap.app.store.ScanApplicationsRequest) DatasetId(io.cdap.cdap.proto.id.DatasetId) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) RunId(org.apache.twill.api.RunId) ApplicationNotFoundException(io.cdap.cdap.common.ApplicationNotFoundException) ProgramHistory(io.cdap.cdap.proto.ProgramHistory) ForwardingApplicationSpecification(io.cdap.cdap.internal.app.ForwardingApplicationSpecification) SortOrder(io.cdap.cdap.spi.data.SortOrder) BasicThrowable(io.cdap.cdap.proto.BasicThrowable) StoreDefinition(io.cdap.cdap.store.StoreDefinition) ImmutableMap(com.google.common.collect.ImmutableMap) Predicate(java.util.function.Predicate) Collection(java.util.Collection) ApplicationSpecification(io.cdap.cdap.api.app.ApplicationSpecification) Table(io.cdap.cdap.api.dataset.table.Table) Set(java.util.Set) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) StructuredTableContext(io.cdap.cdap.spi.data.StructuredTableContext) Collectors(java.util.stream.Collectors) List(java.util.List) TransactionRunner(io.cdap.cdap.spi.data.transaction.TransactionRunner) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) ServiceSpecification(io.cdap.cdap.api.service.ServiceSpecification) NotFoundException(io.cdap.cdap.common.NotFoundException) RunRecord(io.cdap.cdap.proto.RunRecord) WorkflowId(io.cdap.cdap.proto.id.WorkflowId) WorkflowSpecification(io.cdap.cdap.api.workflow.WorkflowSpecification) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) UnauthorizedException(io.cdap.cdap.security.spi.authorization.UnauthorizedException) Deque(java.util.Deque) ProgramType(io.cdap.cdap.proto.ProgramType) AtomicReference(java.util.concurrent.atomic.AtomicReference) ArrayList(java.util.ArrayList) DatasetProperties(io.cdap.cdap.api.dataset.DatasetProperties) HashSet(java.util.HashSet) WorkflowToken(io.cdap.cdap.api.workflow.WorkflowToken) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) Lists(com.google.common.collect.Lists) BiConsumer(java.util.function.BiConsumer) WorkflowActionNode(io.cdap.cdap.api.workflow.WorkflowActionNode) NoSuchElementException(java.util.NoSuchElementException) Nullable(javax.annotation.Nullable) WorkflowNodeStateDetail(io.cdap.cdap.proto.WorkflowNodeStateDetail) Logger(org.slf4j.Logger) WorkflowStatistics(io.cdap.cdap.proto.WorkflowStatistics) DatasetFramework(io.cdap.cdap.data2.dataset2.DatasetFramework) ProgramId(io.cdap.cdap.proto.id.ProgramId) ProgramDescriptor(io.cdap.cdap.app.program.ProgramDescriptor) DatasetManagementException(io.cdap.cdap.api.dataset.DatasetManagementException) IOException(java.io.IOException) WorkerSpecification(io.cdap.cdap.api.worker.WorkerSpecification) Maps(com.google.common.collect.Maps) TableNotFoundException(io.cdap.cdap.spi.data.TableNotFoundException) Store(io.cdap.cdap.app.store.Store) Consumer(java.util.function.Consumer) MapDifference(com.google.common.collect.MapDifference) ProgramNotFoundException(io.cdap.cdap.common.ProgramNotFoundException) ProgramSpecification(io.cdap.cdap.api.ProgramSpecification) RunCountResult(io.cdap.cdap.proto.RunCountResult) Preconditions(com.google.common.base.Preconditions) VisibleForTesting(com.google.common.annotations.VisibleForTesting) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) ArtifactId(io.cdap.cdap.api.artifact.ArtifactId) RunRecord(io.cdap.cdap.proto.RunRecord) ArrayList(java.util.ArrayList) ProgramId(io.cdap.cdap.proto.id.ProgramId) ProgramNotFoundException(io.cdap.cdap.common.ProgramNotFoundException) ProgramHistory(io.cdap.cdap.proto.ProgramHistory)

Example 14 with ProgramRunStatus

use of io.cdap.cdap.proto.ProgramRunStatus in project cdap by cdapio.

the class RuntimeClientServiceTest method testProgramTerminate.

/**
 * Test for {@link RuntimeClientService} that will terminate itself when seeing program completed message.
 */
@Test
public void testProgramTerminate() throws Exception {
    MessagingContext messagingContext = new MultiThreadMessagingContext(clientMessagingService);
    MessagePublisher messagePublisher = messagingContext.getDirectMessagePublisher();
    ProgramStateWriter programStateWriter = new MessagingProgramStateWriter(clientCConf, clientMessagingService);
    // Send a terminate program state first, wait for the service sees the state change,
    // then publish messages to other topics.
    programStateWriter.completed(PROGRAM_RUN_ID);
    Tasks.waitFor(true, () -> runtimeClientService.getProgramFinishTime() >= 0, 2, TimeUnit.SECONDS);
    for (Map.Entry<String, String> entry : topicConfigs.entrySet()) {
        // the RuntimeClientService will decode it to watch for program termination
        if (!entry.getKey().equals(Constants.AppFabric.PROGRAM_STATUS_EVENT_TOPIC)) {
            List<String> payloads = Arrays.asList(entry.getKey(), entry.getKey(), entry.getKey());
            messagePublisher.publish(NamespaceId.SYSTEM.getNamespace(), entry.getValue(), StandardCharsets.UTF_8, payloads.iterator());
        }
    }
    // The client service should get stopped by itself.
    Tasks.waitFor(Service.State.TERMINATED, () -> runtimeClientService.state(), clientCConf.getLong(Constants.RuntimeMonitor.GRACEFUL_SHUTDOWN_MS) + 2000, TimeUnit.MILLISECONDS);
    // All messages should be sent after the runtime client service stopped
    MessagingContext serverMessagingContext = new MultiThreadMessagingContext(messagingService);
    for (Map.Entry<String, String> entry : topicConfigs.entrySet()) {
        if (entry.getKey().equals(Constants.AppFabric.PROGRAM_STATUS_EVENT_TOPIC)) {
            // Extract the program run status from the Notification
            Tasks.waitFor(Collections.singletonList(ProgramRunStatus.COMPLETED), () -> fetchMessages(serverMessagingContext, entry.getValue(), 10, null).stream().map(Message::getPayloadAsString).map(s -> GSON.fromJson(s, Notification.class)).map(n -> n.getProperties().get(ProgramOptionConstants.PROGRAM_STATUS)).map(ProgramRunStatus::valueOf).collect(Collectors.toList()), 5, TimeUnit.SECONDS);
        } else {
            Tasks.waitFor(Arrays.asList(entry.getKey(), entry.getKey(), entry.getKey()), () -> fetchMessages(serverMessagingContext, entry.getValue(), 10, null).stream().map(Message::getPayloadAsString).collect(Collectors.toList()), 5, TimeUnit.SECONDS);
        }
    }
}
Also used : MessagingServerRuntimeModule(io.cdap.cdap.messaging.guice.MessagingServerRuntimeModule) Arrays(java.util.Arrays) ConfigModule(io.cdap.cdap.common.guice.ConfigModule) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) Notification(io.cdap.cdap.proto.Notification) Spliterators(java.util.Spliterators) TimeoutException(java.util.concurrent.TimeoutException) MessageFetcher(io.cdap.cdap.api.messaging.MessageFetcher) ProgramStateWriter(io.cdap.cdap.app.runtime.ProgramStateWriter) Gson(com.google.gson.Gson) RuntimeServerModule(io.cdap.cdap.app.guice.RuntimeServerModule) After(org.junit.After) Map(java.util.Map) ClassRule(org.junit.ClassRule) NoOpMetricsCollectionService(io.cdap.cdap.common.metrics.NoOpMetricsCollectionService) Tasks(io.cdap.cdap.common.utils.Tasks) MessagingService(io.cdap.cdap.messaging.MessagingService) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) List(java.util.List) MultiThreadMessagingContext(io.cdap.cdap.messaging.context.MultiThreadMessagingContext) Constants(io.cdap.cdap.common.conf.Constants) MessagingContext(io.cdap.cdap.api.messaging.MessagingContext) ProgramOptionConstants(io.cdap.cdap.internal.app.runtime.ProgramOptionConstants) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) InMemoryDiscoveryService(org.apache.twill.discovery.InMemoryDiscoveryService) LocalLocationModule(io.cdap.cdap.common.guice.LocalLocationModule) MessagingProgramStateWriter(io.cdap.cdap.internal.app.program.MessagingProgramStateWriter) RemoteAuthenticatorModules(io.cdap.cdap.common.guice.RemoteAuthenticatorModules) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) DiscoveryServiceClient(org.apache.twill.discovery.DiscoveryServiceClient) StreamSupport(java.util.stream.StreamSupport) Nullable(javax.annotation.Nullable) Before(org.junit.Before) DiscoveryService(org.apache.twill.discovery.DiscoveryService) Message(io.cdap.cdap.api.messaging.Message) RunIds(io.cdap.cdap.common.app.RunIds) Test(org.junit.Test) IOException(java.io.IOException) CloseableIterator(io.cdap.cdap.api.dataset.lib.CloseableIterator) TopicNotFoundException(io.cdap.cdap.api.messaging.TopicNotFoundException) Service(com.google.common.util.concurrent.Service) MetricsCollectionService(io.cdap.cdap.api.metrics.MetricsCollectionService) Injector(com.google.inject.Injector) TimeUnit(java.util.concurrent.TimeUnit) CConfiguration(io.cdap.cdap.common.conf.CConfiguration) MessagePublisher(io.cdap.cdap.api.messaging.MessagePublisher) Guice(com.google.inject.Guice) Assert(org.junit.Assert) Collections(java.util.Collections) AuthenticationContextModules(io.cdap.cdap.security.auth.context.AuthenticationContextModules) TemporaryFolder(org.junit.rules.TemporaryFolder) AbstractModule(com.google.inject.AbstractModule) Message(io.cdap.cdap.api.messaging.Message) MessagePublisher(io.cdap.cdap.api.messaging.MessagePublisher) MultiThreadMessagingContext(io.cdap.cdap.messaging.context.MultiThreadMessagingContext) MessagingProgramStateWriter(io.cdap.cdap.internal.app.program.MessagingProgramStateWriter) Notification(io.cdap.cdap.proto.Notification) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) ProgramStateWriter(io.cdap.cdap.app.runtime.ProgramStateWriter) MessagingProgramStateWriter(io.cdap.cdap.internal.app.program.MessagingProgramStateWriter) MultiThreadMessagingContext(io.cdap.cdap.messaging.context.MultiThreadMessagingContext) MessagingContext(io.cdap.cdap.api.messaging.MessagingContext) Map(java.util.Map) Test(org.junit.Test)

Example 15 with ProgramRunStatus

use of io.cdap.cdap.proto.ProgramRunStatus in project cdap by caskdata.

the class RuntimeProgramStatusSubscriberService method processNotification.

/**
 * Processes a given {@link Notification} from TMS and updates the {@link AppMetadataStore}.
 *
 * @param sourceId the message id in TMS
 * @param notification the {@link Notification} to process
 * @param store the {@link AppMetadataStore} to write to
 * @throws IOException if failed to write to the store
 */
private void processNotification(byte[] sourceId, Notification notification, AppMetadataStore store) throws IOException {
    Map<String, String> properties = notification.getProperties();
    ProgramRunId programRunId;
    ProgramRunStatus programRunStatus;
    try {
        programRunId = GSON.fromJson(properties.get(ProgramOptionConstants.PROGRAM_RUN_ID), ProgramRunId.class);
        if (programRunId == null) {
            throw new IllegalArgumentException("Missing program run id from notification");
        }
        programRunStatus = ProgramRunStatus.valueOf(properties.get(ProgramOptionConstants.PROGRAM_STATUS));
    } catch (Exception e) {
        // This shouldn't happen. If it does, we can only log and ignore the event.
        LOG.warn("Ignore notification due to unable to get program run id and program run status from notification {}", notification, e);
        return;
    }
    // Runtime server only needs the programRunId and status. We use the AppMetadataStore to record to help
    // handling state transition correctly, but we omit certain fields when calling those record* methods since
    // they are not used by the runtime server.
    LOG.debug("Received program {} of status {} {}", programRunId, programRunStatus, Bytes.toString(sourceId));
    switch(programRunStatus) {
        case STARTING:
            {
                ProgramOptions programOptions = ProgramOptions.fromNotification(notification, GSON);
                // Strip off user args and trim down system args as runtime only needs the run status for validation purpose.
                // User and system args could be large and store them in local store can lead to unnecessary storage
                // and processing overhead.
                store.recordProgramProvisioning(programRunId, Collections.emptyMap(), RuntimeMonitors.trimSystemArgs(programOptions.getArguments().asMap()), sourceId, null);
                store.recordProgramProvisioned(programRunId, 0, sourceId);
                store.recordProgramStart(programRunId, null, programOptions.getArguments().asMap(), sourceId);
                break;
            }
        case RUNNING:
            store.recordProgramRunning(programRunId, Optional.ofNullable(properties.get(ProgramOptionConstants.LOGICAL_START_TIME)).map(Long::parseLong).orElse(System.currentTimeMillis()), null, sourceId);
            break;
        case SUSPENDED:
            store.recordProgramSuspend(programRunId, sourceId, Optional.ofNullable(properties.get(ProgramOptionConstants.SUSPEND_TIME)).map(Long::parseLong).orElse(System.currentTimeMillis()));
            break;
        case STOPPING:
            store.recordProgramStopping(programRunId, sourceId, Optional.ofNullable(properties.get(ProgramOptionConstants.STOPPING_TIME)).map(Long::parseLong).orElse(System.currentTimeMillis()), Optional.ofNullable(properties.get(ProgramOptionConstants.TERMINATE_TIME)).map(Long::parseLong).orElse(Long.MAX_VALUE));
            break;
        case RESUMING:
            store.recordProgramResumed(programRunId, sourceId, Optional.ofNullable(properties.get(ProgramOptionConstants.RESUME_TIME)).map(Long::parseLong).orElse(System.currentTimeMillis()));
            break;
        case COMPLETED:
        case FAILED:
        case KILLED:
            store.recordProgramStop(programRunId, Optional.ofNullable(properties.get(ProgramOptionConstants.END_TIME)).map(Long::parseLong).orElse(System.currentTimeMillis()), programRunStatus, null, sourceId);
            // We don't need to retain records for terminated programs, hence just delete it
            store.deleteRunIfTerminated(programRunId, sourceId);
            break;
        case REJECTED:
            {
                ProgramDescriptor programDescriptor = GSON.fromJson(properties.get(ProgramOptionConstants.PROGRAM_DESCRIPTOR), ProgramDescriptor.class);
                // Strip off user args and trim down system args as runtime only needs the run status for validation purpose.
                // User and system args could be large and store them in local store can lead to unnecessary storage
                // and processing overhead.
                store.recordProgramRejected(programRunId, Collections.emptyMap(), Collections.emptyMap(), sourceId, programDescriptor.getArtifactId().toApiArtifactId());
                // We don't need to retain records for terminated programs, hence just delete it
                store.deleteRunIfTerminated(programRunId, sourceId);
                break;
            }
    }
}
Also used : ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) ProgramDescriptor(io.cdap.cdap.app.program.ProgramDescriptor) IOException(java.io.IOException) ProgramOptions(io.cdap.cdap.app.runtime.ProgramOptions)

Aggregations

ProgramRunStatus (io.cdap.cdap.proto.ProgramRunStatus)32 ProgramRunId (io.cdap.cdap.proto.id.ProgramRunId)26 Map (java.util.Map)18 NamespaceId (io.cdap.cdap.proto.id.NamespaceId)16 IOException (java.io.IOException)16 RunRecordDetail (io.cdap.cdap.internal.app.store.RunRecordDetail)14 ArrayList (java.util.ArrayList)14 Collections (java.util.Collections)14 List (java.util.List)14 ImmutableMap (com.google.common.collect.ImmutableMap)12 ProgramId (io.cdap.cdap.proto.id.ProgramId)12 TimeUnit (java.util.concurrent.TimeUnit)12 Collectors (java.util.stream.Collectors)12 Nullable (javax.annotation.Nullable)12 Gson (com.google.gson.Gson)10 ArtifactId (io.cdap.cdap.api.artifact.ArtifactId)10 RunIds (io.cdap.cdap.common.app.RunIds)10 Constants (io.cdap.cdap.common.conf.Constants)10 ProgramType (io.cdap.cdap.proto.ProgramType)10 ApplicationId (io.cdap.cdap.proto.id.ApplicationId)10