为什么 Scala + Akka Typed App 没有日志输出?

问题描述 投票:0回答:1

我有一个问题,我的程序中没有任何日志输出。请帮我解决问题并告诉我哪里出错了。 该应用程序是一个聊天应用程序。它由 UserActor、Main、RoomActor 组成。

主要

package Chat

import akka.actor.typed.{ActorRef, ActorSystem, Behavior}
import akka.actor.typed.scaladsl.Behaviors

object Main extends App {
    sealed trait MainActor

    def apply(): Behavior[MainActor] = Behaviors.setup { context =>
        val system: ActorSystem[Nothing] = ActorSystem(Behaviors.empty, "ChatSystem")

        val userActor = system.systemActorOf(UserActor(), "userActor")

        val roomActor = system.systemActorOf(RoomActor(), "roomActor")

        userActor ! UserActor.CreateUser("John", "Doe", 25, system.deadLetters)
        val roomName = "General"
        roomActor ! RoomActor.CreateRoom(userActor, roomName)

        userActor ! UserActor.SendMessageToRoom(roomActor, "Hello, everyone!", "John")

        Thread.sleep(5000)
        system.terminate()

        Behaviors.receiveMessage {
            case _ =>
                context.log.info("Unknown message for MainActor")
                Behaviors.same
        }
    }
}

用户演员

package Chat

import Chat.RoomActor.RoomCommand
import akka.actor.typed.{ActorRef, Behavior}
import akka.actor.typed.scaladsl.Behaviors

import java.util.UUID

object UserActor {
    sealed trait UserCommand
    case class CreateUser(name: String, surname: String, age: Int, userActor: ActorRef[UserCommand]) extends UserCommand
    case class User(name: String, surname: String, age: Int, userId: String, userActor: ActorRef[UserCommand])
    case class SendMessageToRoom(room: ActorRef[RoomCommand], content: String, userName: String) extends UserCommand
    case class LeftRoomNotification(user: ActorRef[UserCommand], roomName: String) extends UserCommand
    case class JoinRoomNotification(user: ActorRef[UserCommand], roomName: String) extends UserCommand
    case class ReceiveMessage(sender: ActorRef[UserCommand], content: String) extends UserCommand

    def apply(): Behavior[UserCommand] = userBehavior(Map.empty)

    private def userBehavior(users: Map[String, User]): Behavior[UserCommand] =
        Behaviors.receive{(context, message) =>
            message match {
                case ReceiveMessage(sender, content) =>
                    context.log.info(s"User ${context.self} received message from $sender: $content")
                    Behaviors.same
                case SendMessageToRoom(room, content, userName) =>
                    users.get(userName) match {
                        case Some(user) =>
                            room ! RoomActor.BroadcastMessage(user.userActor, content)
                        case None =>
                            throw new Exception(s"Unknown User $userName!")
                    }
                    Behaviors.same
                case CreateUser(name, surname, age, userActor) =>
                    val userId = UUID.randomUUID().toString
                    val newUser = User(name, surname, age, userId, userActor)
                    context.log.info(s"User $newUser added in user list")
                    context.log.info(s"Created user: $userId")
                    users + (userId -> newUser)
                    Behaviors.same
                case LeftRoomNotification(user, roomName) =>
                    context.log.info(s"User $user received LeftRoomNotification for room: $roomName")
                    Behaviors.same
                case JoinRoomNotification(user, roomName) =>
                    context.log.info(s"User $user received JoinRoomNotification for room: $roomName")
                    Behaviors.same
                case _ =>
                    context.log.warn("Unknown message for UserActor")
                    Behaviors.same
            }
        }
}

房间演员

package Chat

import Chat.UserActor.{JoinRoomNotification, UserCommand}
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.{ActorRef, Behavior}

import java.time.LocalDateTime
import scala.collection.mutable

object RoomActor {
    sealed trait RoomCommand

    case class CreateRoom(user: ActorRef[UserCommand], roomName: String) extends RoomCommand
    case class LeaveRoom(user: ActorRef[UserCommand], roomName: String) extends RoomCommand
    case class JoinRoom(user: ActorRef[UserCommand], roomName: String) extends RoomCommand
    case class BroadcastMessage(user: ActorRef[UserCommand], content: String) extends RoomCommand
    case class Room(roomName: String, owner: ActorRef[UserCommand], creationDate: LocalDateTime, users: mutable.Set[ActorRef[UserCommand]])

    def apply(): Behavior[RoomCommand] = roomBehavior(Map.empty)

    private def roomBehavior(rooms: Map[String, Room]): Behavior[RoomCommand] =
        Behaviors.receive { (context, message) =>
            message match {
                case CreateRoom(user, roomName) =>
                    val room = Room(roomName, user, LocalDateTime.now(), mutable.Set(user))
                    context.log.info(s"$user created room: $roomName")
                    roomBehavior(rooms + (roomName -> room))
                case LeaveRoom(user, roomName) =>
                    rooms.get(roomName).foreach { room =>
                        room.users -= user
                        if(user == room.owner) {
                            if(room.users.isEmpty) {
                                context.log.info(s"$user was the owner and the last user in room: $roomName. Removing the room.")
                                roomBehavior(rooms - roomName)
                            } else {
                                val newOwner = room.users.head
                                context.log.info(s"$user was the owner. Assigning the new owner: $newOwner")
                                val updatedRoom = room.copy(owner = newOwner)
                                roomBehavior(rooms + (roomName -> updatedRoom))
                            }
                        } else {
                            context.log.info(s"$user left the room: $roomName")
                            for (elem <- room.users) {
                                elem.tell(UserActor.LeftRoomNotification(user, roomName))
                            }
                            Behaviors.same
                        }
                    }
                    context.log.info(s"$user left room: $roomName")
                    Behaviors.same
                case JoinRoom(user, roomName) =>
                    rooms.get(roomName).foreach {room =>
                        room.users += user
                        user ! JoinRoomNotification(user, roomName)
                    }
                    Behaviors.same

                case BroadcastMessage(sender, content) =>
                    rooms.values.foreach{room =>
                        room.users.foreach{user =>
                            if(user != sender) {
                                user ! UserActor.ReceiveMessage(sender, content)
                            }
                        }
                    }
                    context.log.info(s"Broadcast message from $sender: $content")
                    Behaviors.same

                case _ =>
                    throw new IllegalArgumentException("Unknown message for RoomActor")
                    Behaviors.same
            }
        }
}

输出为:

15:24:35: Executing ':Main.main()'...

> Task :compileJava NO-SOURCE

> Task :compileScala
    [Warn] : -target is deprecated: Use -release instead to compile against the correct platform API.
    one warning found

> Task :processResources NO-SOURCE
> Task :classes
> Task :Main.main()

Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

For more on this, please refer to https://docs.gradle.org/8.5/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.

BUILD SUCCESSFUL in 13s
2 actionable tasks: 2 executed
15:24:49: Execution finished ':Main.main()'.

我已经添加了Thread.sleep(5000),但是程序仍然没有任何日志输出。我尝试添加 root level =“DEBUG”和“info”的 logback.xml。另外,我尝试用 Await.result(system.whenTermulated, Duration.Inf) 替换 Thread.sleep

java scala akka slf4j typed
1个回答
0
投票

因为你没有运行任何东西。

Behaviors.xx
只创建一个 actor 工厂,你必须显式地让
ActorSystem
生成它。

object Maim extends App {
  sealed trait MainActor

  // setup your guardian actor here
  val guardianActor: Behavior[Any] = Behaviors.receive { (context, message) =>
    // like java constructor here
    val userActor = system.systemActorOf(UserActor(), "userActor")
    // other...

    // react to message
    message match {
      case _ =>
        context.log.info("Unknown message for MainActor")
        Behaviors.same
    }
  }

  // start ActorSystem here...
  val system: ActorSystem[Nothing] = ActorSystem(guardianActor, "ChatSystem")
© www.soinside.com 2019 - 2024. All rights reserved.