Screenshot CC BY-NC 3.0 Before: the mess CC BY-NC 3.0 Before: - - PowerPoint PPT Presentation

screenshot
SMART_READER_LITE
LIVE PREVIEW

Screenshot CC BY-NC 3.0 Before: the mess CC BY-NC 3.0 Before: - - PowerPoint PPT Presentation

Screenshot CC BY-NC 3.0 Before: the mess CC BY-NC 3.0 Before: the mess CC BY-NC 3.0 Before: the mess Akka & Spray RabbitMQ C++ & CUDA Cassandra CC BY-NC 3.0 Before: the mess scene topic (Map[String, String],


slide-1
SLIDE 1
slide-2
SLIDE 2

🚬 🚬

slide-3
SLIDE 3

CC BY-NC 3.0

Screenshot

slide-4
SLIDE 4

CC BY-NC 3.0

Before: the mess

slide-5
SLIDE 5

CC BY-NC 3.0

Before: the mess

slide-6
SLIDE 6

CC BY-NC 3.0

Before: the mess

Cassandra Akka & Spray C++ & CUDA RabbitMQ

slide-7
SLIDE 7

CC BY-NC 3.0

Before: the mess

scene topic identity topic (Map[String, String], Array[Byte]) (Map[String, String], Array[Byte])

slide-8
SLIDE 8

CC BY-NC 3.0

Before: the mess

_tmp_x topics JSON scene topic identity topic (Map[String, String], Array[Byte]) (Map[String, String], Array[Byte])

slide-9
SLIDE 9

CC BY-NC 3.0

Before: the mess

fire-and-forget at-most-once non-durable fire-and-forget at-most-once

slide-10
SLIDE 10

CC BY-NC 3.0

Asynchronous request–response orchestration

class Orchestrator extends Actor with ActorFSM[Orchestrator.State, Orchestrator.Data] { startWith(Idle, UninitializedData) when(Idle, idleTimeout)(idleSF) when(ImageProcessing, stepTimeout)(imageProcessingSF) when(WaitingForProcessingResult, stepTimeout)(waitingForProcessingSF) whenUnhandled(timeoutSF)

  • nTransition {

case _ -> Aborted => ??? ... } def idleSF: StateFunction = ??? def imageProcessingSF: StateFunction = ??? def waitingForProcessingSF: StateFunction = ??? def timeoutSF: StateFunction = { case Event(StateTimeout, data: RunningTransactionData) => goto(Aborted) } }

slide-11
SLIDE 11

CC BY-NC 3.0

After: proper microservices

text identity ingest dashboard scene

slide-12
SLIDE 12

CC BY-NC 3.0

After: proper microservices

text identity ingest dashboard scene

slide-13
SLIDE 13

CC BY-NC 3.0

After: proper microservices

text identity ingest dashboard scene

Akka Kafka Lagom Cassandra

slide-14
SLIDE 14

CC BY-NC 3.0

After: proper microservices

text identity ingest dashboard scene

tweet-image topic identity group text group scene topic identity topic scene group text topic

slide-15
SLIDE 15

CC BY-NC 3.0

After: proper microservices

text identity ingest dashboard scene

tweet-image topic scene topic identity topic text topic message Scene { … } message Identity { … } bytes image; message Envelope { int32 version = 1; string handle = 2; int64 processingTimestamp = 3; int64 ingestionTimestamp = 4; string correlationId = 5; string messageId = 6; string messageType = 7; bytes payload = 8; } message Text { … }

slide-16
SLIDE 16

CC BY-NC 3.0

After: proper microservices

text identity ingest dashboard scene

at-least-once at-least-once at-most-once fire-and-forget at-least-once

slide-17
SLIDE 17

CC BY-NC 3.0

Persistence and formats

message Envelope {
 int32 version = 1;
 string handle = 2;
 int64 processingTimestamp = 3;
 int64 ingestionTimestamp = 4;
 string correlationId = 5;
 string messageId = 6;
 string messageType = 7;
 bytes payload = 8;
 }

slide-18
SLIDE 18

CC BY-NC 3.0

Persistence and formats

message Text { repeated string areas = 1;
 }

slide-19
SLIDE 19

CC BY-NC 3.0

Persistence and formats

message Scene { message Label {
 string label = 1;
 double score = 2;
 } 
 repeated Label labels = 3;
 }

slide-20
SLIDE 20

CC BY-NC 3.0

Persistence and formats

message Identity {


  • neof face {


IdentifiedFace identifiedFace = 1;
 UnknownFace unknownFace = 2;
 }
 
 message IdentifiedFace {
 string name = 1;
 double score = 2;
 }
 
 message UnknownFace { }
 }

slide-21
SLIDE 21

CC BY-NC 3.0

Persistence and formats

message IdentifyFace {
 int64 ingestionTimestamp = 2;
 string correlationId = 3;
 string handle = 4;
 bytes image = 5;
 }
 
 message IdentifyFaces {
 repeated IdentifyFace identifyFaces = 1;
 }
 
 message FaceImage {
 double confidence = 1;
 int32 x = 2;
 int32 y = 3;
 int32 w = 4;
 int32 h = 5;
 bytes rgbBitmap = 6;
 }

slide-22
SLIDE 22

CC BY-NC 3.0

Fire–and–forget send

  • bject Act {

def props(config: Config): Props = { val producerConf = KafkaProducer.Conf(config.getConfig("..."), new StringSerializer, KafkaSerializer[Envelope](_.toByteArray)) Props(classOf[Act], producerConf) } } class Act(producerConf: KafkaProducer.Conf[String, Envelope]) extends Actor { private[this] val producer = KafkaProducer(conf = producerConf)

  • verride def receive: Receive = {

case TweetImage(handle, content) => producer.send(KafkaProducerRecord("tweet-image", handle, Envelope(version = 100, handle = handle, ingestionTimestamp = System.nanoTime(), processingTimestamp = System.nanoTime(), messageId = UUID.randomUUID().toString, correlationId = UUID.randomUUID().toString, payload = content))) } }

slide-23
SLIDE 23

CC BY-NC 3.0

At least once delivery I

class SceneClassifierActor(…) extends Actor { private[this] val kafkaConsumerActor = context.actorOf(…) private[this] val producer = KafkaProducer(…)

  • verride def receive: Receive = {

case extractor(consumerRecords) => val futures = consumerRecords.pairs.flatMap { case (_, envelope) => val outEnvelope = … Some(producer.send(KafkaProducerRecord("scene", envelope.handle, outEnvelope))) } import context.dispatcher Future.sequence(futures).onSuccess { case _ => kafkaConsumerActor ! Confirm(consumerRecords.offsets, commit = true) } } }

slide-24
SLIDE 24

CC BY-NC 3.0

At least once delivery II

class IdentityMatcherActor(...) extends PersistentActor with AtLeastOnceDelivery {

  • verride val persistenceId: String = "identity-matcher-actor"

def identifyFacesAndSend(identifyFaces: Seq[IdentifyFace])(implicit executor: ExecutionContext): Future[Unit] = { // Future.sequence(producer.send(...)) } def handleIdentifyFace: Receive = { case (deliveryId: Long, identifyFaces: IdentifyFaces) => import context.dispatcher identifyFacesAndSend(identifyFaces.identifyFaces).onSuccess { case _ => confirmDelivery(deliveryId) } case IdentifyFaces(faces) => import context.dispatcher identifyFacesAndSend(faces).onFailure { case _ => self ! Kill } }

  • verride def receiveRecover: Receive = handleIdentifyFace
  • verride def receiveCommand: Receive = handleIdentifyFace orElse {

case extractor(consumerRecords) => val identifyFaces = consumerRecords.pairs.map { case (_, envelope) => IdentifyFace(envelope.ingestionTimestamp, envelope.correlationId, envelope.handle, envelope.payload)) } persist(IdentifyFaces(identifyFaces = identifyFaces)) { result => deliver(self.path)(deliveryId => (deliveryId, result)) sender() ! Confirm(consumerRecords.offsets, commit = true) } } }

slide-25
SLIDE 25

CC BY-NC 3.0

At least once delivery III

public interface TweetImageService extends Service {
 Topic<Envelope> tweetImageTopic();
 …
 }
 public class TextServiceImpl implements TextService {
 private final PersistentEntityRegistry persistentEntityRegistry;
 
 public Topic<Envelope> textTopic() {
 return TopicProducer.singleStreamWithOffset(offset -> persistentEntityRegistry
 .eventStream(TextEntityEvent.OcredTag.INSTANCE, offset)
 .map(p -> new Pair<>(p.first().envelope(), offset))
 );
 }
 
 @Inject
 public TextServiceImpl(PersistentEntityRegistry persistentEntityRegistry, TweetImageService tweetImageService) {
 this.persistentEntityRegistry = persistentEntityRegistry;
 persistentEntityRegistry.register(TextEntity.class);
 tweetImageService.tweetImageTopic().subscribe().withGroupId("text").atLeastOnce(Flow.fromFunction(this::extractText));
 }
 
 private Done extractText(Envelope envelope) {
 TextEntityCommand.Ocr command = new TextEntityCommand.Ocr(…);
 PersistentEntityRef<TextEntityCommand> ref = persistentEntityRegistry.refFor(TextEntity.class, envelope.handle());
 ref.ask(command);
 return Done.getInstance();
 }
 
 }

slide-26
SLIDE 26

CC BY-NC 3.0

At most once delivery

class DashboardSinkActor(...) extends Actor { private[this] val kafkaConsumerActor = context.actorOf(...)

  • verride def receive: Receive = {

case extractor(consumerRecords) => consumerRecords.pairs.foreach { case (_, envelope) => context.system.eventStream.publish(envelope); } kafkaConsumerActor ! Confirm(consumerRecords.offsets, commit = true) } }

slide-27
SLIDE 27

CC BY-NC 3.0

ENOUGH SLIDES!

slide-28
SLIDE 28

CC BY-NC 3.0

After: proper microservices

text identity ingest dashboard scene

slide-29
SLIDE 29

@cakesolutions

www.cakesolutions.net

MANCHESTER LONDON NEW YORK

CC BY-NC 3.0

enquiries@cakesolutions.net

slide-30
SLIDE 30