Created
October 1, 2018 21:32
-
-
Save SegFaultAX/e9489993dafed4fae547b7cd7a71bf86 to your computer and use it in GitHub Desktop.
An either-based pipeline example [Java]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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