Skip to content

Instantly share code, notes, and snippets.

@SegFaultAX
Created October 1, 2018 21:32
Show Gist options
  • Save SegFaultAX/e9489993dafed4fae547b7cd7a71bf86 to your computer and use it in GitHub Desktop.
Save SegFaultAX/e9489993dafed4fae547b7cd7a71bf86 to your computer and use it in GitHub Desktop.
An either-based pipeline example [Java]
import static org.assertj.core.api.Assertions.assertThat;
import java.util.function.Function;
import org.junit.Test;
import io.atlassian.fugue.Either;
public class ChainTest {
static class Context<T, Status extends Enum<Status>> {
private final T value;
private final Status status;
Context(T value, Status status) {
this.value = value;
this.status = status;
}
static <T, Status extends Enum<Status>> Context<T, Status> of(T value, Status status) {
return new Context<>(value, status);
}
public T getValue() {
return value;
}
public Status getStatus() {
return status;
}
}
enum ProcessingStatus {
INITIAL,
FETCHING,
PROCESSING,
COMPLETE,
}
static class Thingy {
String value = "init";
}
Either<String, Context<Thingy, ProcessingStatus>> step1(Context<Thingy, ProcessingStatus> ctx) {
ctx.getValue().value += " got to step1!";
return Either.right(Context.of(ctx.getValue(), ProcessingStatus.FETCHING));
}
Either<String, Context<Thingy, ProcessingStatus>> step2(Context<Thingy, ProcessingStatus> ctx) {
ctx.getValue().value += " got to step2!";
return Either.right(Context.of(ctx.getValue(), ProcessingStatus.PROCESSING));
}
Either<String, Context<Thingy, ProcessingStatus>> step3(Context<Thingy, ProcessingStatus> ctx) {
ctx.getValue().value += " got to step3!";
return Either.right(Context.of(ctx.getValue(), ProcessingStatus.COMPLETE));
}
Either<String, Context<Thingy, ProcessingStatus>> run(Context<Thingy, ProcessingStatus> ctx) {
return Either.<String, Context<Thingy, ProcessingStatus>>right(ctx)
.flatMap(onlyState(this::step1, ProcessingStatus.INITIAL))
.flatMap(onlyState(this::step2, ProcessingStatus.FETCHING))
.flatMap(onlyState(this::step3, ProcessingStatus.PROCESSING));
}
private <E, T, Status extends Enum<Status>> Function<Context<T, Status>, Either<E, Context<T, Status>>> onlyState(
Function<Context<T, Status>, Either<E, Context<T, Status>>> f,
Status state) {
return ctx -> (ctx.getStatus() == state) ? f.apply(ctx) : Either.right(ctx);
}
@Test
public void testPipeline() {
Thingy thing = new Thingy();
Either<String, Context<Thingy, ProcessingStatus>> result = run(Context.of(thing, ProcessingStatus.INITIAL));
assertThat(result.isRight()).isTrue();
Context<Thingy, ProcessingStatus> ctx = result.right().get();
assertThat(ctx.getValue().value).isEqualTo("init got to step1! got to step2! got to step3!");
assertThat(ctx.getStatus()).isEqualTo(ProcessingStatus.COMPLETE);
assertThat(run(ctx).right().get().getValue().value).isEqualTo("init got to step1! got to step2! got to step3!");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment