Executando verificação de segurança...
3

Vou primeiro passar pelas soluções que vc mesmo propôs:

  1. criar um state para cada requisição que vai morrer no fim dela: a única parte "horrível" que consigo ver aqui é o desempenho que seria impactado significativamente por ter de criar e carregar o lua state a cada requisição. Algo que pode aliviar isso seria manter um pool de estados em branco pré-criados que só são consumidos quando há requisições. Este pool poderia ser preenchido constantemente em uma thread separada, isso aliviaria mais ainda o problema de desempenho e acredito que não teria problemas com threads, uma vez que ele nunca é usado simultaneamente em dois threads diferentes.

  2. outra solução é manter um pool de estados: Bem eu devia ter lido esse antes de escrever meu ponto acima :) Mas acho que a diferença é que vc não precisa separar por threads. Não importa em qual thread o lua state é criado, mesmo que seja utilizado em outro thread. Isso não acarreta em problemas de multithreading pois ele nunca é usado ao mesmo tempo em dois threads. Quanto à solução opensource que utilize essa abordagem: também não sei dizer.

  3. por último, bolar um event loop para tornar o call de cada script assíncrona: não conheço a linguagem Rust pra poder afirmar, mas imagino que vc teria que implementar todo o core de event loop e async em todos lugares que fazem I/O. Me parece extremamente complexo. Eu sei que existe o Tokio (https://tokio.rs/) para Rust, mas como nunca usei não posso dizer muito; talvez ele te ajude aqui, mas talvez vc precisaria re-implementar toda biblioteca de I/O do Lua, pra que leve em conta o assincronismo e isso me parece um trabalho absurdamente gigante!

Agora deixa eu questionar a primeira solução que vc deu e que eu complementei. Por que o state precisa morrer ao final da requisição? Não poderia ele ser long-lived, isto é, servir várias requisições no decorrer da vida dele, sem que precise morrer e ser re-criado a cada requisição? Isso é um requisito que vc tem que definir, mas estou só questionando o porquê dele. Se vc quer garantir absolutamente que não haverá estado compartilhado entre uma requisição e outra, então faz sentido. Mas talvez também faça sentido assumir que o programa Lua que rodar não vá alterar o estado -- é que claro que daí cabe ao programa respeitar isso; a garantia não é tão grande quanto re-criar o estado todas as vezes. Aí vc quem decide, já que o requisito é vc quem está dando.

Se não estou enganado, os servidores que rodam através de Fork (e.g. Apache) funcionam assim: eles sempre rodam a aplicação dentro de um fork, uma vez. Portanto, quando o processo forkado termina, o estado é eliminado. Semelhante ao seu requisito, mas usando CoW (copy-on-write) do próprio OS+hardware pra fazer o equivalente que vc faria de criar o lua state toda vez. Vc também poderia fazer desta forma!

Já outros servidores, tipo o puma do Ruby (falo dele pois conheço relativamente bem), compartilham o estado entre requisições mesmo e deixam para a aplicação a resposabilidade de não mexer no estado compartilhado. Mais suscetível à bugs, porém é comum rodar sistemas em produção dessa forma.

Carregando publicação patrocinada...
1

Foi bem elucidativo, obrigado. O requisito do estado morrer ao fim de cada requisição é pelo próprio Rust não permitir o compartilhamento do state entre threads. Apesar de que ainda não testei algumas ideias que podem resolver isso.

Para criar uma solução assíncrona realmente pensei no Tokio, até por que ele já é a base do servidor web. Vou dar uma olhada para ver o quão tranquilo seria implementar isso.

Vou manter em mente a solução de consumir a pool. No caso de não conseguir algo mais eficiente já é um bom começo, bem melhor que criar um por conexão.

Muito obrigado por comentar.