1 /*
2  *  Make.org Core API
3  *  Copyright (C) 2018 Make.org
4  *
5  * This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU Affero General Public License as
7  *  published by the Free Software Foundation, either version 3 of the
8  *  License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU Affero General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Affero General Public License
16  *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  *
18  */
19 
20 package org.make.api.technical
21 
22 import scalikejdbc.{DBConnection, DBSession, Tx, TxBoundary}
23 
24 import scala.annotation.tailrec
25 import scala.util.{Failure, Success, Try}
26 
27 object DatabaseTransactions {
28 
29   private val retries = 5
30 
31   implicit class RichDatabase(val self: DBConnection) extends AnyVal {
32 
33     def retryableExceptionTxBoundary[A]: TxBoundary[A] = new TxBoundary[A] {
34       def finishTx(result: A, tx: Tx): A = {
35         finishInternal(result, tx, retries)
36       }
37 
38       @SuppressWarnings(Array("org.wartremover.warts.Throw"))
39       @tailrec
40       private def finishInternal(result: A, tx: Tx, retries: Int): A = {
41         (retries, Try(tx.commit())) match {
42           case (_, Success(_)) => result
43           case (0, Failure(e)) => throw e
44           case (retry, _)      => finishInternal(result, tx, retry - 1)
45         }
46       }
47     }
48 
49     def retryableTx[A](
50       execution: DBSession => A
51     )(implicit boundary: TxBoundary[A] = retryableExceptionTxBoundary[A]): A = {
52       self.localTx(execution)(boundary)
53     }
54   }
55 
56 }
Line Stmt Id Pos Tree Symbol Tests Code
29 21891 969 - 970 Literal <nosymbol> 5
33 21844 1101 - 1104 Apply org.make.api.technical.DatabaseTransactions.RichDatabase.$anon.<init> new $anon()
35 20529 1174 - 1209 Apply org.make.api.technical.DatabaseTransactions.RichDatabase.$anon.finishInternal $anon.this.finishInternal(result, tx, DatabaseTransactions.this.retries)
35 21007 1201 - 1208 Select org.make.api.technical.DatabaseTransactions.retries DatabaseTransactions.this.retries
43 19553 1488 - 1495 Throw <nosymbol> throw e
44 21183 1557 - 1566 Apply scala.Int.- retry.-(1)
44 20151 1530 - 1567 Apply org.make.api.technical.DatabaseTransactions.RichDatabase.$anon.finishInternal $anon.this.finishInternal(result, tx, retry.-(1))
52 21343 1736 - 1769 Apply scalikejdbc.DBConnection.localTx RichDatabase.this.self.localTx[A](execution)(boundary)