na creditas architecture event driven - qconsp · event driven architecture na creditas...

Post on 29-May-2020

50 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

@camposmilaa

Event Driven Architecturena Creditas

@camposmilaa

@camposmilaa

Camila CamposCreditas

Rails Girls São PauloWomen Dev Summit

@camposmilaa

@camposmilaa

Plataforma online

Empréstimo com garantia

Juros baixos pra você <3

creditas.com.br

vagas.creditas.com.br

@CreditasBR

@camposmilaa

Event Driven Architecturena Creditas

@camposmilaa

@camposmilaa

Orientação a Objetos

@camposmilaa

Orientação a Objetos

Alan Kay

@camposmilaa

"OOP to me means only messaging, local retention and

protection and hiding of state-process, and extreme late-binding of all things."

Alan Kay

@camposmilaa

"The big idea is messaging [...] The key in making great and

growable systems is much more to design how its modules

communicate rather than what their internal properties and

behaviors should be"

Alan Kay

@camposmilaa

ANALISE DE RISCO- data

- resultado

IMÓVEL- endereço

- valorCLIENTE- cpf

- nome- data de nascimento

@camposmilaa

@camposmilaa

Orientação a Objetosé sobre

Troca de Mensagens

@camposmilaa

Orientação a Objetosé sobre

Comunicação

@camposmilaa

Orientação a Objetosé sobre

Comunicação

@camposmilaa

Remetente(emissor)

Comunicação

@camposmilaa

Remetente(emissor)

Destinatário(receptor)

Comunicação

@camposmilaa

Remetente(emissor)

Destinatário(receptor)Mensagem

Comunicação

@camposmilaa

Remetente(emissor)

Destinatário(receptor)Mensagem

Comunicação

CódigoContexto

Canal

@camposmilaa

Domain Driven Design(DDD)

@camposmilaa

@camposmilaa

cliente

cliente

Linguagem Ubíqua

@camposmilaa

Bounded Context

@camposmilaa

Creditas + DDD

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

Entender e modelara realidade

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

Invasão de contextos

@camposmilaa

Invasão de contextosOnboarding de devs

@camposmilaa

Invasão de contextosOnboarding de devs

Deploy lento

@camposmilaa

Invasão de contextosOnboarding de devs

Deploy lentoTudo ou nada

@camposmilaa

Invasão de contextosOnboarding de devs

Deploy lentoTudo ou nada

Right tool for the job

@camposmilaa

Invasão de contextosOnboarding de devs

Deploy lentoTudo ou nada

Right tool for the jobEscalabilidade

@camposmilaa

Micro-services! .

@camposmilaa

@camposmilaa

@camposmilaa

Isolamento real

@camposmilaa

Isolamento realServiços menores

@camposmilaa

Isolamento realServiços menores

Deploy menor

@camposmilaa

Isolamento realServiços menores

Deploy menor, mas mais complexo

@camposmilaa

Isolamento realServiços menores

Deploy menor, mas mais complexoRight tool for the job

@camposmilaa

Isolamento realServiços menores

Deploy menor, mas mais complexoRight tool for the job

Escalabilidade

@camposmilaa

@camposmilaa

Comunicação entre sistemas

@camposmilaa

@camposmilaa

A B

Remote Procedure Invocation (RPC)

@camposmilaa

Simplicidade

@camposmilaa

SimplicidadeGeralmente síncrona

@camposmilaa

SimplicidadeGeralmente síncrona

Encapsulamento

@camposmilaa

SimplicidadeGeralmente síncrona

EncapsulamentoAcoplamento

@camposmilaa

SimplicidadeGeralmente síncrona

EncapsulamentoAcoplamentoPerformance

@camposmilaa

SimplicidadeGeralmente síncrona

EncapsulamentoAcoplamentoPerformance

Disponibilidade

@camposmilaa

A B

Remote Procedure Invocation (RPC)

@camposmilaa

Mensageria

@camposmilaa

A B

Mensageria

Mes

sage

bu

s

@camposmilaa

Assíncrona

@camposmilaa

AssíncronaDesacoplamento

@camposmilaa

AssíncronaDesacoplamentoNão bloqueante

@camposmilaa

A B

Mensageria

Mes

sage

bu

s

@camposmilaa

AssíncronaDesacoplamentoNão bloqueante

Realidade

@camposmilaa

Remetente(emissor)

Destinatário(receptor)Mensagem

Código

Comunicação

Contexto

Canal

@camposmilaa

Remetente(emissor)

Destinatário(receptor)Mensagem

Comunicação entre sistemas

ContratoContexto

Canal

@camposmilaa

Nem tudo são flores!

@camposmilaa

Complexidade

@camposmilaa

ComplexidadeRequest-Response

@camposmilaa

ComplexidadeRequest-Response

Tratamento de erros

@camposmilaa

ComplexidadeRequest-Response

Tratamento de errosSistema para mensageria

@camposmilaa

Teorema CAP

Escolha dois

Tolerância a falhas

DisponibilidadeConsistência

@camposmilaa

Mensageria

A B

Mes

sage

bu

s

@camposmilaa

@camposmilaa

Tipos de mensagem

@camposmilaa

@camposmilaa

Comandos

@camposmilaa

Comandos

Documentos

@camposmilaa

Comandos

Documentos

Eventos

@camposmilaa

Eventos são fatos que expressam o passado

@camposmilaa

A vida é expressada por eventos

@camposmilaa

Como cê tá?

@camposmilaa

BEM ou MAL

@camposmilaa

BEM ou MAL

@camposmilaa

@camposmilaa

@camposmilaa

1.2.3.4.5.

@camposmilaa

Solicitei um empréstimo1.2.3.4.5.

@camposmilaa

Solicitei um empréstimoPreenchi o cadastro

1.2.3.4.5.

@camposmilaa

Solicitei um empréstimoPreenchi o cadastro

Coloquei a casa como garantia

1.2.3.4.5.

@camposmilaa

Solicitei um empréstimoPreenchi o cadastro

Coloquei a casa como garantiaMeu crédito foi aprovado

1.2.3.4.5.

@camposmilaa

Solicitei um empréstimoPreenchi o cadastro

Coloquei a casa como garantiaMeu crédito foi aprovado

O empréstimo foi concedido

1.2.3.4.5.

@camposmilaa

Event Driven Architecture(EDA)

@camposmilaa

Martin Fowler

1.2.

3.4.

@camposmilaa

Event Notification

Martin Fowler

1.2.

3.4.

@camposmilaa

Event Notification

Solicitações Priorização

Crédito Solicitado

@camposmilaa

Event Notification

Solicitações Priorização

Crédito Solicitado

Quais dados?

@camposmilaa

Event NotificationEvent-carried State

Transfer

Martin Fowler

1.2.

3.4.

@camposmilaa

Event-carried State Notification

Solicitações Notificações

Crédito Solicitado

+ dados

@camposmilaa

Event NotificationEvent-carried State

TransferEvent Sourcing

Martin Fowler

1.2.

3.4.

@camposmilaa

Event Sourcing diz que todo estado é transiente e que

apenas fatos são persistidos

@camposmilaa

ANALISE DE RISCO- data

- resultado

IMÓVEL- endereço

- valor

CLIENTE- cpf

- nome

@camposmilaa

Modelo tradicional

Clienteid cpf nome

1 11122233344 Pedro Salomão

2 55566677788 Maria Rita

3 98765432100 Sandy & Junior

@camposmilaa

Modelo tradicional

Clienteid cpf nome

1 11122233344 Pedro Salomão

2 55566677788 Maria Rita

3 98765432100 Sandy

@camposmilaa

Event Sourcing

Event Store

Cliente Cadastrado {nome: Sandy & Junior, cpf: 12345678900}

Solicitação criada {valor: 50.000, motivo: Reforma}

Garantia Adicionada {tipo: Casa, valor: 200.000}

Nome Alterado {nome: Sandy}

@camposmilaa

Cliente preenche cadastro

Solicitação criada

@camposmilaa

Cliente preenche cadastro

Cliente adiciona

documento

Doc adicionadoSolicitação criada

@camposmilaa

Cliente preenche cadastro

Cliente adiciona

documento

Doc removidoDoc adicionado

Solicitação criada

Cliente remove

documento

@camposmilaa

Cliente preenche cadastro

Cliente adiciona

documento

Cliente adiciona

documento

Doc adicionadoDoc removido

Doc adicionadoSolicitação criada

Cliente remove

documento

@camposmilaa

Cliente preenche cadastro

Cliente adiciona

documento

Cliente cadastra garantia

Cliente adiciona

documento

Garantia adicionadaDoc adicionadoDoc removido

Doc adicionadoSolicitação criada

Cliente remove

documento

@camposmilaa

Cliente preenche cadastro

Cliente adiciona

documento

Cliente cadastra garantia

Cliente adiciona

documento

Creditas aprova o crédito

Crédito aprovadoGarantia adicionada

Doc adicionadoDoc removido

Doc adicionadoSolicitação criada

Cliente remove

documento

@camposmilaa

Crédito aprovadoGarantia adicionada

Doc adicionadoDoc removido

Doc adicionadoSolicitação criada

Query

@camposmilaa

Crédito aprovadoGarantia adicionada

Doc adicionadoDoc removido

Doc adicionadoSolicitação criada

Query

@camposmilaa

Event NotificationEvent-carried State

TransferEvent Sourcing

CQRS

Martin Fowler

1.2.

3.4.

@camposmilaa

Asking a question should not change the answer

Bertrand Meyer

@camposmilaa

Commands

Queries

Command Query Separation

@camposmilaa

Modelo tradicional

@camposmilaa

Command Query Responsibility Segregation

@camposmilaa

CQRSCommand Model

@camposmilaa

CQRSCommand Model

@camposmilaa

CQRSCommand Model

Query Model

@camposmilaa

CQRS

Base para relatóriosAplicação

@camposmilaa

CQRS + Event Sourcing

Event Sourcing Banco de leitura

evento 1, id: 2evento 2, id: 1evento 1, id: 1

id: 1, estado 2id: 2, estado 1

@camposmilaa

Crédito aprovadoGarantia adicionada

Doc adicionadoDoc removido

Doc adicionadoSolicitação criada

Query

@camposmilaa

Crédito aprovadoGarantia adicionada

Doc adicionadoDoc removido

Doc adicionadoSolicitação criada

@camposmilaa

Crédito aprovadoGarantia adicionada

Doc adicionadoDoc removido

Doc adicionadoSolicitação criada

Query

@camposmilaa

Quem já usou um sistema com event sourcing?

@camposmilaa

Adiciona atributo aos dados do veículo

app/vehicle_data/get_vehicle_data.rb | 2 +-

spec/infra/get_molicar_versions_spec.rb | 10 ++++++----

spec/use_case/fetch_vehicle_data_spec.rb | 2 +-

spec/vehicle_data/get_vehicle_data_spec.rb | 2 +-

4 files changed, 9 insertions(+), 7 deletions(-)

@camposmilaa

Saldo disponível

Conta Corrente 10.000

Conta Poupança 2.000

@camposmilaa

Saldo disponível

Conta Corrente 10.000

Conta Poupança 2.000

Extrato Conta Corrente

data valor descrição

03/05 +7000 Salário

05/05 +4000 Freela

06/05 -1000 Aluguel

@camposmilaa

@camposmilaa

@camposmilaa

Producer

Producer

Tópico 1

Tópico 2

Consumer

Consumer Group

Consumer

Consumer

@camposmilaa

Tópico

0 1 2 3 4 5 6

0 1 2 3 4 5 6 7 8 9 10 11 12

0 1 2 3 4 5 6 7 8 9

Partição 1

Partição 2

Partição 3

@camposmilaa

Tópico

0 1 2 3 4 5 6

1 1 2 3 4 5 6 7 8 9 10 11 12

2 1 2 3 4 5 6 7 8 9

Partição 1

Partição 2

Partição 3

@camposmilaa

Tópico

0 1 2 3 4 5 6

0 1 2 3 4 5 6 7 8 9 10 11 12

0 1 2 3 4 5 6 7 8 9

Partição 1

Partição 2

Partição 3

@camposmilaa

Tópico

0 1 2 3 4 5 6

0 1 2 3 4 5 6 7 8 9 10 11 12

0 1 2 3 4 5 6 7 8 9

Partição 1

Partição 2

Partição 3

@camposmilaa

O problema

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

@camposmilaa

Versão 1

Versão 3 Versão N

Versão X

@camposmilaa

A solução

@camposmilaa

Versão 1

Versão 3 Versão N

Versão X

@camposmilaa

Solicitação criada

Imóvel modificado

Condições alteradas

Pessoa adicionada

Garantia substituída

@camposmilaa

Solicitação criada

Imóvel modificado

Condições alteradas

Pessoa adicionada

Garantia substituída

@camposmilaa

@camposmilaa

/karafka/karafka

/camilacampos/sample-karafka-sinatra

@camposmilaa

AplicaçãoA

Front-end Eventos

@camposmilaa

AplicaçãoA

Front-endAplicação

ES

@camposmilaa

ACLAplicaçãoA

Front-end Evento Comando

@camposmilaa

AplicaçãoES

Comando Evento

@camposmilaa

Event Store

+Aplicação

ESComando Evento

@camposmilaa

Event Store

+

Projeção

+

AplicaçãoES

Comando Evento

@camposmilaa

Não fizemos

@camposmilaa

RespostaAplicação

AAplicação

ES

@camposmilaa

Aplicação Event SourcingSHOW ME THE CODE

@camposmilaa

Comando

{

"id": "id-da-solicitacao",

"data_da_solicitacao": "2019-05-04 22:28:14 UTC",

"valor_solicitado": 100000,

"motivo_do_emprestimo": "pagar dividas",

"solicitante": {"nome": "Mariazinha"},

"garantias": [{"type": "house", "value": 200000}],

"metadata": {

"timestamp": "2019-05-05 10:14:29 UTC",

"name": "CriarSolicitacao",

"id": "some-id",

"user_id": "some-user-id"

}

}

Entrada da aplicação

@camposmilaa

command.metadata.name # => CriarSolicitacao

Solicitacao.new(command.to_h)

class Solicitacao

def initialize(data, valor, ...)

publish_event(SolicitacaoCriada.new(data, valor, ...))

end

end

Consumo dos comandos

@camposmilaa

command.metadata.name # => CriarSolicitacao

Solicitacao.new(command.to_h)

class Solicitacao

def initialize(data, valor, ...)

publish_event(SolicitacaoCriada.new(data, valor, ...))

end

end

Consumo dos comandos

@camposmilaa

command.metadata.name # => CriarSolicitacao

Solicitacao.new(command.to_h)

class Solicitacao

def initialize(data, valor, ...)

publish_event(SolicitacaoCriada.new(data, valor, ...))

end

end

Consumo dos comandos

@camposmilaa

def publish_event(evento)

pending_events << evento

event_handlers[evento.name].call(evento)

end

def solicitacao_criada_handler(evento)

@data = evento.data

@valor = evento.valor

# ...

end

Lidando com os eventos

@camposmilaa

def publish_event(evento)

pending_events << evento

event_handlers[evento.name].call(evento)

end

def solicitacao_criada_handler(evento)

@data = evento.data

@valor = evento.valor

# ...

end

Lidando com os eventos

@camposmilaa

class SolicitacaoRepository

def save(solicitacao)

eventos = solicitacao.pending_events

eventos.each do |evento|

events_table.insert(id: solicitacao.id, event: evento.to_json)

events_producer.publish(evento)

end

ProjecaoEstadoAtual.new.save(solicitacao)

end

end

Persistência+

Event Store

Projeção

+Evento

@camposmilaa

class SolicitacaoRepository

def save(solicitacao)

eventos = solicitacao.pending_events

eventos.each do |evento|

events_table.insert(id: solicitacao.id, event: evento.to_json)

events_producer.publish(evento)

end

ProjecaoEstadoAtual.new.save(solicitacao)

end

end

Persistência+

Event Store

Projeção

+Evento

@camposmilaa

class SolicitacaoRepository

def save(solicitacao)

eventos = solicitacao.pending_events

eventos.each do |evento|

events_table.insert(id: solicitacao.id, event: evento.to_json)

events_producer.publish(evento)

end

ProjecaoEstadoAtual.new.save(solicitacao)

end

end

Persistência+

Event Store

Projeção

+Evento

@camposmilaa

class SolicitacaoRepository

def save(solicitacao)

eventos = solicitacao.pending_events

eventos.each do |evento|

events_table.insert(id: solicitacao.id, event: evento.to_json)

events_producer.publish(evento)

end

ProjecaoEstadoAtual.new.save(solicitacao)

end

end

Persistência+

Event Store

Projeção

+Evento

@camposmilaa

class SolicitacaoRepository

def save(solicitacao)

eventos = solicitacao.pending_events

eventos.each do |evento|

events_table.insert(id: solicitacao.id, event: evento.to_json)

events_producer.publish(evento)

end

ProjecaoEstadoAtual.new.save(solicitacao)

end

end

Persistência+

Event Store

Projeção

+Evento

@camposmilaa

class ProjecaoEstadoAtual

def save(solicitacao)

estado_atual.update_or_insert(

id: solicitacao.id, solicitacao: solicitacao.to_json

)

end

def find_by_id(id)

estado_atual.where(id: id)

end

end

Projeção - Estado atual

@camposmilaa

class ProjecaoEstadoAtual

def save(solicitacao)

estado_atual.update_or_insert(

id: solicitacao.id, solicitacao: solicitacao.to_json

)

end

def find_by_id(id)

estado_atual.where(id: id)

end

end

Projeção - Estado atual

@camposmilaa

Banco de dadosEvent Store

id event

1 Solicitação criada {valor: 50.000, motivo: Reforma}

Projeção - Estado Atual

id estado atual

1 {id: 1, valor: 50.000, motivo: Reforma}

@camposmilaa

Event Driven Architecture

@camposmilaa

Event Driven Architecture

Não é complicada

@camposmilaa

Event Driven Architecture

Não é complicada

Reflete a realidade

@camposmilaa

Event Driven Architecture

Não é complicada

Auditoria "de graça"

Reflete a realidade

@camposmilaa

Event Driven Architecture

Não é complicada

Auditoria "de graça"

Serviços autônomos

Reflete a realidade

@camposmilaa

Event Driven Architecture

Não é complicada

Auditoria "de graça"

Serviços autônomos

Reflete a realidade

Escalável

@camposmilaa

Não é complicada

Auditoria "de graça"

Serviços autônomos

Reflete a realidade

Escalável

Análises complexas

Event Driven Architecture

@camposmilaa

Event

Driven Architecture

@camposmilaa

Event

Driven Architecture

Assincronia

@camposmilaa

Event

Driven Architecture

Assincronia

Consistência Eventual

@camposmilaa

Event

Driven Architecture

Assincronia

Correções por eventos

Consistência Eventual

@camposmilaa

Event

Driven Architecture

Assincronia

Correções por eventos

Demanda projeções

Consistência Eventual

@camposmilaa

Event

Driven Architecture

Assincronia

Correções por eventos

Demanda projeções

Consistência Eventual

Replay tenso

@camposmilaa

Assincronia

Correções por eventos

Demanda projeções

Overengineering

Consistência Eventual

Replay tenso

Event

Driven Architecture

@camposmilaa

Não use um canhão para matar uma formiga

@camposmilaa

Agradecida!

bit.ly/camila-qcon

camposmilaa

top related