Last active
March 27, 2020 07:02
-
-
Save d-plaindoux/23b4f4f33d5d494a243b49fc7a627b3a to your computer and use it in GitHub Desktop.
Saga like transaction
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
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 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A simple and basic Saga like monad providing compensation.