Java Code Examples for java.util.concurrent.CompletionStage#thenCompose()

The following examples show how to use java.util.concurrent.CompletionStage#thenCompose() . These examples are extracted from open source projects. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
@HystrixCommand(fallbackMethod = "fallback")
@Override
public CompletionStage<Either<CommandFailure, Tuple2<PaymentId, PaymentStatus>>> process(PerformPayment performPayment) {

    LOG.debug("Payment process {}", performPayment);

    Payment payment = new Payment(applicationContext);
    CompletionStage<Either<CommandFailure, PaymentRequested>> performPaymentPromise = payment.handle(performPayment);
    return performPaymentPromise.thenCompose(paymentRequested -> paymentRequested.fold(
            rejectPayment -> completed(rejectPayment),
            acceptPayment -> authorize(payment, acceptPayment).thenCompose(paymentAuthorized -> paymentAuthorized.fold(
                    rejectAuthorization -> completed(rejectAuthorization),
                    acceptAuthorization -> {
                        if (acceptPayment.getPaymentIntent().isAuthorize()) {
                            return completed(acceptAuthorization, PaymentStatus.AUTHORIZED);
                        } else {
                            return confirm(payment, acceptPayment, acceptAuthorization);
                        }
                    }
            ))
    ));
}
 
Example 2
Source Project: samza   File: OperatorImpl.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Handle timer ticks for this {@link OperatorImpl} and propagate the results and timer tick to registered operators.
 * <p>
 * Delegates to {@link #handleTimer(MessageCollector, TaskCoordinator)} for handling the timer tick.
 *
 * @param collector  the {@link MessageCollector} in the context
 * @param coordinator  the {@link TaskCoordinator} in the context
 */
public final CompletionStage<Void> onTimer(MessageCollector collector, TaskCoordinator coordinator) {
  long startNs = this.highResClock.nanoTime();
  Collection<RM> results = handleTimer(collector, coordinator);
  long endNs = this.highResClock.nanoTime();
  this.handleTimerNs.update(endNs - startNs);

  CompletionStage<Void> resultFuture = CompletableFuture.allOf(
      results.stream()
          .flatMap(r -> this.registeredOperators.stream()
              .map(op -> op.onMessageAsync(r, collector, coordinator)))
          .toArray(CompletableFuture[]::new));

  return resultFuture.thenCompose(x ->
      CompletableFuture.allOf(this.registeredOperators
          .stream()
          .map(op -> op.onTimer(collector, coordinator))
          .toArray(CompletableFuture[]::new)));
}
 
Example 3
public static CompletionStage<?> fetchLazyAssociationsBeforeCascade(
		CascadingAction<?> action,
		EntityPersister persister,
		Object entity,
		EventSource session) {

	CompletionStage<?> beforeDelete = CompletionStages.nullFuture();
	if ( persister.hasCascades() ) {
		CascadeStyle[] cascadeStyles = persister.getPropertyCascadeStyles();
		Object[] state = persister.getPropertyValues( entity );
		for (int i = 0; i < cascadeStyles.length; i++) {
			if ( cascadeStyles[i].doCascade( action.delegate() ) ) {
				Object fetchable = state[i];
				if ( !Hibernate.isInitialized( fetchable ) ) {
					beforeDelete = beforeDelete.thenCompose( v -> session.unwrap(ReactiveSession.class).reactiveFetch( fetchable, true ) );
				}
			}
		}
	}
	return beforeDelete;
}
 
Example 4
@Override
public CompletionStage<JsonObject> retrievePartialThing(final ThingId thingId,
        final JsonFieldSelector jsonFieldSelector,
        final DittoHeaders dittoHeaders,
        @Nullable final Signal<?> concernedSignal) {

    if (concernedSignal instanceof ThingDeleted && !(ProtocolAdapter.isLiveSignal(concernedSignal))) {
        // twin deleted events should not be enriched, return empty JsonObject
        return CompletableFuture.completedFuture(JsonObject.empty());
    }

    // remove channel header to prevent looping on live messages
    final DittoHeaders headersWithoutChannel = dittoHeaders.toBuilder().channel(null).build();

    final RetrieveThing command =
            RetrieveThing.getBuilder(thingId, headersWithoutChannel)
                    .withSelectedFields(jsonFieldSelector)
                    .build();

    final CompletionStage<Object> askResult = Patterns.ask(commandHandler, command, askTimeout);

    return askResult.thenCompose(ByRoundTripSignalEnrichmentFacade::extractPartialThing);
}
 
Example 5
/**
 * Perform all currently queued actions.
 *
 * @throws HibernateException error executing queued actions.
 */
public CompletionStage<Void> executeActions() {
	if ( hasUnresolvedEntityInsertActions() ) {
		return CompletionStages.failedFuture( new IllegalStateException(
				"About to execute actions, but there are unresolved entity insert actions." ) );
	}

	CompletionStage<Void> ret = CompletionStages.nullFuture();
	for ( ListProvider<? extends ReactiveExecutable> listProvider : EXECUTABLE_LISTS_MAP.values() ) {
		ExecutableList<? extends ReactiveExecutable> l = listProvider.get( this );
		if ( l != null && !l.isEmpty() ) {
			ret = ret.thenCompose( v -> executeActions( l ) );
		}
	}
	return ret;
}
 
Example 6
@Override
public CompletionStage<PropertyContext<?>> convert(final CompletionStage<PropertyContext<?>> cs) {
    return cs.thenCompose(context -> {
        final UiSchema arraySchema = newUiSchema(context);
        final SimplePropertyDefinition original = context.getProperty();
        arraySchema.setTitle(original.getDisplayName());
        arraySchema.setItems(new ArrayList<>());
        arraySchema.setItemWidget("collapsibleFieldset");
        final UiSchemaConverter converter =
                new UiSchemaConverter(gridLayoutFilter, family, arraySchema.getItems(), new ArrayList<>(), client,
                        jsonSchema, properties, actions, lang, customPropertyConverters, idGenerator);
        return converter
                .convertObject(new PropertyContext<>(
                        new SimplePropertyDefinition(original.getPath() + "[]", original.getName(), null,
                                original.getType(), original.getDefaultValue(), original.getValidation(),
                                metaToPropagate, original.getPlaceholder(), original.getProposalDisplayNames()),
                        context.getRootContext(), context.getConfiguration()), metaToPropagate, arraySchema,
                        idGenerator);
    });
}
 
Example 7
/**
 * process cascade save/update at the start of a flush to discover
 * any newly referenced entity that must be passed to saveOrUpdate(),
 * and also apply orphan delete
 */
private CompletionStage<Void> prepareEntityFlushes(EventSource session, PersistenceContext persistenceContext) throws HibernateException {

	LOG.debug( "Processing flush-time cascades" );

	CompletionStage<Void> stage = CompletionStages.nullFuture();
	final IdentitySet copiedAlready = new IdentitySet( 10 );
	//safe from concurrent modification because of how concurrentEntries() is implemented on IdentityMap
	for ( Map.Entry<Object, EntityEntry> me : persistenceContext.reentrantSafeEntityEntries() ) {
		EntityEntry entry = me.getValue();
		Status status = entry.getStatus();
		if ( status == Status.MANAGED || status == Status.SAVING || status == Status.READ_ONLY ) {
			stage = stage.thenCompose( v -> cascadeOnFlush( session, entry.getPersister(), me.getKey(), copiedAlready ) );
		}
	}
	return stage;
}
 
Example 8
private <T> CompletionStage<T> applyToAll(
		Function<Object, CompletionStage<T>> op,
		Object[] entity) {
	if ( entity.length==0 ) {
		return CompletionStages.nullFuture();
	}
	else if ( entity.length==1 ) {
		return op.apply( entity[0] );
	}

	CompletionStage<T> stage = CompletionStages.nullFuture();
	for (Object e: entity) {
		stage = stage.thenCompose( v -> op.apply(e) );
	}
	return stage;
}
 
Example 9
Source Project: beam   File: MoreFutures.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * Like {@link CompletableFuture#runAsync} but for {@link ThrowingRunnable}.
 *
 * <p>If the {@link ThrowingRunnable} throws an exception, the future completes exceptionally.
 */
public static CompletionStage<Void> runAsync(
    ThrowingRunnable runnable, ExecutorService executorService) {
  CompletableFuture<Void> result = new CompletableFuture<>();

  CompletionStage<Void> wrapper =
      CompletableFuture.runAsync(
          () -> {
            try {
              runnable.run();
              result.complete(null);
            } catch (InterruptedException e) {
              result.completeExceptionally(e);
              Thread.currentThread().interrupt();
            } catch (Throwable t) {
              result.completeExceptionally(t);
            }
          },
          executorService);
  return wrapper.thenCompose(nothing -> result);
}
 
Example 10
/**
 * This method is based on {@link AbstractRowReader#performTwoPhaseLoad}
 */
public CompletionStage<Void> reactivePerformTwoPhaseLoad(
		ReactiveLoadPlanBasedResultSetProcessor resultSetProcessor,
		PreLoadEvent preLoadEvent,
		ResultSetProcessingContextImpl context,
		List<HydratedEntityRegistration> hydratedEntityRegistrations) {
	final int numberOfHydratedObjects = hydratedEntityRegistrations == null
			? 0
			: hydratedEntityRegistrations.size();
	//log.tracev( "Total objects hydrated: {0}", numberOfHydratedObjects );

	CompletionStage<Void> stage = CompletionStages.nullFuture();

	if ( numberOfHydratedObjects == 0 ) {
		return stage;
	}

	final SharedSessionContractImplementor session = context.getSession();
	final Iterable<PreLoadEventListener> listeners = session
			.getFactory()
			.getServiceRegistry()
			.getService( EventListenerRegistry.class )
			.getEventListenerGroup( EventType.PRE_LOAD )
			.listeners();

	for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) {
		final EntityEntry entityEntry = session.getPersistenceContext().getEntry( registration.getInstance() );
		stage = stage.thenCompose( v -> resultSetProcessor.initializeEntity(
				registration.getInstance(),
				false,
				session,
				preLoadEvent,
				listeners
		));
	}

	return stage;
}
 
Example 11
Source Project: samza   File: OperatorImpl.java    License: Apache License 2.0 5 votes vote down vote up
public final CompletionStage<Void> onMessageAsync(M message, MessageCollector collector,
    TaskCoordinator coordinator) {
  this.numMessage.inc();
  long startNs = this.highResClock.nanoTime();
  CompletionStage<Collection<RM>> completableResultsFuture;
  try {
    completableResultsFuture = handleMessageAsync(message, collector, coordinator);
  } catch (ClassCastException e) {
    String actualType = e.getMessage().replaceFirst(" cannot be cast to .*", "");
    String expectedType = e.getMessage().replaceFirst(".* cannot be cast to ", "");
    throw new SamzaException(
        String.format("Error applying operator %s (created at %s) to its input message. "
                + "Expected input message to be of type %s, but found it to be of type %s. "
                + "Are Serdes for the inputs to this operator configured correctly?",
            getOpImplId(), getOperatorSpec().getSourceLocation(), expectedType, actualType), e);
  }

  CompletionStage<Void> result = completableResultsFuture.thenCompose(results -> {
    long endNs = this.highResClock.nanoTime();
    this.handleMessageNs.update(endNs - startNs);

    return CompletableFuture.allOf(results.stream()
        .flatMap(r -> this.registeredOperators.stream()
          .map(op -> op.onMessageAsync(r, collector, coordinator)))
        .toArray(CompletableFuture[]::new));
  });

  WatermarkFunction watermarkFn = getOperatorSpec().getWatermarkFn();
  if (watermarkFn != null) {
    // check whether there is new watermark emitted from the user function
    Long outputWm = watermarkFn.getOutputWatermark();
    return result.thenCompose(ignored -> propagateWatermark(outputWm, collector, coordinator));
  }

  return result;
}
 
Example 12
private CompletionStage<Void> addResolvedEntityInsertAction(ReactiveEntityInsertAction insert) {
	CompletionStage<Void> ret;
	if ( insert.isEarlyInsert() ) {
		LOG.trace( "Executing insertions before resolved early-insert" );
		ret = executeInserts();
		LOG.debug( "Executing identity-insert immediately" );
		ret = ret.thenCompose( v -> execute( insert ) );
	}
	else {
		LOG.trace( "Adding resolved non-early insert action." );
		addAction( ReactiveEntityInsertAction.class, insert );
		ret = CompletionStages.nullFuture();
	}

	return ret.thenCompose( v -> {
		if ( !insert.isVeto() ) {
			CompletionStage<Void> comp = insert.reactiveMakeEntityManaged();
			if ( unresolvedInsertions != null ) {
				for ( AbstractEntityInsertAction resolvedAction : unresolvedInsertions.resolveDependentActions(
						insert.getInstance(),
						session
				) ) {
					comp = comp.thenCompose( v2 -> addResolvedEntityInsertAction( (ReactiveEntityRegularInsertAction) resolvedAction ) );
				}
			}
			return comp;
		}
		else {
			throw new EntityActionVetoException(
					"The EntityInsertAction was vetoed.",
					(EntityAction) insert
			);
		}
	} );
}
 
Example 13
/**
 * Perform {@link org.hibernate.action.spi.Executable#execute()} on each element of the list
 *
 * @param list The list of Executable elements to be performed
 */
private <E extends ReactiveExecutable> CompletionStage<Void> executeActions(
		ExecutableList<E> list) throws HibernateException {
	// todo : consider ways to improve the double iteration of Executables here:
	//		1) we explicitly iterate list here to perform Executable#execute()
	//		2) ExecutableList#getQuerySpaces also iterates the Executables to collect query spaces.
	CompletionStage<Void> ret = CompletionStages.nullFuture();
	for ( E e : list ) {
		ret = ret.thenCompose( v -> e.reactiveExecute().whenComplete( (v2, x) -> {
			if ( e.getBeforeTransactionCompletionProcess() != null ) {
				if ( beforeTransactionProcesses == null ) {
					beforeTransactionProcesses = new BeforeTransactionCompletionProcessQueue( session );
				}
				beforeTransactionProcesses.register( e.getBeforeTransactionCompletionProcess() );
			}
			if ( e.getAfterTransactionCompletionProcess() != null ) {
				if ( afterTransactionProcesses == null ) {
					afterTransactionProcesses = new AfterTransactionCompletionProcessQueue( session );
				}
				afterTransactionProcesses.register( e.getAfterTransactionCompletionProcess() );
			}
		} ) );
	}
	return ret.whenComplete( (v, x) -> {
		if ( session.getFactory().getSessionFactoryOptions().isQueryCacheEnabled() ) {
			// Strictly speaking, only a subset of the list may have been processed if a RuntimeException occurs.
			// We still invalidate all spaces. I don't see this as a big deal - after all, RuntimeExceptions are
			// unexpected.
			Set<Serializable> propertySpaces = list.getQuerySpaces();
			invalidateSpaces( convertTimestampSpaces( propertySpaces ) );
		}
	} ).thenRun( () -> {
		list.clear();
		session.getJdbcCoordinator().executeBatch();
	} );
}
 
Example 14
@Override
public CompletionStage<PropertyContext<?>> convert(final CompletionStage<PropertyContext<?>> cs) {
    return cs.thenCompose(context -> {
        jsonSchema.setType(context.getProperty().getType().toLowerCase(ROOT));
        final String prefix = context.getProperty().getPath() + "[]";
        final List<SimplePropertyDefinition> arrayElements =
                properties.stream().filter(child -> child.getPath().startsWith(prefix)).collect(toList());

        if (arrayElements.stream().anyMatch(e -> e.getPath().startsWith(prefix + '.'))) { // complex object
            final JsonSchema items = new JsonSchema();
            items.setType("object");
            items.setProperties(new TreeMap<>());
            jsonSchema.setItems(items);
            return CompletableFuture
                    .allOf(arrayElements
                            .stream()
                            .filter(prop -> prop.getPath().startsWith(prefix + '.')
                                    && prop.getPath().indexOf('.', prefix.length() + 1) < 0)
                            .map(it -> new PropertyContext(it, context.getRootContext(),
                                    context.getConfiguration()))
                            .map(CompletionStages::toStage)
                            .map(e -> new JsonSchemaConverter(jsonb, items, properties).convert(e))
                            .toArray(CompletableFuture[]::new))
                    .thenApply(done -> context);
        } else if (!arrayElements.isEmpty()) { // primitive
            final String type = arrayElements.get(0).getType();
            final JsonSchema item = new JsonSchema();
            item.setTitle(jsonSchema.getTitle());
            item.setType("enum".equalsIgnoreCase(type) ? "string" : type.toLowerCase(ROOT));
            jsonSchema.setItems(item);
        }
        return CompletableFuture.completedFuture(context);
    });
}
 
Example 15
@Override
public CompletionStage<PropertyContext<?>> convert(final CompletionStage<PropertyContext<?>> cs) {
    return cs.thenCompose(context -> {
        final JsonSchema jsonSchema = new JsonSchema();
        jsonSchema.setTitle(context.getProperty().getDisplayName());
        final String type = context.getProperty().getType();
        switch (type.toLowerCase(ROOT)) {
        case "enum":
            return new EnumPropertyConverter(jsonSchema)
                    .convert(CompletableFuture.completedFuture(context))
                    .thenCompose(c -> postHandling(context, jsonSchema, type));
        case "array":
            return new ArrayPropertyConverter(jsonb, jsonSchema, properties)
                    .convert(CompletableFuture.completedFuture(context))
                    .thenCompose(c -> postHandling(context, jsonSchema, type));
        default:
            if (context.getProperty().getPath().endsWith("[]")) {
                return CompletableFuture.completedFuture(context);
            }
            jsonSchema.setType(type.toLowerCase(ROOT));
            of(context
                    .findDirectChild(properties)
                    .filter(nested -> new PropertyContext<>(nested, context.getRootContext(),
                            context.getConfiguration()).isRequired())
                    .map(SimplePropertyDefinition::getName)
                    .collect(toSet())).filter(s -> !s.isEmpty()).ifPresent(jsonSchema::setRequired);
            return CompletableFuture
                    .completedFuture(context)
                    .thenCompose(c -> postHandling(context, jsonSchema, type));
        }
    });
}
 
Example 16
@Override
public CompletionStage<PropertyContext<?>> convert(final CompletionStage<PropertyContext<?>> cs) {
    return cs
            .thenCompose(context -> customConverters
                    .stream()
                    .filter(it -> it.supports(context))
                    .findFirst()
                    .map(it -> it
                            .convert(cs,
                                    new CustomPropertyConverter.ConverterContext(family, schemas,
                                            includedProperties, client, jsonSchema, properties, actions, lang)))
                    .orElseGet(() -> {
                        final SimplePropertyDefinition property = context.getProperty();
                        final String type = property.getType().toLowerCase(Locale.ROOT);
                        final Map<String, String> metadata = property.getMetadata();
                        switch (type) {
                        case "object":
                            return convertObject(context, metadata, null, idGenerator);
                        case "boolean":
                            includedProperties.add(property);
                            return new ToggleWidgetConverter(schemas, properties, actions, jsonSchema, lang)
                                    .convert(CompletableFuture.completedFuture(context));
                        case "enum":
                            includedProperties.add(property);
                            return new DataListWidgetConverter(schemas, properties, actions, client, family,
                                    jsonSchema, lang).convert(CompletableFuture.completedFuture(context));
                        case "number":
                            includedProperties.add(property);
                            return new NumberWidgetConverter(schemas, properties, actions, jsonSchema, lang)
                                    .convert(CompletableFuture.completedFuture(context));
                        case "array":
                            includedProperties.add(property);
                            final String nestedPrefix = property.getPath() + "[].";
                            final int from = nestedPrefix.length();
                            final Collection<SimplePropertyDefinition> nested = properties
                                    .stream()
                                    .filter(prop -> prop.getPath().startsWith(nestedPrefix)
                                            && prop.getPath().indexOf('.', from) < 0)
                                    .collect(toList());
                            if (!nested.isEmpty()) {
                                return new ObjectArrayWidgetConverter(schemas, properties, actions, family, client,
                                        gridLayoutFilter, jsonSchema, lang, customConverters, metadata, idGenerator)
                                                .convert(CompletableFuture.completedFuture(context));
                            }
                            return new MultiSelectWidgetConverter(schemas, properties, actions, client, family,
                                    jsonSchema, lang).convert(CompletableFuture.completedFuture(context));
                        case "string":
                        default:
                            if (property.getPath().endsWith("[]")) {
                                return CompletableFuture.completedFuture(context);
                            }
                            includedProperties.add(property);
                            if ("true".equalsIgnoreCase(metadata.get("ui::credential"))) {
                                return new CredentialWidgetConverter(schemas, properties, actions, jsonSchema, lang)
                                        .convert(CompletableFuture.completedFuture(context));
                            } else if (metadata.containsKey("ui::code::value")) {
                                return new CodeWidgetConverter(schemas, properties, actions, jsonSchema, lang)
                                        .convert(CompletableFuture.completedFuture(context));
                            } else if (metadata.containsKey("action::suggestions")
                                    || metadata.containsKey("action::built_in_suggestable")) {
                                return new SuggestionWidgetConverter(schemas, properties, actions, jsonSchema, lang)
                                        .convert(CompletableFuture.completedFuture(context));
                            } else if (metadata.containsKey("action::dynamic_values")) {
                                return new DataListWidgetConverter(schemas, properties, actions, client, family,
                                        jsonSchema, lang).convert(CompletableFuture.completedFuture(context));
                            } else if (metadata.containsKey("ui::textarea")
                                    && Boolean.valueOf(metadata.get("ui::textarea"))) {
                                return new TextAreaWidgetConverter(schemas, properties, actions, jsonSchema, lang)
                                        .convert(CompletableFuture.completedFuture(context));
                            } else if (metadata.containsKey("ui::datetime")) {
                                return new DateTimeConverter(schemas, properties, actions, jsonSchema, lang,
                                        metadata.get("ui::datetime"))
                                                .convert(CompletableFuture.completedFuture(context));
                            }

                            return new TextWidgetConverter(schemas, properties, actions, jsonSchema, lang)
                                    .convert(CompletableFuture.completedFuture(context));
                        }
                    }));
}
 
Example 17
/**
 * Verify that thread context is captured and propagated per the configuration of the
 * ManagedExecutor builder for all dependent stages of the completed future that is created
 * by the ManagedExecutor's completedStage implementation. Thread context is captured
 * at each point where a dependent stage is added, rather than solely upon creation of the
 * initial stage or construction of the builder.
 *
 * @throws InterruptedException indicates test failure
 */
@Test
public void completedStageDependentStagesRunWithContext() throws InterruptedException {
    ManagedExecutor executor = ManagedExecutor.builder()
            .propagated(Label.CONTEXT_NAME)
            .cleared(ThreadContext.ALL_REMAINING)
            .build();

    try {
        // Set non-default values
        Buffer.set(new StringBuffer("completedStage-test-buffer"));
        Label.set("completedStage-test-label-A");

        CompletionStage<String> stage1 = executor.completedStage("5A");

        // The following incomplete future prevents subsequent stages from completing
        CompletableFuture<Integer> stage2 = new CompletableFuture<Integer>();

        Label.set("completedStage-test-label-B");

        CompletionStage<Integer> stage3 = stage1.thenCompose(s -> {
            Assert.assertEquals(s, "5A",
                    "Value supplied to compose function was lost or altered.");

            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "completedStage-test-label-B",
                    "Context type was not propagated to contextual action.");

            return stage2.thenApply(i -> i + Integer.parseInt(s, 16));
        });

        Label.set("completedStage-test-label-C");

        CompletionStage<Integer> stage4 = stage3.applyToEither(new CompletableFuture<Integer>(), i -> {
            Assert.assertEquals(i, Integer.valueOf(99),
                    "Value supplied to function was lost or altered.");

            Assert.assertEquals(Buffer.get().toString(), "",
                    "Context type that is configured to be cleared was not cleared.");

            Assert.assertEquals(Label.get(), "completedStage-test-label-C",
                    "Context type was not propagated to contextual action.");

            return i + 1;
        });

        Label.set("completedStage-test-label-D");

        CountDownLatch completed = new CountDownLatch(1);
        AtomicInteger resultRef = new AtomicInteger();
        stage4.whenComplete((result, failure) -> {
            resultRef.set(result);
            completed.countDown();
        });

        // allow stages 3 and 4 to complete
        stage2.complete(9);

        Assert.assertTrue(completed.await(MAX_WAIT_NS, TimeUnit.NANOSECONDS),
                "Completion stage did not finish in a reasonable amount of time.");

        Assert.assertEquals(resultRef.get(), 100,
                "Unexpected result for stage 4.");

        // Is context properly restored on current thread?
        Assert.assertEquals(Buffer.get().toString(), "completedStage-test-buffer",
                "Previous context was not restored after context was cleared for managed executor tasks.");
        Assert.assertEquals(Label.get(), "completedStage-test-label-D",
                "Previous context was not restored after context was propagated for managed executor tasks.");
    }
    finally {
        executor.shutdownNow();
        // Restore original values
        Buffer.set(null);
        Label.set(null);
    }
}
 
Example 18
Source Project: samza   File: OperatorImpl.java    License: Apache License 2.0 4 votes vote down vote up
/**
 * A watermark comes from an upstream operator. This function decides whether we should update the
 * input watermark based on the watermark time of all the previous operators, and then call handleWatermark()
 * to let the inherited operator to act on it.
 * @param watermark incoming watermark from an upstream operator
 * @param collector message collector
 * @param coordinator task coordinator
 */
private CompletionStage<Void> onWatermark(long watermark, MessageCollector collector, TaskCoordinator coordinator) {
  final long inputWatermarkMin;
  if (prevOperators.isEmpty()) {
    // for input operator, use the watermark time coming from the source input
    inputWatermarkMin = watermark;
  } else {
    // InputWatermark(op) = min { OutputWatermark(op') | op' is upstream of op}
    inputWatermarkMin = prevOperators.stream()
        .map(op -> op.getOutputWatermark())
        .min(Long::compare)
        .get();
  }

  CompletionStage<Void> watermarkFuture = CompletableFuture.completedFuture(null);
  if (currentWatermark < inputWatermarkMin) {
    // advance the watermark time of this operator
    currentWatermark = inputWatermarkMin;
    LOG.trace("Advance input watermark to {} in operator {}", currentWatermark, getOpImplId());

    final Long outputWm;
    final Collection<RM> output;
    final WatermarkFunction watermarkFn = getOperatorSpec().getWatermarkFn();
    if (watermarkFn != null) {
      // user-overrided watermark handling here
      output = (Collection<RM>) watermarkFn.processWatermark(currentWatermark);
      outputWm = watermarkFn.getOutputWatermark();
    } else {
      // use samza-provided watermark handling
      // default is to propagate the input watermark
      output = handleWatermark(currentWatermark, collector, coordinator);
      outputWm = currentWatermark;
    }

    if (!output.isEmpty()) {
      watermarkFuture = CompletableFuture.allOf(
          output.stream()
              .flatMap(rm -> this.registeredOperators.stream()
                  .map(op -> op.onMessageAsync(rm, collector, coordinator)))
              .toArray(CompletableFuture[]::new));
    }

    watermarkFuture = watermarkFuture.thenCompose(res -> propagateWatermark(outputWm, collector, coordinator));
  }

  return watermarkFuture;
}
 
Example 19
/**
 * Given a list of update actions batches represented by a {@link List}&lt;{@link List}&gt; of {@link UpdateAction},
 * this method executes the update command, computed by {@code updateCommandFunction}, on each batch.
 *
 * @param result                in the first call of this method, this result is normally a completed
 *                              future containing the resource to update, it is then used within each iteration of
 *                              batch execution to have the latest resource (with version) once the previous batch
 *                              has finished execution.
 * @param updateCommandFunction a {@link BiFunction} used to compute the update command required to update the
 *                              resource.
 * @param batches               the batches of update actions to execute.
 * @return an instance of {@link CompletionStage}&lt;{@code U}&gt; which contains as a result an instance of
 *         the resource {@link U} after all the update actions in all batches have been executed.
 */
@Nonnull
private CompletionStage<U> updateBatches(
    @Nonnull final CompletionStage<U> result,
    @Nonnull final BiFunction<U, List<? extends UpdateAction<U>>, UpdateCommand<U>> updateCommandFunction,
    @Nonnull final List<List<UpdateAction<U>>> batches) {

    CompletionStage<U> resultStage = result;
    for (final List<UpdateAction<U>> batch : batches) {
        resultStage = resultStage.thenCompose(updatedProduct ->
            syncOptions.getCtpClient().execute(updateCommandFunction.apply(updatedProduct, batch)));
    }
    return resultStage;
}
 
Example 20
/**
 * Given a completion stage {@code currentPageStage} containing a current page result {@link PagedQueryResult}, this
 * method composes the completion stage by first checking if the result is null or not. If it is not, then it
 * recursivley (by calling itself with the next page's completion stage result) composes to the supplied stage,
 * stages of the all next pages' processing. If there is no next page, then the result of the
 * {@code currentPageStage} would be null and this method would just return a completed future containing
 * containing null result, which in turn signals the last page of processing.
 *
 * @param currentPageStage a future containing a result {@link PagedQueryResult}.
 */
@Nonnull
private CompletionStage<Void> queryNextPages(@Nonnull final CompletionStage<PagedQueryResult<T>> currentPageStage) {
    return currentPageStage.thenCompose(currentPage ->
        currentPage != null ? queryNextPages(processPageAndGetNext(currentPage)) : completedFuture(null));
}