Artigo
· 5 hr atrás 2min de leitura

Arquivos temporários e singletons: limpem o que vocês gerarem.

Há um padrão com o qual já me deparei várias vezes em que preciso usar um arquivo ou pasta temporária e que ela seja limpa em algum momento mais tarde.

O natural aqui é seguir os padrões de "Robust Error Handling and Cleanup in ObjectScript" , usando um try/catch/pseudo-finally ou um objeto registrado para gerenciar a limpeza no destrutor. %Stream.File* também tem a propriedade RemoveOnClose, que vocês podem ativar… mas usem com cuidado, pois podem acabar excluindo acidentalmente um arquivo importante. Além disso, esse indicador é redefinido ao chamar %Save(), então será necessário configurá-lo novamente como 1 depois disso.

Mas existe um caso complicado: imaginem que vocês precisam que o arquivo temporário sobreviva em um nível superior da pilha. Por exemplo:

ClassMethod MethodA()
{
    Do ..MethodB(.filename)
    // Do something else with the filename
}

ClassMethod MethodB(Output filename)
{
    // Create a temp file and set filename to the file's name
    Set filename = ##class(%Library.File).TempFilename()
    
    //... and probably do some other stuff
}

Vocês sempre poderiam passar objetos %Stream.File* com RemoveOnClose definido como 1, mas aqui estamos falando, na verdade, apenas de arquivos temporários.

É aí que entra o conceito de “Singleton”. No IPM , temos uma implementação base em %IPM.General.Singleton que vocês podem estender para cobrir diferentes casos de uso. O comportamento geral e o padrão de uso são:

  • Em um nível superior da pilha, vocês chamam %Get() nessa classe e obtêm a instância única, que também ficará acessível por meio de chamadas a %Get() em níveis inferiores.
  • Quando o objeto sai de escopo no nível mais alto da pilha que o utiliza, o código de limpeza é executado.
  • Isso é um pouco melhor do que usar uma variável %, porque vocês não precisam verificar se ela está definida e, além disso, ela sobrevive a NEW sem argumentos nos níveis inferiores da pilha, graças a uma certa “magia” profunda do sistema de objetos.

Passando para os arquivos temporários, o IPM também possui um singleton gerenciador de arquivos temporários . Aplicando isso a este problema, a solução é:

ClassMethod MethodA()
{
    Set tempFileManager = ##class(%IPM.Utils.TempFileManager).%Get()
    Do ..MethodB(.filename)
    // Do something else with the filename
    // The temp file is cleaned up automatically when tempFileManager goes out of scope
}

ClassMethod MethodB(Output filename)
{
    Set tempFileManager = ##class(%IPM.Utils.TempFileManager).%Get()
    // Create a temp file and set filename to the file's name
    Set filename = tempFileManager.GetTempFileName(".md")
    
    //... and probably do some other stuff
}
Discussão (0)1
Entre ou crie uma conta para continuar