Skip to content

Instantly share code, notes, and snippets.

@d-plaindoux
Last active March 27, 2020 07:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d-plaindoux/23b4f4f33d5d494a243b49fc7a627b3a to your computer and use it in GitHub Desktop.
Save d-plaindoux/23b4f4f33d5d494a243b49fc7a627b3a to your computer and use it in GitHub Desktop.
Saga like transaction
object Saga {
type Rollback[A] = A => Any
case class Compensate[A](future: Future[(A, Rollback[A])]) {
def flatMap[B](nextCompensate: A => Compensate[B]): Compensate[B] = {
Compensate(future.flatMap({
case (v, rollback) =>
nextCompensate(v).future recoverWith { e =>
rollback(v)
Future.failed(e)
}
}))
}
def map[B](nextCompensate: A => B): Compensate[B] = {
Compensate(future.flatMap {
v =>
Future {
(nextCompensate(v._1), { _ => })
}
})
}
}
class Step[A](val future: Future[A]) {
def compensate(rollback: A => Unit): Compensate[A] =
Compensate(future map { a => (a, rollback) })
}
object Step {
implicit def to_step[A](f: Future[A]): Step[A] = new Step(f)
}
}
object Main {
def main(args: Array[String]): Unit = {
import Saga.Step._
for {
v1 <- Future(1) compensate { println(_) }
v2 <- Future(2) compensate { println(_) }
v3 <- Future(3) compensate { println(_) }
v4 <- Future.failed[Int](new IllegalArgumentException) compensate { _ => println("4") }
} yield v4
}
}
@d-plaindoux
Copy link
Author

A simple and basic Saga like monad providing compensation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment