{"id":50482792,"url":"https://github.com/diegomaiasantos/dotnet-engineering-challenge","last_synced_at":"2026-06-01T19:00:59.802Z","repository":{"id":350954517,"uuid":"1208912667","full_name":"DiegoMaiaSantos/dotnet-engineering-challenge","owner":"DiegoMaiaSantos","description":"Desafio técnico .NET com tratamento de duplicidade, retry e concorrência em processamento de pagamentos.","archived":false,"fork":false,"pushed_at":"2026-04-12T23:01:42.000Z","size":4,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-13T01:07:16.483Z","etag":null,"topics":["challenge","csharp","dotnet"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DiegoMaiaSantos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-12T22:44:59.000Z","updated_at":"2026-04-12T23:01:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/DiegoMaiaSantos/dotnet-engineering-challenge","commit_stats":null,"previous_names":["diegomaiasantos/dotnet-engineering-challenge"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/DiegoMaiaSantos/dotnet-engineering-challenge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiegoMaiaSantos%2Fdotnet-engineering-challenge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiegoMaiaSantos%2Fdotnet-engineering-challenge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiegoMaiaSantos%2Fdotnet-engineering-challenge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiegoMaiaSantos%2Fdotnet-engineering-challenge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DiegoMaiaSantos","download_url":"https://codeload.github.com/DiegoMaiaSantos/dotnet-engineering-challenge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DiegoMaiaSantos%2Fdotnet-engineering-challenge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33789013,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["challenge","csharp","dotnet"],"created_at":"2026-06-01T19:00:56.842Z","updated_at":"2026-06-01T19:00:59.790Z","avatar_url":"https://github.com/DiegoMaiaSantos.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Desafio Técnico – Processamento de Pagamentos\n\n## ❌ O que estava errado no código original\n\nA implementação original apresentava alguns problemas importantes:\n\n- **Processamento de eventos duplicados:** o mesmo `Id` poderia ser processado mais de uma vez.\n- **Ausência de retry:** em caso de falha no método `Pagar`, o pagamento era ignorado sem nova tentativa.\n- **Exceções ignoradas:** o bloco `catch` estava vazio, ocultando falhas e dificultando o diagnóstico.\n- **Falta de retorno estruturado:** não havia forma de identificar quais pagamentos falharam.\n\n---\n\n## ✅ O que foi alterado e por quê\n\n- **Controle de duplicidade:**  \n  Foi utilizado `ConcurrentDictionary` para garantir que cada `Id` seja processado apenas uma vez, inclusive em cenário concorrente.\n\n- **Implementação de retry:**  \n  Cada pagamento é tentado até 3 vezes antes de ser considerado falha, tratando possíveis instabilidades do serviço externo.\n\n- **Processamento simultâneo (diferencial):**  \n  Foi utilizado `Parallel.ForEach` para processar múltiplos pagamentos em paralelo.\n\n- **Thread safety:**  \n  - `ConcurrentDictionary` para controle de IDs  \n  - `ConcurrentBag` para armazenar falhas  \n  - `lock` para proteger a soma do total (tipo `decimal` não é thread-safe)\n\n- **Retorno estruturado:**  \n  Foi criado um objeto de resultado contendo o total processado e a lista de falhas, permitindo melhor controle e visibilidade.\n\n---\n\n## 📊 Decisões de implementação\n\n### 🔎 Forma de reportar falhas\n\nOptei por **retornar os pagamentos que falharam** dentro do objeto de resultado, ao invés de utilizar apenas logs ou lançar exceções.\n\n**Motivos da escolha:**\n\n- Permite que o processamento continue mesmo com falhas pontuais  \n- Preserva o valor total processado com sucesso  \n- Dá visibilidade completa das falhas ao consumidor do método  \n- Mantém a solução mais flexível, permitindo que a camada superior decida como tratar os erros  \n\n---\n\n### 🧱 Criação de classes e estrutura\n\nForam criados os seguintes objetos auxiliares:\n\n- `ResultadoProcessamento`: encapsula o total processado e a lista de falhas  \n- `PagamentoFalhou`: representa um pagamento que não foi processado após todas as tentativas  \n\n**Motivo:**\n\nMelhorar a organização, legibilidade e clareza da resposta do método, evitando retornos simples que não representam todo o estado do processamento.\n\n---\n\n### ⚙️ Versão do .NET\n\nO projeto original estava configurado para **.NET 10**.\n\nPara execução no ambiente disponível, a solução foi adaptada para **.NET 8**, mantendo total compatibilidade com a lógica implementada e sem impacto no comportamento esperado.\n\n---\n\n## 🚀 O que faria a mais se tivesse mais tempo\n\n- Implementação de testes automatizados cobrindo cenários de sucesso, retry e falha definitiva\n- Adição de logging estruturado para rastreamento de erros\n- Separação do serviço de pagamento via interface para facilitar testes\n- Configuração externa do número de tentativas (retry)\n- Criação de versões separadas para processamento sequencial e paralelo","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiegomaiasantos%2Fdotnet-engineering-challenge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdiegomaiasantos%2Fdotnet-engineering-challenge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdiegomaiasantos%2Fdotnet-engineering-challenge/lists"}