Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building Reactive Systems

Building Reactive Systems

Eduardo Costa

November 25, 2017
Tweet

More Decks by Eduardo Costa

Other Decks in Programming

Transcript

  1. About me - Eduardo Costa - 99ner - Backend developer

    - Scala enthusiastic - @jeduardocosta
  2. Agenda - Demystifying Reactive - Back-pressure - Circuit breaker -

    Event Driven Architecture - Event Sourcing and CQRS - How can we start?
  3. Back Pressure // Getting a stream of jobs from an

    imaginary external system as a Source val jobs: Source[Job, NotUsed] = inboundJobsConnector() jobs .buffer(1000, OverflowStrategy.backpressure) .map(url => pipeline(Get(url)).map((url, _))) .mapAsync(4)(identity) .map(parseUrls) .mapConcat(identity) .runWith(Sink.foreach(println)) OverflowStrategy.dropBuffer | OverflowStrategy.dropHead OverflowStrategy.dropTail | OverflowStrategy.dropNew
  4. Circuit Breaker class DangerousActor extends Actor with ActorLogging { import

    context.dispatcher val breaker = new CircuitBreaker( context.system.scheduler, maxFailures = 5, callTimeout = 10.seconds, resetTimeout = 1.minute).onOpen(notifyMeOnOpen()) def notifyMeOnOpen(): Unit = log.warning("My CircuitBreaker is now open, and will not close for one minute")
  5. "Event-Driven Architecture (EDA) is a design paradigm in which a

    software component executes in response to receiving one or more event notifications" (Gartner)
  6. The good part - No need for mapping between domain

    objects and database representation - Easy to test and debug - Production troubleshooting - Audit log for free - Scalability allowing scale out bounded context separately - Handle complex domain separating read and write responsibility
  7. The bad part - Unfamiliar model - Defines events can

    be hard - Versioning - Eventual Consistency
  8. Event Sourcing and CQRS Actions() .onCommand[SubmitPaymentStatus, Done] { case (SubmitPaymentStatus(userId,

    status), ctx, _) if userId == transaction.creator => status match { case PaymentInfoStatus.Approved => ctx.thenPersist(PaymentApproved(transaction.itemId))(_ => ctx.reply(Done)) case PaymentInfoStatus.Rejected => ctx.thenPersist(PaymentRejected(transaction.itemId))(_ => ctx.reply(Done)) } case (_, ctx, _) => ctx.invalidCommand("Only the auction creator can submit payment status") ctx.done } .onEvent { case (PaymentApproved(_), _) => Some(transaction.updateStatus(PaymentConfirmed)) case (PaymentRejected(_), _) => Some(transaction.updateStatus(PaymentPending)) }
  9. Steps - Embrace reactive principles - Asynchronous processing with Streams

    / Back-pressuring - Start with reactive programming - Use circuit-breaker - Don't build microliths - Events over states (Event Sourcing and CQRS)
  10. References - CQRS Journey (https://msdn.microsoft.com/en-us/library/jj554200.aspx) - How Events Are Reshaping

    Modern Systems - Jonas Bonér (https://speakerdeck.com/jboner/how-events-are-reshaping-modern-systems) - Lessons Learned From PayPal: Implementing Back-Pressure With Akka Streams And Kafka (https://www.lightbend.com/blog/lessons-learned-from-paypal-implementing-back-pres sure-with-akka-streams-and-kafka)