Decisão técnica - melhor abordagem para uma rota http que cria um cliente.

Definição de Padrões no Projeto

Me ajudem a tomar uma decisão, meu banco de dados está diagramado assim:

tabela de customers ---- > id name cpf

tabela de emails ---- > email table table_id

ou seja, a tabela de email é morfológica, assim como a de addresses e phones uso o knex para fazer as querys

Caso de uso: Cadastro de Cliente

Quando houver a necessidade de criar um cliente no banco de dados, mas alguns dos dados fornecidos pelo front-end não estejam presentes na tabela "customers", como por exemplo, emails, phones, addresses... precisamos decidir entre:

  1. Fazer uma transação no Knex, incluindo todos os dados em todas as tabelas. Se algo der errado, faremos um rollback, ou seja, chamaremos apenas um método do repositório no serviço.

  2. Criar apenas o registro do cliente e utilizar o padrão Observer para criar os outros registros, como se fosse um efeito dominó.


Comentário: Uma observação importante em relação à opção 2 é que a requisição HTTP ficará aguardando o Observer criar os registros de email, phone e addresses antes de retornar "true". Isso pode resultar em um tempo de resposta mais longo para o cliente, pois depende da eficiência do processo de criação desses registros adicionais.

outra questão, o observer não deve ser assincrono? tipo enviar um email, enviar um whatsapp para o cliente desejando boas vindas, não é certo esperar o observador executar algo para dar um resposta na req http, certo ?

Desculpe, mas pra que você usaria um Observer para gravar os dados ? Qual a vantagem ?

dev iniciante. alguma neura com algo como. o meu repositorio de companies so pode inserir dados na tabela companies. faz sentido isso ? pelo pouco que eu estudei desse design Pattern por enquanto ele me parece fazer sentido em situações estilo ' efeito dominó ' eu cadastrei uma company eu preciso apos isso inserir dados acessorias como endereços, telefones e emails.
Entendi sua lógica. Não é esse o caso. O objetivo do observer não é cascatear (efeito em cascata/dominó) eventos mas permitir a objetos "interessados" em alguma ocorrencia ficarem cientes quando algo acontecer. Isso ajuda a isolar as responsabilidades e desacoplar os objetos. No seu caso a solução é a transação. Caso contrário você corre o risco de ter inconsistências na sua base de dados.
auditar uma acao de um usuário é uma exemplo de caso de uso do observer?(no meu caso efetivamente um registro na tabela de auditorias) ou tbm deve ser feito enquanto a requisição http estiver aberta ? outro exemplo. cadastrei um cliente e quero enviar um whats/email de boas vindas. esse faz sentido ne ?
Olá. Desculpe a demora na resposta. Sim, pode ser usado o observer, mas isso também pode ser resolvido apenas com a emissão de eventos de dominio pelos seus objetos. É uma solução mais simples, desacopla os objetos envolvidos e ainda mantém a semantica do domínio. Imagino que seu cadastro de cliente aconteça dentro de um objeto de serviço. Esse objeto pode emitir eventos como CadastroEfetuado, CadastroCancelado, CadastroRemovido, CadastroAtualizado dependendo da ação executada. O payload desse evento pode ser o cliente e a data/hora que o evento ocorreu.

Primeiro, só tu tens o contexto completo pra tomar uma decisão dessas.

Dito isso...

Como avisaste que estás usando knex, já assumo que estás usando js/ts. Dessa forma, posso presumir que estavas falando sobre "Observables" do RxJS, quando falaste de "observers".

Dado esse micro contexto, eu optaria por fazer uma transaction pelo knex, simplesmente pelo princípio KISS (keep it simple, stupid). Os observables do rxjs são bons pra problemas onde é preciso se aplicar filas, buffers e/ou pipelines. Pra essa situação, onde é preciso esperar que todas as informações sejam inseridas no banco de dados antes de dar uma mensagem de sucesso ou erro, o bom é velho beginTransaction -> inserts -> commit (ou rollback, em caso de erro) é a melhor solução.

Espero ter ajudado 😁

n sei o que é rxjs. me referia ao desing pattern mesmo. pelo que entendi pode ser implementado de algumas maneiras. obrigado pela resposta. ajudou. no final foi decidido que cada tabela tem seu repositorio. ai chama cada repo necessario para criar uma entidade no serviço. o que achou disso? eu to so tentando entender novas perspectivas pq sou dev iniciante e to meio isolado no meu contexto. Não quero ficar limitado a ter sempre a mesma cabeca e so conseguir enxergar uma solução p tudo.