Ciclo de vida do aplicativo
Neste guia, aprenderemos como o AdonisJS inicializa seu aplicativo e quais ganchos de ciclo de vida você pode usar para alterar o estado do aplicativo antes que ele seja considerado pronto.
O ciclo de vida de um aplicativo depende do ambiente em que ele está sendo executado. Por exemplo, um processo de longa duração iniciado para atender a solicitações HTTP é gerenciado de forma diferente de um comando ace de curta duração.
Então, vamos entender o ciclo de vida do aplicativo para cada ambiente suportado.
Como um aplicativo AdonisJS é iniciado
Um aplicativo AdonisJS tem vários pontos de entrada, e cada ponto de entrada inicializa o aplicativo em um ambiente específico. Os seguintes arquivos de ponto de entrada são armazenados dentro do diretório bin
.
- O ponto de entrada
bin/server.ts
inicializa o aplicativo AdonisJS para manipular solicitações HTTP. Quando você executa o comandonode ace serve
, nos bastidores, executamos esse arquivo como um processo filho. - Ace nos bastidores.
- O ponto de entrada
bin/test.ts
inicializa o aplicativo AdonisJS para executar testes usando Japa.
Se você abrir qualquer um desses arquivos, nos verá usando o módulo Ignitor para conectar as coisas e, em seguida, iniciar o aplicativo.
O módulo Ignitor encapsula a lógica de iniciar um aplicativo AdonisJS. Nos bastidores, ele executa as seguintes ações.
- Classe Application.
- Iniciar/inicializar o aplicativo.
- Executar a ação principal para iniciar o aplicativo. Por exemplo, no caso de um servidor HTTP, a ação
main
envolve iniciar o servidor HTTP. Enquanto isso, no caso de testes, a açãomain
envolve executar os testes.
A base de código do Ignitor é relativamente simples, então navegue pelo código-fonte para entendê-lo melhor.
A fase de inicialização
A fase de inicialização permanece a mesma para todos os ambientes, exceto o ambiente console
. No ambiente console
, o comando executado decide se deve inicializar o aplicativo.
Você só pode usar as ligações e serviços do contêiner depois que o aplicativo for inicializado.
A fase de inicialização
A fase de inicialização varia entre todos os ambientes. Além disso, o fluxo de execução é dividido nas seguintes subfases
A fase
pré-inicialização
se refere às ações realizadas antes de iniciar o aplicativo.A fase
post-start
se refere às ações realizadas após iniciar o aplicativo. No caso de um servidor HTTP, as ações serão executadas após o servidor HTTP estar pronto para aceitar novas conexões.
Durante o ambiente da web
No ambiente da web, uma conexão HTTP de longa duração é criada para escutar solicitações de entrada, e o aplicativo permanece no estado ready
até que o servidor falhe ou o processo receba um sinal para desligar.
Durante o ambiente de teste
As ações pre-start e post-start são executadas no ambiente de teste. Depois disso, importamos os arquivos de teste e executamos os testes.
Durante o ambiente do console
No ambiente console
, o comando executado decide se deve iniciar o aplicativo.
Um comando pode iniciar o aplicativo habilitando o sinalizador options.startApp
. Como resultado, as ações pré-início e pós-início serão executadas antes do método run
do comando.
import { BaseCommand } from '@adonisjs/core/ace'
export default class GreetCommand extends BaseCommand {
static options = {
startApp: true
}
async run() {
console.log(this.app.isReady) // true
}
}
A fase de encerramento
O encerramento do aplicativo varia muito entre processos de curta e longa duração.
Um comando de curta duração ou o processo de teste inicia o encerramento após o término da operação principal.
Um processo de servidor HTTP de longa duração aguarda sinais de saída como SIGTERM
para iniciar o processo de encerramento.
Respondendo a sinais de processo
Em todos os ambientes, iniciamos um processo de encerramento normal quando o aplicativo recebe um sinal SIGTERM
. Se você iniciou seu aplicativo usando pm2, o encerramento normal ocorrerá após receber o evento SIGINT
.
Durante o ambiente da web
No ambiente da web, o aplicativo continua em execução até que o servidor HTTP subjacente trave com um erro. Nesse caso, iniciamos o encerramento do aplicativo.
Durante o ambiente de teste
O encerramento normal começa depois que todos os testes foram executados.
Durante o ambiente de console
No ambiente console
, o encerramento do aplicativo depende do comando executado.
O aplicativo será encerrado assim que o comando for executado, a menos que o sinalizador options.staysAlive
esteja habilitado e, neste caso, o comando deve encerrar explicitamente o aplicativo.
import { BaseCommand } from '@adonisjs/core/ace'
export default class GreetCommand extends BaseCommand {
static options = {
startApp: true,
staysAlive: true,
}
async run() {
await runSomeProcess()
// Termina o processo
await this.terminate()
}
}
Ganchos do ciclo de vida
Os ganchos do ciclo de vida permitem que você se conecte ao processo de bootstrap do aplicativo e execute ações conforme o aplicativo passa por diferentes estados.
Você pode ouvir ganchos usando as classes do provedor de serviços ou defini-los em linha na classe do aplicativo.
Retornos de chamada em linha
Você deve registrar ganchos do ciclo de vida assim que uma instância do aplicativo for criada.
Os arquivos de ponto de entrada bin/server.ts
, bin/console.ts
e bin/test.ts
criam uma nova instância de aplicativo para diferentes ambientes, e você pode registrar retornos de chamada em linha nesses arquivos.
const app = new Application(new URL('../', import.meta.url))
new Ignitor(APP_ROOT, { importer: IMPORTER })
.tap((app) => {
app.booted(() => {
console.log('invoked after the app is booted')
})
app.ready(() => {
console.log('invoked after the app is ready')
})
app.terminating(() => {
console.log('invoked before the termination starts')
})
})
initiating
: As ações de hook são chamadas antes que o aplicativo passe para o estado iniciado. O arquivoadonisrc.ts
é analisado após a execução dos hooksinitiating
.booting
: As ações de hook são chamadas antes da inicialização do aplicativo. Os arquivos de configuração são importados após a execução dos hooksbooting
.booted
: As ações de hook são invocadas após todos os provedores de serviço terem sido registrados e inicializados.starting
: As ações de hook são invocadas antes da importação dos arquivos de pré-carregamento.ready
: As ações de hook são invocadas após o aplicativo estar pronto.terminating
: As ações de hook são invocadas quando o processo de saída normal começa. Por exemplo, este hook pode fechar conexões de banco de dados ou encerrar fluxos abertos.
Usando provedores de serviço
Os provedores de serviço definem os hooks do ciclo de vida como métodos na classe do provedor. Recomendamos usar provedores de serviço em vez de retornos de chamada em linha, pois eles mantêm tudo bem organizado.
A seguir está a lista de métodos de ciclo de vida disponíveis.
import { ApplicationService } from '@adonisjs/core/types'
export default class AppProvider {
constructor(protected app: ApplicationService) {}
register() {
}
async boot() {
}
async start() {
}
async ready() {
}
async shutdown() {
}
}
register
: O método register registra ligações dentro do contêiner. Este método é síncrono por design.boot
: O método boot é usado para inicializar ou inicializar as ligações que você registrou dentro do contêiner.start
: O método start é executado logo antes do métodoready
. Ele permite que você execute ações que as ações do hookready
podem precisar.ready
: O método ready é executado após o aplicativo ser considerado pronto.shutdown
: O método shutdown é invocado quando o aplicativo inicia o desligamento normal. Você pode usar esse método para fechar conexões de banco de dados ou encerrar fluxos abertos.