Search in sources :

Example 21 with ProgramRunStatus

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

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)

Example 22 with ProgramRunStatus

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

the class AppMetadataStoreTest method testGetActiveRuns.

@Test
public void testGetActiveRuns() throws Exception {
    // write a run record for each state for two programs in two apps in two namespaces
    String app1 = "app1";
    String app2 = "app2";
    String program1 = "prog1";
    String program2 = "prog2";
    Collection<NamespaceId> namespaces = Arrays.asList(new NamespaceId("ns1"), new NamespaceId("ns2"));
    Collection<ApplicationId> apps = namespaces.stream().flatMap(ns -> Stream.of(ns.app(app1), ns.app(app2))).collect(Collectors.toList());
    Collection<ProgramId> programs = apps.stream().flatMap(app -> Stream.of(app.mr(program1), app.mr(program2))).collect(Collectors.toList());
    for (ProgramId programId : programs) {
        TransactionRunners.run(transactionRunner, context -> {
            AppMetadataStore store = AppMetadataStore.create(context);
            // one run in pending state
            ProgramRunId runId = programId.run(RunIds.generate());
            store.recordProgramProvisioning(runId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()), ARTIFACT_ID);
            // one run in starting state
            runId = programId.run(RunIds.generate());
            store.recordProgramProvisioning(runId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()), ARTIFACT_ID);
            store.recordProgramProvisioned(runId, 3, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            store.recordProgramStart(runId, UUID.randomUUID().toString(), Collections.emptyMap(), AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            // one run in running state
            runId = programId.run(RunIds.generate());
            store.recordProgramProvisioning(runId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()), ARTIFACT_ID);
            store.recordProgramProvisioned(runId, 3, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            String twillRunId = UUID.randomUUID().toString();
            store.recordProgramStart(runId, twillRunId, Collections.emptyMap(), AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            store.recordProgramRunning(runId, System.currentTimeMillis(), twillRunId, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            // one in suspended state
            runId = programId.run(RunIds.generate());
            store.recordProgramProvisioning(runId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()), ARTIFACT_ID);
            store.recordProgramProvisioned(runId, 3, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            twillRunId = UUID.randomUUID().toString();
            store.recordProgramStart(runId, twillRunId, Collections.emptyMap(), AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            store.recordProgramRunning(runId, System.currentTimeMillis(), twillRunId, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            store.recordProgramSuspend(runId, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()), System.currentTimeMillis());
            // one run in stopping state
            runId = programId.run(RunIds.generate());
            store.recordProgramProvisioning(runId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()), ARTIFACT_ID);
            store.recordProgramProvisioned(runId, 3, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            twillRunId = UUID.randomUUID().toString();
            store.recordProgramStart(runId, twillRunId, Collections.emptyMap(), AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            store.recordProgramRunning(runId, System.currentTimeMillis(), twillRunId, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            store.recordProgramStopping(runId, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()), System.currentTimeMillis(), System.currentTimeMillis() + 1000);
            // one run in each stopped state
            for (ProgramRunStatus runStatus : ProgramRunStatus.values()) {
                if (!runStatus.isEndState()) {
                    continue;
                }
                runId = programId.run(RunIds.generate());
                store.recordProgramProvisioning(runId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()), ARTIFACT_ID);
                store.recordProgramProvisioned(runId, 3, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
                twillRunId = UUID.randomUUID().toString();
                store.recordProgramStart(runId, twillRunId, Collections.emptyMap(), AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
                store.recordProgramStop(runId, System.currentTimeMillis(), runStatus, null, AppFabricTestHelper.createSourceId(sourceId.incrementAndGet()));
            }
        });
    }
    Set<ProgramRunStatus> activeStates = new HashSet<>();
    activeStates.add(ProgramRunStatus.PENDING);
    activeStates.add(ProgramRunStatus.STARTING);
    activeStates.add(ProgramRunStatus.RUNNING);
    activeStates.add(ProgramRunStatus.SUSPENDED);
    activeStates.add(ProgramRunStatus.STOPPING);
    // test the instance level method and namespace level method
    TransactionRunners.run(transactionRunner, context -> {
        AppMetadataStore store = AppMetadataStore.create(context);
        Map<ProgramId, Set<ProgramRunStatus>> allExpected = new HashMap<>();
        Map<ProgramId, Set<ProgramRunStatus>> allActual = new HashMap<>();
        // check active runs per namespace
        for (NamespaceId namespace : namespaces) {
            Map<ProgramRunId, RunRecordDetail> activeRuns = store.getActiveRuns(namespace);
            // we expect 4 runs per program, with 4 programs in each namespace
            Map<ProgramId, Set<ProgramRunStatus>> expected = new HashMap<>();
            expected.put(namespace.app(app1).mr(program1), activeStates);
            expected.put(namespace.app(app1).mr(program2), activeStates);
            expected.put(namespace.app(app2).mr(program1), activeStates);
            expected.put(namespace.app(app2).mr(program2), activeStates);
            Map<ProgramId, Set<ProgramRunStatus>> actual = new HashMap<>();
            actual.put(namespace.app(app1).mr(program1), new HashSet<>());
            actual.put(namespace.app(app1).mr(program2), new HashSet<>());
            actual.put(namespace.app(app2).mr(program1), new HashSet<>());
            actual.put(namespace.app(app2).mr(program2), new HashSet<>());
            allActual.putAll(actual);
            for (Map.Entry<ProgramRunId, RunRecordDetail> activeRun : activeRuns.entrySet()) {
                ProgramId programId = activeRun.getKey().getParent();
                Assert.assertTrue("Unexpected program returned: " + programId, actual.containsKey(activeRun.getKey().getParent()));
                actual.get(programId).add(activeRun.getValue().getStatus());
            }
            Assert.assertEquals(expected, actual);
            allExpected.putAll(expected);
        }
        // test the instance level method
        for (Map.Entry<ProgramRunId, RunRecordDetail> activeRun : store.getActiveRuns(x -> true).entrySet()) {
            ProgramId programId = activeRun.getKey().getParent();
            Assert.assertTrue("Unexpected program returned: " + programId, allActual.containsKey(activeRun.getKey().getParent()));
            allActual.get(programId).add(activeRun.getValue().getStatus());
        }
        Assert.assertEquals(allExpected, allActual);
        // test the count-all method
        Assert.assertEquals(store.getActiveRuns(x -> true).size(), store.countActiveRuns(null));
        Assert.assertEquals(store.getActiveRuns(x -> true).size(), store.countActiveRuns(100));
        Assert.assertEquals(2, store.countActiveRuns(2));
    });
    // check active runs per app
    for (ApplicationId app : apps) {
        TransactionRunners.run(transactionRunner, context -> {
            AppMetadataStore store = AppMetadataStore.create(context);
            Map<ProgramRunId, RunRecordDetail> activeRuns = store.getActiveRuns(app);
            // we expect 3 runs per program, with 2 programs in each app
            Map<ProgramId, Set<ProgramRunStatus>> expected = new HashMap<>();
            expected.put(app.mr(program1), activeStates);
            expected.put(app.mr(program2), activeStates);
            Map<ProgramId, Set<ProgramRunStatus>> actual = new HashMap<>();
            actual.put(app.mr(program1), new HashSet<>());
            actual.put(app.mr(program2), new HashSet<>());
            for (Map.Entry<ProgramRunId, RunRecordDetail> activeRun : activeRuns.entrySet()) {
                ProgramId programId = activeRun.getKey().getParent();
                Assert.assertTrue("Unexpected program returned: " + programId, actual.containsKey(activeRun.getKey().getParent()));
                actual.get(programId).add(activeRun.getValue().getStatus());
            }
            Assert.assertEquals(expected, actual);
        });
    }
    // check active runs per program
    for (ProgramId program : programs) {
        TransactionRunners.run(transactionRunner, context -> {
            AppMetadataStore store = AppMetadataStore.create(context);
            Map<ProgramRunId, RunRecordDetail> activeRuns = store.getActiveRuns(program);
            Set<ProgramRunStatus> actual = new HashSet<>();
            for (Map.Entry<ProgramRunId, RunRecordDetail> activeRun : activeRuns.entrySet()) {
                Assert.assertEquals(program, activeRun.getKey().getParent());
                actual.add(activeRun.getValue().getStatus());
            }
            Assert.assertEquals(activeStates, actual);
        });
    }
}
Also used : Arrays(java.util.Arrays) TransactionRunners(io.cdap.cdap.spi.data.transaction.TransactionRunners) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) Callable(java.util.concurrent.Callable) ProgramType(io.cdap.cdap.proto.ProgramType) AtomicReference(java.util.concurrent.atomic.AtomicReference) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) Lists(com.google.common.collect.Lists) ImmutableList(com.google.common.collect.ImmutableList) ScanApplicationsRequest(io.cdap.cdap.app.store.ScanApplicationsRequest) AppFabricTestHelper(io.cdap.cdap.internal.AppFabricTestHelper) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Map(java.util.Map) RunId(org.apache.twill.api.RunId) SystemArguments(io.cdap.cdap.internal.app.runtime.SystemArguments) Before(org.junit.Before) SortOrder(io.cdap.cdap.spi.data.SortOrder) ImmutableMap(com.google.common.collect.ImmutableMap) RunIds(io.cdap.cdap.common.app.RunIds) Collection(java.util.Collection) ApplicationSpecification(io.cdap.cdap.api.app.ApplicationSpecification) ProgramId(io.cdap.cdap.proto.id.ProgramId) Set(java.util.Set) Test(org.junit.Test) IOException(java.io.IOException) UUID(java.util.UUID) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) Collectors(java.util.stream.Collectors) TimeUnit(java.util.concurrent.TimeUnit) AtomicLong(java.util.concurrent.atomic.AtomicLong) List(java.util.List) Stream(java.util.stream.Stream) TransactionRunner(io.cdap.cdap.spi.data.transaction.TransactionRunner) ProfileId(io.cdap.cdap.proto.id.ProfileId) AllProgramsApp(io.cdap.cdap.AllProgramsApp) Assert(org.junit.Assert) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) Collections(java.util.Collections) ArtifactId(io.cdap.cdap.api.artifact.ArtifactId) Specifications(io.cdap.cdap.internal.app.deploy.Specifications) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ProgramId(io.cdap.cdap.proto.id.ProgramId) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) ApplicationId(io.cdap.cdap.proto.id.ApplicationId) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 23 with ProgramRunStatus

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

the class RuntimeClientServiceTest method testBasicRelay.

@Test
public void testBasicRelay() throws Exception {
    // Send some messages to multiple topics in the client side TMS, they should get replicated to the server side TMS.
    MessagingContext messagingContext = new MultiThreadMessagingContext(clientMessagingService);
    MessagePublisher messagePublisher = messagingContext.getDirectMessagePublisher();
    ProgramStateWriter programStateWriter = new MessagingProgramStateWriter(clientCConf, clientMessagingService);
    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)) {
            // Write a non-terminal state to test basic relaying
            programStateWriter.running(PROGRAM_RUN_ID, null);
        } else {
            messagePublisher.publish(NamespaceId.SYSTEM.getNamespace(), entry.getValue(), entry.getKey(), entry.getKey());
        }
    }
    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.RUNNING), () -> 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()), () -> fetchMessages(serverMessagingContext, entry.getValue(), 10, null).stream().map(Message::getPayloadAsString).collect(Collectors.toList()), 5, TimeUnit.SECONDS);
        }
    }
    // Writes a program terminate message to unblock stopping of the client service
    programStateWriter.completed(PROGRAM_RUN_ID);
}
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) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) Message(io.cdap.cdap.api.messaging.Message) ProgramStateWriter(io.cdap.cdap.app.runtime.ProgramStateWriter) MessagingProgramStateWriter(io.cdap.cdap.internal.app.program.MessagingProgramStateWriter) MessagePublisher(io.cdap.cdap.api.messaging.MessagePublisher) MultiThreadMessagingContext(io.cdap.cdap.messaging.context.MultiThreadMessagingContext) MessagingContext(io.cdap.cdap.api.messaging.MessagingContext) MultiThreadMessagingContext(io.cdap.cdap.messaging.context.MultiThreadMessagingContext) MessagingProgramStateWriter(io.cdap.cdap.internal.app.program.MessagingProgramStateWriter) Map(java.util.Map) Notification(io.cdap.cdap.proto.Notification) Test(org.junit.Test)

Example 24 with ProgramRunStatus

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

the class DirectRuntimeRequestValidatorTest method testFetcher.

@Test
public void testFetcher() throws BadRequestException {
    ArtifactId artifactId = new ArtifactId("test", new ArtifactVersion("1.0"), ArtifactScope.USER);
    ProgramRunId programRunId = NamespaceId.DEFAULT.app("app").spark("spark").run(RunIds.generate());
    ProgramRunStatus programRunStatus = ProgramRunStatus.RUNNING;
    RunRecordDetail runRecord = RunRecordDetail.builder().setProgramRunId(programRunId).setStartTime(System.currentTimeMillis()).setArtifactId(artifactId).setStatus(programRunStatus).setSystemArgs(ImmutableMap.of(SystemArguments.PROFILE_NAME, "default", SystemArguments.PROFILE_PROVISIONER, "native")).setProfileId(NamespaceId.DEFAULT.profile("native")).setSourceId(new byte[MessageId.RAW_ID_SIZE]).build();
    MockProgramRunRecordFetcher runRecordFetcher = new MockProgramRunRecordFetcher().setRunRecord(runRecord);
    RuntimeRequestValidator validator = new DirectRuntimeRequestValidator(cConf, txRunner, runRecordFetcher, accessEnforcer, authenticationContext);
    // The first call should be hitting the run record fetching to fetch the run record.
    ProgramRunInfo programRunInfo = validator.getProgramRunStatus(programRunId, new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/"));
    Assert.assertEquals(programRunStatus, programRunInfo.getProgramRunStatus());
    // The second call will hit the runtime store, so it shouldn't matter what the run record fetch returns
    runRecordFetcher.setRunRecord(null);
    programRunInfo = validator.getProgramRunStatus(programRunId, new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/"));
    Assert.assertEquals(programRunStatus, programRunInfo.getProgramRunStatus());
}
Also used : ArtifactVersion(io.cdap.cdap.api.artifact.ArtifactVersion) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) ArtifactId(io.cdap.cdap.api.artifact.ArtifactId) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) RunRecordDetail(io.cdap.cdap.internal.app.store.RunRecordDetail) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) Test(org.junit.Test)

Example 25 with ProgramRunStatus

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

the class RunRecordCorrectorServiceTest method testFixProgram.

@Test
public void testFixProgram() throws Exception {
    final AtomicInteger sourceId = new AtomicInteger(0);
    // Write 10 services with starting state
    // Write 10 workers with running state
    Map<ProgramRunId, ProgramRunStatus> expectedStates = new HashMap<>();
    ArtifactId artifactId = NamespaceId.DEFAULT.artifact("testArtifact", "1.0").toApiArtifactId();
    for (int i = 0; i < 10; i++) {
        ProgramRunId serviceId = NamespaceId.DEFAULT.app("test").service("service" + i).run(randomRunId());
        store.setProvisioning(serviceId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, Bytes.toBytes(sourceId.getAndIncrement()), artifactId);
        store.setProvisioned(serviceId, 0, Bytes.toBytes(sourceId.getAndIncrement()));
        store.setStart(serviceId, null, Collections.emptyMap(), Bytes.toBytes(sourceId.getAndIncrement()));
        expectedStates.put(serviceId, ProgramRunStatus.FAILED);
        ProgramRunId workerId = new NamespaceId("ns").app("test").worker("worker" + i).run(randomRunId());
        store.setProvisioning(workerId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, Bytes.toBytes(sourceId.getAndIncrement()), artifactId);
        store.setProvisioned(workerId, 0, Bytes.toBytes(sourceId.getAndIncrement()));
        store.setStart(workerId, null, Collections.emptyMap(), Bytes.toBytes(sourceId.getAndIncrement()));
        store.setRunning(workerId, System.currentTimeMillis(), null, Bytes.toBytes(sourceId.getAndIncrement()));
        expectedStates.put(workerId, ProgramRunStatus.FAILED);
    }
    // Write a service with suspend state
    ProgramRunId flowId = new NamespaceId("ns").app("test").service("flow").run(randomRunId());
    store.setProvisioning(flowId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, Bytes.toBytes(sourceId.getAndIncrement()), artifactId);
    store.setProvisioned(flowId, 0, Bytes.toBytes(sourceId.getAndIncrement()));
    store.setStart(flowId, null, Collections.emptyMap(), Bytes.toBytes(sourceId.getAndIncrement()));
    store.setRunning(flowId, System.currentTimeMillis(), null, Bytes.toBytes(sourceId.getAndIncrement()));
    store.setSuspend(flowId, Bytes.toBytes(sourceId.getAndIncrement()), -1);
    expectedStates.put(flowId, ProgramRunStatus.SUSPENDED);
    // Write two MR in starting state. One with workflow information, one without.
    ProgramRunId mrId = NamespaceId.DEFAULT.app("app").mr("mr").run(randomRunId());
    store.setProvisioning(mrId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, Bytes.toBytes(sourceId.getAndIncrement()), artifactId);
    store.setProvisioned(mrId, 0, Bytes.toBytes(sourceId.getAndIncrement()));
    store.setStart(mrId, null, Collections.emptyMap(), Bytes.toBytes(sourceId.getAndIncrement()));
    expectedStates.put(mrId, ProgramRunStatus.FAILED);
    ProgramRunId workflowId = NamespaceId.DEFAULT.app("app").workflow("workflow").run(randomRunId());
    ProgramRunId mrInWorkflowId = workflowId.getParent().getParent().mr("mrInWorkflow").run(randomRunId());
    store.setProvisioning(mrInWorkflowId, Collections.emptyMap(), ImmutableMap.of(ProgramOptionConstants.WORKFLOW_NAME, workflowId.getProgram(), ProgramOptionConstants.WORKFLOW_RUN_ID, workflowId.getRun(), ProgramOptionConstants.WORKFLOW_NODE_ID, "mr", SystemArguments.PROFILE_NAME, ProfileId.NATIVE.getScopedName()), Bytes.toBytes(sourceId.getAndIncrement()), artifactId);
    store.setProvisioned(mrInWorkflowId, 0, Bytes.toBytes(sourceId.getAndIncrement()));
    store.setStart(mrInWorkflowId, null, ImmutableMap.of(ProgramOptionConstants.WORKFLOW_NAME, workflowId.getProgram(), ProgramOptionConstants.WORKFLOW_RUN_ID, workflowId.getRun(), ProgramOptionConstants.WORKFLOW_NODE_ID, "mr"), Bytes.toBytes(sourceId.getAndIncrement()));
    expectedStates.put(workflowId, ProgramRunStatus.STARTING);
    // Write the workflow in RUNNING state.
    store.setProvisioning(workflowId, Collections.emptyMap(), SINGLETON_PROFILE_MAP, Bytes.toBytes(sourceId.getAndIncrement()), artifactId);
    store.setProvisioned(workflowId, 0, Bytes.toBytes(sourceId.getAndIncrement()));
    store.setStart(workflowId, null, Collections.emptyMap(), Bytes.toBytes(sourceId.getAndIncrement()));
    store.setRunning(workflowId, System.currentTimeMillis(), null, Bytes.toBytes(sourceId.getAndIncrement()));
    expectedStates.put(workflowId, ProgramRunStatus.RUNNING);
    // Use a ProgramRuntimeService that only reports running state based on a set of know ids
    final Map<ProgramId, RunId> runningSet = new HashMap<>();
    ProgramRuntimeService programRuntimeService = new AbstractProgramRuntimeService(cConf, null, null, new NoOpProgramStateWriter(), null) {

        @Override
        public ProgramLiveInfo getLiveInfo(ProgramId programId) {
            return new NotRunningProgramLiveInfo(programId);
        }

        @Override
        public Map<RunId, RuntimeInfo> list(ProgramId program) {
            RunId runId = runningSet.get(program);
            if (runId != null) {
                RuntimeInfo runtimeInfo = new SimpleRuntimeInfo(null, program);
                return Collections.singletonMap(runId, runtimeInfo);
            }
            return Collections.emptyMap();
        }
    };
    // Have both flow and workflow running
    runningSet.put(flowId.getParent(), RunIds.fromString(flowId.getRun()));
    runningSet.put(workflowId.getParent(), RunIds.fromString(workflowId.getRun()));
    ProgramStateWriter programStateWriter = new NoOpProgramStateWriter() {

        @Override
        public void error(ProgramRunId programRunId, Throwable failureCause) {
            store.setStop(programRunId, System.currentTimeMillis(), ProgramRunStatus.FAILED, new BasicThrowable(failureCause), Bytes.toBytes(sourceId.getAndIncrement()));
        }
    };
    // Create a run record fixer.
    // Set the start buffer time to -1 so that it fixes right away.
    // Also use a small tx batch size to validate the batching logic.
    RunRecordCorrectorService fixer = new RunRecordCorrectorService(cConf, store, programStateWriter, programRuntimeService, namespaceAdmin, datasetFramework, -1L, 5) {
    };
    fixer.fixRunRecords();
    // Validates all expected states
    for (Map.Entry<ProgramRunId, ProgramRunStatus> entry : expectedStates.entrySet()) {
        validateExpectedState(entry.getKey(), entry.getValue());
    }
    // Remove the workflow from the running set and mark it as completed
    runningSet.remove(workflowId.getParent());
    store.setStop(workflowId, System.currentTimeMillis(), ProgramRunStatus.COMPLETED, Bytes.toBytes(sourceId.getAndIncrement()));
    fixer.fixRunRecords();
    // Both the workflow and the MR in workflow should be changed to failed state
    expectedStates.put(workflowId, ProgramRunStatus.COMPLETED);
    expectedStates.put(mrInWorkflowId, ProgramRunStatus.FAILED);
    // Validates all expected states again
    for (Map.Entry<ProgramRunId, ProgramRunStatus> entry : expectedStates.entrySet()) {
        validateExpectedState(entry.getKey(), entry.getValue());
    }
}
Also used : NoOpProgramStateWriter(io.cdap.cdap.app.runtime.NoOpProgramStateWriter) ArtifactId(io.cdap.cdap.api.artifact.ArtifactId) SimpleRuntimeInfo(io.cdap.cdap.internal.app.runtime.service.SimpleRuntimeInfo) HashMap(java.util.HashMap) ProgramId(io.cdap.cdap.proto.id.ProgramId) AbstractProgramRuntimeService(io.cdap.cdap.app.runtime.AbstractProgramRuntimeService) SimpleRuntimeInfo(io.cdap.cdap.internal.app.runtime.service.SimpleRuntimeInfo) NotRunningProgramLiveInfo(io.cdap.cdap.proto.NotRunningProgramLiveInfo) ProgramRunStatus(io.cdap.cdap.proto.ProgramRunStatus) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) NoOpProgramStateWriter(io.cdap.cdap.app.runtime.NoOpProgramStateWriter) ProgramStateWriter(io.cdap.cdap.app.runtime.ProgramStateWriter) BasicThrowable(io.cdap.cdap.proto.BasicThrowable) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) NamespaceId(io.cdap.cdap.proto.id.NamespaceId) ProgramRunId(io.cdap.cdap.proto.id.ProgramRunId) RunId(org.apache.twill.api.RunId) BasicThrowable(io.cdap.cdap.proto.BasicThrowable) HashMap(java.util.HashMap) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) AbstractProgramRuntimeService(io.cdap.cdap.app.runtime.AbstractProgramRuntimeService) ProgramRuntimeService(io.cdap.cdap.app.runtime.ProgramRuntimeService) Test(org.junit.Test)

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