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

Building Reactive Systems

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

Building Reactive Systems

Avatar for Eduardo Costa

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)