Uma boa ferramenta é meio mestre.
Dizia meu pai em relação à qualidade das ferramentas escolhidas para um determinado trabalho. Lembro-me de várias vezes em que estava a fazer algo na garagem ou no quintal com uma ferramenta que não era a mais apropriada para o trabalho e vir o meu pai com uma de melhor qualidade, ou mais apropriada para o ofício em questão, e explicar-me o porquê da escolha arrematando no fim: “Uma boa ferramenta é meio mestre”. Que é como quem diz, a ferramenta certa e de qualidade faz metade do trabalho sozinha. Vem isto a propósito de um bug, daqueles memoráveis, com que tive de lidar numa aplicação web, provocado em parte pela escolha desadequada da ferramenta.
Para contextualizar, a tecnologia em questão era OutSystems e na nossa aplicação havia uma integração com um sistema externo onde deveriamos receber notificações desse sistema e processar a informação num processo que fazia uma série de chamadas a outros sistemas externos de modo a complementar a informação original, que depois de consolidada era armazenada na base de dados local (da aplicação em OutSystems). Na implementação original (feita por outra equipa) a ferramenta escolhida para o propósito foi um Process (ou BPT - Business Process Technology), um processo automático que corria quando a notificação era recebida do sistema externo. A informação chegava através na API exposta, era guardada assincronamente na base de dados e ao gravar era despoletado o BPT que iria processar a informação, chamar outros sistemas externos e criar ou atualizar registos noutras tabelas. Para o utilizador este processo acontecia em poucos minutos desde o momento em que era lançada a notificação no sistema externo.
Em teoria tudo era perfeito. No entanto, de vez em quando as notificações chegavam ao nosso lado e não eram processadas. A informação não era complementada e atualizada nas tabelas esperadas. Uma característica dos BPT’s é a possibilidade de lançar várias instâncias do processo em simultâneo (processamento paralelo com várias threads) e depois de muitas horas a “bater com a cabeça” descobrimos que o erro apenas acontecia quando o sistema externo enviava várias notificações em simultâneo (com diferença de milissegundos entre eventos) correspondentes a uma mesma entidade. Era um problema de acessos concorrentes à base de dados. Uma parte do BPT criava ou atualizava um registo com base num código único que vinha na informação do sistema externo. Se existisse um registo com esse código, então era atualizado, caso contrário seria criado. A tabela tinha uma restrição de unicidade e esse código nunca poderia ser repetido. Na prática, quando recebíamos vários eventos em simultâneo com o mesmo código, eram lançados vários BPT’s (ou seja, várias threads) e quando chegavam ao momento de validar se o registo existia, todas verificavam que não e iam tentar criar o registo, a primeira thread tinha sucesso na criação do registo e as restantes recebiam uma exceção da base de dados devido à violação do índice único. Conclusão, a exceção interrompia o fluxo das restantes threads e a consolidação e atualização de dados não acontecia.
A solução era óbvia, mudar o mecanismo de processamento paralelo para um mecanismo de processamento em série, criar uma queue. Em OutSystems isto pode ser alcançado com o uso de um Timer (um scheduled job). No entanto, por diversos motivos já não nos foi possível a refactorização necessária. A solução? Dessincronizar as várias instâncias dos BPT’s gerando um número aleatório que depois era usado para atrasar a thread em X milissegundos. No mínimo deselegante, mas esta resolução deu origem a muitas gargalhadas e fez-me lembrar o velho e sábio conselho do meu pai: “Uma boa ferramenta é meio mestre”. E saber escolher a ferramenta certa para o trabalho é meia arte, diria eu.
Notícias Recentes
Das pessoas às máquinas: de psicólogo a programador em três meses.
Hoje o resultado é notório, quatro anos como software developer, vários projetos em clientes e áreas distintas, várias tecnologias diferentes (desde C e C++ a OutSystems) e uma satisfação profissional que jamais imaginava alcançar no dia em que fiz a candidatura ao bootcamp da <Academia de Código_>. E claro, fazer parte deste projeto incrível que é a team.it é até agora o ponto mais alto desde ain