OTAlgorithms { public static <K, D, A> Promise<FindResult<K, A>> findParent(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startNodes, DiffsReducer<A, D> diffsReducer, AsyncPredicate<OTCommit<K, D>> matchPredicate) { return reduce(repository, system, startNodes, new AbstractGraphReducer<K, D, A, FindResult<K, A>>(diffsReducer) { int epoch; @Override public void onStart(@NotNull Collection<OTCommit<K, D>> queue) { this.epoch = queue.iterator().next().getEpoch(); super.onStart(queue); } @NotNull @Override protected Promise<Optional<FindResult<K, A>>> tryGetResult(OTCommit<K, D> commit, Map<K, Map<K, A>> accumulators, Map<K, OTCommit<K, D>> headCommits) { return matchPredicate.test(commit) .map(matched -> { if (!matched) return Optional.empty(); Map.Entry<K, A> someHead = accumulators.get(commit.getId()).entrySet().iterator().next(); return Optional.of(new FindResult<>( epoch, commit.getId(), commit.getParentIds(), commit.getLevel(), someHead.getKey(), headCommits.get(someHead.getKey()).getLevel(), someHead.getValue() )); }); } }); }  static Promise<R> reduce(OTRepository<K, D> repository, OTSystem<D> system,
			Set<K> heads, GraphReducer<K, D, R> reducer); static Promise<FindResult<K, A>> findParent(OTRepository<K, D> repository, OTSystem<D> system,
			Set<K> startNodes, DiffsReducer<A, D> diffsReducer, AsyncPredicate<OTCommit<K, D>> matchPredicate); static Promise<K> mergeAndPush(OTRepository<K, D> repository, OTSystem<D> system); static Promise<K> mergeAndPush(OTRepository<K, D> repository, OTSystem<D> system, @NotNull Set<K> heads); static Promise<K> mergeAndUpdateHeads(OTRepository<K, D> repository, OTSystem<D> system); static Promise<K> mergeAndUpdateHeads(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads); @NotNull static Promise<OTCommit<K, D>> merge(OTRepository<K, D> repository, OTSystem<D> system, @NotNull Set<K> heads); static Promise<Set<K>> findCut(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startNodes,
			Predicate<Collection<OTCommit<K, D>>> matchPredicate); static Promise<K> findAnyCommonParent(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startCut); static Promise<Set<K>> findAllCommonParents(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startCut); static Promise<List<D>> diff(OTRepository<K, D> repository, OTSystem<D> system, K node1, K node2); static Promise<Set<K>> excludeParents(OTRepository<K, D> repository, OTSystem<D> system, Set<K> startNodes); static Promise<Map<K, A>> reduceEdges(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads, K parentNode,
			DiffsReducer<A, D> diffAccumulator); static Promise<List<D>> checkout(OTRepository<K, D> repository, OTSystem<D> system); static Promise<List<D>> checkout(OTRepository<K, D> repository, OTSystem<D> system, K commitId); static Promise<Void> saveSnapshot(OTRepository<K, D> repository, OTSystem<D> system, K revisionId); static Promise<OTLoadedGraph<K, D>> loadForMerge(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads); static Promise<OTLoadedGraph<K, D>> loadGraph(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads, OTLoadedGraph<K, D> graph); static Promise<OTLoadedGraph<K, D>> loadGraph(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads); static Promise<OTLoadedGraph<K, D>> loadGraph(OTRepository<K, D> repository, OTSystem<D> system, Set<K> heads, Function<K, String> idToString, Function<D, String> diffToString); static Promise<Void> copy(OTRepository<K, D> from, OTRepository<K, D> to); static final StacklessException GRAPH_EXHAUSTED; }
@Test public void testFindParentNoSnapshot() { REPOSITORY.revisionIdSupplier = () -> RANDOM.nextInt(1000) + 1; Integer id1 = await(REPOSITORY.createCommitId()); await(REPOSITORY.pushAndUpdateHead(OTCommit.ofRoot(id1))); Integer id2 = await(REPOSITORY.createCommitId()); await(REPOSITORY.pushAndUpdateHead(OTCommit.ofCommit(0, id2, id1, emptyList(), id1))); Throwable exception = awaitException(findParent(REPOSITORY, TEST_OP, singleton(id2), DiffsReducer.toVoid(), commit -> REPOSITORY.loadSnapshot(commit.getId()) .map(Optional::isPresent))); assertSame(GRAPH_EXHAUSTED, exception); }