Skip to content

Instantly share code, notes, and snippets.

@raulraja
Created January 26, 2016 23:25
Show Gist options
  • Save raulraja/c9e52f90a10688a4fcb3 to your computer and use it in GitHub Desktop.
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`
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