use of com.hazelcast.jet.core.JobStatus.SUSPENDED in project hazelcast by hazelcast.
the class SuspendExecutionOnFailureTest method when_jobSuspendedDueToFailure_then_canBeResumed.
@Test
public void when_jobSuspendedDueToFailure_then_canBeResumed() {
int numItems = 100;
int interruptItem = 50;
StreamSource<Integer> source = SourceBuilder.stream("src", procCtx -> new int[1]).<Integer>fillBufferFn((ctx, buf) -> {
if (ctx[0] < numItems) {
buf.add(ctx[0]++);
sleepMillis(5);
}
}).createSnapshotFn(ctx -> ctx[0]).restoreSnapshotFn((ctx, state) -> ctx[0] = state.get(0)).build();
Pipeline p = Pipeline.create();
p.readFrom(source).withoutTimestamps().<String, Boolean, Map.Entry<Integer, Integer>>mapUsingIMap("SuspendExecutionOnFailureTest_failureMap", item -> "key", (item, value) -> {
if (value && item == interruptItem) {
throw new RuntimeException("Fail deliberately");
}
return entry(item, item);
}).setLocalParallelism(1).writeTo(Sinks.map("SuspendExecutionOnFailureTest_sinkMap"));
IMap<String, Boolean> counterMap = hz().getMap("SuspendExecutionOnFailureTest_failureMap");
counterMap.put("key", true);
jobConfig.setProcessingGuarantee(ProcessingGuarantee.AT_LEAST_ONCE).setSnapshotIntervalMillis(50);
Job job = hz().getJet().newJob(p, jobConfig);
assertJobStatusEventually(job, SUSPENDED);
IMap<Integer, Integer> sinkMap = hz().getMap("SuspendExecutionOnFailureTest_sinkMap");
counterMap.put("key", false);
job.resume();
// sinkMap is an idempotent sink, so even though we're using at-least-once, no key will be duplicated, so it
// must contain the expected number of items.
assertTrueEventually(() -> assertEquals(numItems, sinkMap.size()));
assertTrueEventually(() -> assertEquals(JobStatus.RUNNING, job.getStatus()));
cancelAndJoin(job);
}
use of com.hazelcast.jet.core.JobStatus.SUSPENDED in project hazelcast by hazelcast.
the class WatermarkCoalescer_TerminalSnapshotTest method test.
@Test
public void test() throws Exception {
/*
This test tests the issue that after a terminal barrier is processed, no other work should
be done by the ProcessorTasklet or CIES after that (except for emitting the DONE_ITEM).
Also, if at-least-once guarantee is used, the tasklet should not continue to drain
the queue that had the barrier while waiting for other barriers.
Specifically, the issue was that in at-least-once mode the DONE_ITEM was processed
after the terminal barrier while waiting for the barrier on other queues/edges. The
DONE_ITEM could have caused a WM being emitted after the barrier, which is ok
for the at-least-once mode, but the terminal snapshot should behave as if exactly-once
mode was used.
This test ensures that we're waiting for a WM in coalescer (by having a stream skew)
and then does a graceful restart in at-least-once mode and checks that the results are
correct.
*/
String key0 = generateKeyForPartition(instance, 0);
String key1 = generateKeyForPartition(instance, 1);
Pipeline p = Pipeline.create();
p.readFrom(Sources.mapJournal(sourceMap, JournalInitialPosition.START_FROM_OLDEST)).withTimestamps(Map.Entry::getValue, 0).setLocalParallelism(PARTITION_COUNT).groupingKey(Map.Entry::getKey).window(WindowDefinition.sliding(1, 1)).aggregate(AggregateOperations.counting()).setLocalParallelism(PARTITION_COUNT).writeTo(SinkBuilder.sinkBuilder("throwing", ctx -> "").<KeyedWindowResult<String, Long>>receiveFn((w, kwr) -> {
if (kwr.result() != COUNT) {
throw new RuntimeException("Received unexpected item " + kwr + ", expected count is " + COUNT);
}
}).build());
Job job = instance.getJet().newJob(p, new JobConfig().setProcessingGuarantee(ProcessingGuarantee.AT_LEAST_ONCE));
List<Future> futures = new ArrayList<>();
futures.add(spawn(() -> {
for (; ; ) {
assertJobStatusEventually(job, JobStatus.RUNNING);
System.out.println("============RESTARTING JOB=========");
job.restart();
Thread.sleep(2000);
}
}));
// one producer is twice as fast as the other, to cause waiting for WM while doing snapshot
futures.add(spawn(() -> producer(key0, 1)));
futures.add(spawn(() -> producer(key1, 2)));
sleepSeconds(20);
for (Future f : futures) {
f.cancel(true);
// check that the future was cancelled and didn't fail with another error
try {
f.get();
fail("Exception was expected");
} catch (CancellationException expected) {
}
}
// check that the job is running
JobStatus status = job.getStatus();
assertTrue("job should not be completed, status=" + status, status != FAILED && status != COMPLETED && status != SUSPENDED);
}
Aggregations