CODESAMPLE

Space-Based Architecture - Scala

Share on:

The Space-Based Architecture pattern decouples components of a system by using a message-based communication system, often referred to as a “space.” Components interact by sending and receiving messages without direct knowledge of each other. This promotes scalability, fault tolerance, and flexibility. In Scala, Akka’s Actors provide a natural implementation of this pattern. Each actor represents a component and communicates via asynchronous messages. This example demonstrates a simple order processing system with an OrderService and a PaymentService communicating through messages. The use of immutable data and pattern matching on messages is idiomatic Scala and enhances the clarity and safety of the interaction.

import akka.actor.{Actor, ActorSystem, Props}

// Messages
sealed trait OrderEvent
case class CreateOrder(orderId: String, amount: Double) extends OrderEvent
case object OrderCreated extends OrderEvent
case object PaymentProcessed extends OrderEvent
case class PaymentFailed(orderId: String, reason: String) extends OrderEvent

// Order Service Actor
class OrderService extends Actor {
  override def receive: Receive = {
    case CreateOrder(orderId, amount) =>
      println(s"Order Service: Received CreateOrder for $orderId, amount $amount")
      // Simulate order creation
      sender() ! OrderCreated
    case OrderCreated =>
      println("Order Service: Order created.  Requesting Payment.")
      context.actorFor("PaymentService") ! CreateOrder(orderId = "123", amount = 100.0) // Hardcoded for simplicity
    case PaymentProcessed =>
      println("Order Service: Payment processed successfully.")
    case PaymentFailed(orderId, reason) =>
      println(s"Order Service: Payment failed for $orderId, reason: $reason")
  }
}

// Payment Service Actor
class PaymentService extends Actor {
  override def receive: Receive = {
    case CreateOrder(orderId, amount) =>
      println(s"Payment Service: Received CreateOrder for $orderId, amount $amount")
      // Simulate payment processing
      if (amount > 50) {
        sender() ! PaymentProcessed
      } else {
        sender() ! PaymentFailed(orderId, "Amount too low")
      }
  }
}

// Main Application
object SpaceBasedArchitecture extends App {
  val system = ActorSystem("SpaceBasedSystem")

  val orderService = system.actorOf(Props[OrderService], "OrderService")
  val paymentService = system.actorOf(Props[PaymentService], "PaymentService")

  orderService ! CreateOrder("456", 75.0)

  Thread.sleep(1000) // Allow messages to be processed
  system.terminate()
}