Upload
others
View
53
Download
0
Embed Size (px)
Citation preview
@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