Eventos de Domínio e Jobs Agendados
Como o status do candidato reage automaticamente às mudanças de candidatura, e a rotina diária de vagas.
Eventos de domínio (application)
Cada transição de estado de ApplicationEntity (ver Recrutamento) publica um
evento (ApplicationCreatedEvent, ApplicationHiredEvent, ApplicationRejectedEvent,
ApplicationWithdrawnEvent), consumido por um listener próprio
(ApplicationEventListener<T> do Micronaut) em
application/application/listener/. É assim que o status do candidato fica sincronizado com o
andamento das candidaturas sem o service de Application precisar conhecer as regras de Candidate.
| Evento | Listener | O que faz |
|---|---|---|
ApplicationCreatedEvent | ApplicationCreatedEventListener | Se o candidato está AVAILABLE, muda pra IN_PROCESS |
ApplicationHiredEvent | ApplicationHiredEventListener | Marca o candidato como ALLOCATED, marca a vaga como FILLED, e rejeita automaticamente todas as outras candidaturas ativas daquela vaga (cada rejeição recalcula o status dos outros candidatos) |
ApplicationRejectedEvent | ApplicationRejectedEventListener | Se o candidato não tem mais nenhuma candidatura ativa, volta pra AVAILABLE |
ApplicationWithdrawnEvent | ApplicationWithdrawnEventListener | Mesma lógica do rejeitado — recalcula o status do candidato |
O "recalcular status" em comum usa applicationRepository.existsActiveApplicationForCandidate(id) — uma
query dedicada, sem carregar a coleção inteira de candidaturas em memória.
Efeito colateral importante: contratar um candidato numa vaga (hire()) rejeita silenciosamente todos
os outros candidatos em processo naquela mesma vaga — não é preciso rejeitar manualmente cada um.
Job agendado: fechamento por atraso (vacancy)
VacancySchedule (vacancy/application/service/VacancySchedule.java) roda todo dia à meia-noite
(@Scheduled(cron = "0 0 0 * * *")):
@Scheduled(cron = "0 0 0 * * *")
@Transactional("default")
public void markVacanciesAsBehindSchedule() {
List<VacancyEntity> openVacancies = vacancyRepository.findAllByStatusAndDeletedAtIsNull(VacancyStatusEnum.OPEN);
openVacancies.forEach(vacancy -> vacancy.markAsBehindSchedule(LocalDate.now()));
}Ele varre todas as vagas OPEN e chama markAsBehindSchedule() — que só efetivamente muda o status se a
startDate estiver a ≤3 dias (ver a máquina de estados em Recrutamento). É a
única tarefa agendada do sistema hoje.