
com.codebullets.sagalib.processing.invocation.ModulesInvoker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of saga-lib Show documentation
Show all versions of saga-lib Show documentation
Java saga pattern library to organize and handle domain events.
The newest version!
/*
* Copyright 2016 Stefan Domnanovits
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.codebullets.sagalib.processing.invocation;
import com.codebullets.sagalib.ExecutionContext;
import com.codebullets.sagalib.SagaModule;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Executes the methods on the list of available modules. This has the following rules:
*
* - Every module that is at least partly started will also be finished.
* - If an error occurs when starting {@code onError} will be called for all
* started modules as well a the module raising the error.
* - {@code onFinished} will be called for all started and partially started modules.
*
*/
@Immutable
final class ModulesInvoker {
private static final Logger LOG = LoggerFactory.getLogger(ModulesInvoker.class);
private final List>> finishers;
private final List>> errorHandlers;
private ModulesInvoker(
final List>> finishers,
final List>> errorHandlers) {
this.finishers = Collections.unmodifiableList(finishers);
this.errorHandlers = Collections.unmodifiableList(errorHandlers);
}
/**
* Executes start on a list of modules.
* In case of an error during start, calls error and finished on already started/starting modules.
* @return Invoker in case all modules started without error
*/
static StartResult start(final ExecutionContext context, final Iterable modules) {
Exception possibleStartException = null;
List>> finishers = new ArrayList<>();
List>> errorHandlers = new ArrayList<>();
try {
for (final SagaModule module : modules) {
finishers.add(createFinisher(module, context));
errorHandlers.add(createErrorHandler(module, context));
module.onStart(context);
}
} catch (Exception ex) {
possibleStartException = ex;
}
return new StartResult(possibleStartException, new ModulesInvoker(finishers, errorHandlers));
}
/**
* Call finishers on all started modules.
*/
Collection finish() {
return Lists.reverse(finishers).stream()
.flatMap(f -> f.get().map(Stream::of).orElse(Stream.empty()))
.collect(Collectors.toList());
}
/**
* Execute error method on started modules.
* @return Returns possible errors triggered during error handing itself
*/
public Collection error(final Object message, final Throwable error) {
return Lists.reverse(errorHandlers).stream()
.flatMap(f -> f.apply(message, error).map(Stream::of).orElse(Stream.empty()))
.collect(Collectors.toList());
}
private static Supplier> createFinisher(final SagaModule module, final ExecutionContext context) {
return () -> tryExecute(() -> module.onFinished(context), module);
}
private static BiFunction
© 2015 - 2025 Weber Informatics LLC | Privacy Policy