using System; using System.Threading; using System.Threading.Tasks; namespace RecruitmentBLL.Common { // Abstraction over the SignalR hub push (RecruitmentHub + its push DTOs live in // RecruitmentSL/Hubs — BLL must stay free of ASP.NET/SignalR types per CLAUDE.md's // "BLL must never reference ASP.NET types" rule, and RecruitmentBLL cannot ProjectReference // RecruitmentSL without creating a circular reference, since RecruitmentSL already // references RecruitmentBLL). Concrete implementation: RecruitmentSL/Hubs/RecruitmentHubNotifier.cs, // wrapping IHubContext. Registered in // RecruitmentSL/Program.cs. Mirrors WiBLL.Common.IWiHubNotifier / DXPBLL.Common.IDXPHubNotifier // exactly — the same pattern used repo-wide. // // Signatures here are deliberately scalar/primitive (never a RecruitmentSL.Hubs.*DTO type) — // that keeps this interface free of any dependency on the SL project; the concrete // implementation builds the actual wire-shape push DTO (ApplicationStageChangedDTO / // InterviewScheduledDTO) from these values before pushing to clients. // // Must never throw — a push failure is non-fatal to the underlying save that triggered it; // the implementation logs a warning and swallows (same contract as IWiHubNotifier's doc // comment). Callers additionally wrap the call in their own try/catch as defence in depth. public interface IRecruitmentHubNotifier { // Pushed to the "recruitment:client:{clientId}" group — a kanban board watching all // applications for the org moves the card without polling. Task NotifyApplicationStageChangedAsync( int applicationId, int jobRequisitionId, int oldSelectionProcessStageId, int newSelectionProcessStageId, int clientId, CancellationToken ct = default); // Pushed to the "recruitment:user:{interviewerId}" group — the assigned interviewer's // personal notification stream. Covers both a brand-new interview and a reschedule of // an existing one (isReschedule distinguishes the two for the client). Task NotifyInterviewScheduledAsync( int interviewId, int applicationId, int interviewerId, DateTime interviewDate, short interviewTime, short durationMinutes, bool isReschedule, CancellationToken ct = default); } }