Created
January 26, 2016 23:25
-
-
Save raulraja/c9e52f90a10688a4fcb3 to your computer and use it in GitHub Desktop.
An example of refactoring nested login in the Ensime Search Service with `XorT`
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 cats.data.Xor, cats.syntax.xor._, cats.data.XorT | |
//Some type aliases for semantic purposes | |
type IndexedSymbols = Iterable[(FileObject, List[FqnSymbol])] | |
type IndexingError = (String, Throwable) | |
type ProcessResult[A] = XorT[Future, IndexingError, A] | |
// run a future lifting its success and failure to a disjoint union left and right | |
def runF[A](f : Future[A])(errorMsg : String): ProcessResult[A] = | |
XorT(f map (_.right) recover { | |
case NonFatal(e) => (errorMsg, e).left | |
}) | |
def extractSymbols: ProcessResult[IndexedSymbols] = | |
runF(Future.traverse(batch) { case (_, f) => | |
if (!f.exists()) Future.successful(f -> Nil) | |
else searchService.extractSymbolsFromClassOrJar(f).map(f -> _) | |
})(s"failed to index batch of ${batch.size} files") | |
def removeStaleEntries(indexed: IndexedSymbols): ProcessResult[Int] = | |
runF(searchService.delete(indexed.map(_._1)(collection.breakOut)) | |
)(s"failed to remove stale entries in ${batch.size} files") | |
def persistEntries(indexed : IndexedSymbols): ProcessResult[Iterable[Int]] = runF(Future.sequence(indexed.collect { | |
case (file, syms @ _ :: _) => | |
searchService.persist(FileCheck(file), syms, commitIndex = true) | |
}).map(_.flatten))(s"failed persisting entries") | |
// compute over each process with a bias on the right side | |
val op: ProcessResult[(IndexedSymbols, Int, Iterable[Int])] = for { | |
indexedSymbols <- extractSymbols | |
removedCount <- removeStaleEntries(indexedSymbols) | |
persisted <- persistEntries(indexedSymbols) | |
} yield (indexedSymbols, removedCount, persisted) | |
// inform of the Op outcome | |
op.value map { | |
case Xor.Left((msg, ex)) => log.error(msg, ex) | |
case Xor.Right((indexedSymbols, removedCount, persisted)) => | |
log.debug(s"Process completed for [$indexedSymbols]. Removed : $removedCount, Persisted : $persisted") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment