CÓDIGO LABORATORIO AKKA IBDN

Código de práctica de introducción a actores de Akka.
mail@pastecode.io avatar
unknown
scala
2 months ago
3.6 kB
1
Indexable
Never
import akka.actor.{Actor, ActorRef, ActorSystem, Props}

// Creo el actor NetworkManager
class NetworkManager extends Actor {
  def receive: Receive = {
    case ForwardMessage(recipient, message) => {
      println(f"[NETWORK_MANAGER_ACTOR]: Forwarding message from ${sender().path.name} to ${recipient.path.name}")
      recipient ! message}
    case _ => println("Not supported")
  }
}

class CuentaBancaria extends Actor { // este es el actor principal, los demás se han hecho por que lo dice el enunciado pero habría prefeerido fusionarlos en uno sólo
  var balance = 6
  def receive: Receive = {
    case "withdraw" => withdraw(1)  // Por defecto, se retira 1 unidad si el mensaje es "withdraw"
    case Withdraw(amount) => withdraw(amount)
    case "balance" => println(f"[BANK_ACC_ACTOR_${self.path.name}]: Balance = $balance")
    case "deposit" => {
      balance += 1
      println(f"[BANK_ACC_${self.path.name}]: Received 1 unit of currency.")
    }
    case "reset" => balance = 6
    case Bizum(depositActor ,amount, recipient) => {
      depositActor ! DepositTo(amount, recipient)
      balance -= amount
    }
    case DepositFrom(amount) => {
      balance += amount
      println(f"[BANK_ACC_${self.path.name}]: Received ${amount} unit(s) of currency.")
    }
  }

  def withdraw(amount: Int): Unit = {
    if (amount <= balance) {
      balance -= amount
      println(f"[BANK_ACC_ACTOR_${self.path.name}]: Withdrawal of $amount successful. New balance = $balance")
    } else {
      println(f"[BANK_ACC_ACTOR_${self.path.name}]: Insufficient funds for withdrawal. Balance = $balance")
    }
}
}

class DepositActor extends Actor {
  def receive: Receive = {
    case DepositTo(amount, recipient) => {
      recipient ! DepositFrom(amount)
      println(f"[DEPOSIT_ACTOR]: Deposit order sent to ${recipient.path.name}.")
      }
    case _ => println("Not supported")
  }
}

class WithdrawActor extends Actor {
  def receive: Receive = {
    case WithdrawFrom(amount, recipient) => {
      recipient ! Withdraw(amount)
      println(f"[WITHDRAW_ACTOR]: Withdraw order sent to ${recipient.path.name}.")
      // ...
    }
    case _ => println("Not supported")
  }
}


case class ForwardMessage(recipient: ActorRef, message: Any)
case class Bizum(depositActor: ActorRef, amount: Int, recipient: ActorRef)
case class DepositFrom(amount: Int)
case class DepositTo(amount: Int, recipient: ActorRef)
case class Withdraw(amount: Int)
case class WithdrawFrom(amount: Int, recipient: ActorRef)

object Main extends App {
   val system = ActorSystem("NetworkSystem")
   type ActorRefType = ActorRef

   // Crear actores para la simulación de red
   val networkManager = system.actorOf(Props[NetworkManager], name = "networkManager")
   val bankacc1 = system.actorOf(Props[CuentaBancaria], name = "bankacc1")
   val bankacc2 = system.actorOf(Props[CuentaBancaria], name = "bankacc2")
   val depositActor = system.actorOf(Props[DepositActor], name = "depositActor")
   val withdrawActor = system.actorOf(Props[WithdrawActor], name = "withdrawActor")

  // Envío de mensajes. Todos los mensajes que vayan desde main irán a través de networkManager, utilizando el match case ForwardMessage.
  //  Los que sean entre actores, se comunicarán directamente en principio.
   networkManager ! ForwardMessage(depositActor, DepositTo(3, bankacc2))
   networkManager ! ForwardMessage(withdrawActor, WithdrawFrom(5, bankacc2))
   networkManager ! ForwardMessage(bankacc1, "balance")
   networkManager ! ForwardMessage(bankacc2, Bizum(depositActor ,1, bankacc1))

   system.terminate()
 }
Leave a Comment