Skip to content

Instantly share code, notes, and snippets.

@gakuzzzz
Created May 19, 2012 08:09
Show Gist options
  • Save gakuzzzz/2730028 to your computer and use it in GitHub Desktop.
Save gakuzzzz/2730028 to your computer and use it in GitHub Desktop.
finagle_hack

Twitter-Util Futureでのトランザクションを考える

やりたいこと

def findUser(screenName: String): Future[User] = ... 
def findFollowers(user: User): Future[Set[User]] = ...
def unfollowAtRandom(user: User, followers: Set[User]): Future[Unit] = ...

def domainLogic(screenName: String) = atomically {
  for {
    user <- findUser(screenName)
    followers <- findFollowers(user)
    _ <- unfollowAtRandom(user, followers)
  } yield ()
}

こんな感じで独立した非同期呼び出しを簡単に同一トランザクションにしたい。

全体の Future が成功したらcommit, 失敗したらrollbackしてくれる感じ。

atomically がネストしてたら同一のトランザクションにしてくれるとなお嬉しい。

API案

def atomically[A](f: => Future[A]): Future[A]

実装方法検討

トランザクション制御は JTA を使用して抽象化したい。

Future の内部計算はどのスレッドで実行されるかコントロールできないので、 DynamicVariableThreadLocal で共有する方法は使えない。

そもそも javax.transaction.Transaction の実装や、 各 XAResource の実装がスレッドセーフだとは思えないので Transactionインスタンス等へのアクセスは シングルスレッドで動かす保障をした方がいい。

Actor 使う? → Futureモデルと Actorモデルの合成とか茨の道感

Executors.singleThreadPool()FuturePool を用意して Transactionインスタンス等へのアクセスは必ずその FuturePool で行う。 こっちのが現実的か。

トランザクションが並列に大量発生したらどうする?

その FuturePool をトランザクション毎に作成すればいい?

findUserfindFollowers の内部実装では、 どうにかして現在のトランザクションを知る必要がある。 これはどうやって取得するべきか。

implicit parameter 使う? → ドメインロジックのAPIになるべくそういうIFは入れたくない。

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