scp2: task 2 + 3
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import collection.mutable.Map
|
||||
import java.util.UUID
|
||||
|
||||
class Bank(val allowedAttempts: Integer = 3) {
|
||||
|
||||
@@ -9,54 +10,95 @@ class Bank(val allowedAttempts: Integer = 3) {
|
||||
|
||||
def processing: Boolean = !transactionsPool.isEmpty
|
||||
|
||||
// TODO
|
||||
// Adds a new transaction for the transfer to the transaction pool
|
||||
def transfer(from: String, to: String, amount: Double): Unit = ???
|
||||
def transfer(from: String, to: String, amount: Double): Unit = {
|
||||
if (amount <= 0) {
|
||||
val t = new Transaction(from, to, amount)
|
||||
t.fail()
|
||||
completedTransactions.add(t)
|
||||
return
|
||||
}
|
||||
|
||||
val f = getAccount(from)
|
||||
val t = getAccount(to)
|
||||
|
||||
if (f.isEmpty || t.isEmpty) {
|
||||
val t = new Transaction(from, to, amount)
|
||||
t.fail()
|
||||
completedTransactions.add(t)
|
||||
return
|
||||
}
|
||||
|
||||
if (f.get.balance < amount) {
|
||||
val t = new Transaction(from, to, amount)
|
||||
t.fail()
|
||||
completedTransactions.add(t)
|
||||
return
|
||||
}
|
||||
|
||||
transactionsPool.add(new Transaction(from, to, amount))
|
||||
}
|
||||
|
||||
// TODO
|
||||
// Process the transactions in the transaction pool
|
||||
// The implementation needs to be completed and possibly fixed
|
||||
def processTransactions: Unit = {
|
||||
|
||||
// val workers : List[Thread] = transactionsPool.iterator.toList
|
||||
// .filter(/* select only pending transactions */)
|
||||
// .map(processSingleTransaction)
|
||||
val workers: List[Thread] = transactionsPool.iterator.toList
|
||||
.filter(_.isPending)
|
||||
.map(processSingleTransaction)
|
||||
|
||||
// workers.map( element => element.start() )
|
||||
// workers.map( element => element.join() )
|
||||
workers.map(element => element.start())
|
||||
workers.map(element => element.join())
|
||||
|
||||
/* TODO: change to select only transactions that succeeded */
|
||||
// val succeded : List[Transaction] = transactionsPool
|
||||
val succeded: List[Transaction] =
|
||||
transactionsPool.iterator.toList.filter(_.succeeded)
|
||||
|
||||
/* TODO: change to select only transactions that failed */
|
||||
// val failed : List[Transaction] = transactionsPool
|
||||
val failed: List[Transaction] =
|
||||
transactionsPool.iterator.toList.filter(_.failed)
|
||||
|
||||
// succeded.map(/* remove transactions from the transaction pool */)
|
||||
// succeded.map(/* add transactions to the completed transactions queue */)
|
||||
succeded.map(transactionsPool.remove(_))
|
||||
succeded.map(completedTransactions.add(_))
|
||||
|
||||
// failed.map(t => {
|
||||
/* transactions that failed need to be set as pending again;
|
||||
if the number of retry has exceeded they also need to be removed from
|
||||
the transaction pool and to be added to the queue of completed transactions */
|
||||
// })
|
||||
failed.map(t => {
|
||||
t.setPending()
|
||||
t.incrementAttempt()
|
||||
if (t.exceeded) {
|
||||
transactionsPool.remove(t)
|
||||
completedTransactions.add(t)
|
||||
}
|
||||
})
|
||||
|
||||
if (!transactionsPool.isEmpty) {
|
||||
processTransactions
|
||||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
// The function creates a new thread ready to process
|
||||
// the transaction, and returns it as a return value
|
||||
private def processSingleTransaction(t: Transaction): Thread = ???
|
||||
private def processSingleTransaction(t: Transaction): Thread =
|
||||
new Thread(() => {
|
||||
accountsRegistry.synchronized {
|
||||
val fromOpt = getAccount(t.from)
|
||||
val toOpt = getAccount(t.to)
|
||||
|
||||
// TODO
|
||||
// Creates a new account and returns its code to the user.
|
||||
// The account is stored in the local registry of bank accounts.
|
||||
def createAccount(initialBalance: Double): String = ???
|
||||
(fromOpt, toOpt) match {
|
||||
case (Some(from), Some(to)) =>
|
||||
from.withdraw(t.amount) match {
|
||||
case Right(updatedFrom) =>
|
||||
to.deposit(t.amount) match {
|
||||
case Right(updatedTo) =>
|
||||
accountsRegistry(t.from) = updatedFrom
|
||||
accountsRegistry(t.to) = updatedTo
|
||||
t.succeed()
|
||||
case Left(_) => t.fail()
|
||||
}
|
||||
case Left(_) => t.fail()
|
||||
}
|
||||
case _ => t.fail()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// TODO
|
||||
// Return information about a certain account based on its code.
|
||||
// Remember to handle the case in which the account does not exist
|
||||
def getAccount(code: String): Option[Account] = ???
|
||||
def createAccount(initialBalance: Double): String = {
|
||||
val code = UUID.randomUUID().toString
|
||||
accountsRegistry(code) = new Account(code, initialBalance)
|
||||
code
|
||||
}
|
||||
|
||||
def getAccount(code: String): Option[Account] = accountsRegistry.get(code)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,23 @@ class Transaction(
|
||||
private var status: TransactionStatus.Value = TransactionStatus.PENDING
|
||||
private var attempts = 0
|
||||
|
||||
def getStatus() = status
|
||||
def getStatus(): TransactionStatus.Value = status
|
||||
|
||||
def isPending(): Boolean = status == TransactionStatus.PENDING
|
||||
|
||||
def succeeded(): Boolean = status == TransactionStatus.SUCCESS
|
||||
|
||||
def failed(): Boolean = status == TransactionStatus.FAILED
|
||||
|
||||
def setPending(): Unit = status = TransactionStatus.PENDING
|
||||
|
||||
def incrementAttempt(): Unit = attempts += 1
|
||||
|
||||
def exceeded(): Boolean = attempts > retries
|
||||
|
||||
def succeed(): Unit = status = TransactionStatus.SUCCESS
|
||||
|
||||
def fail(): Unit = status = TransactionStatus.FAILED
|
||||
|
||||
// TODO: Implement methods that change the status of the transaction
|
||||
|
||||
|
||||
Reference in New Issue
Block a user