| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647 |
- using Application.Abstractions.Data;
- using Application.Helpers;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Logging;
- namespace Infrastructure.StockData;
- /// <summary>
- /// 장전 브리핑 자동 발행 배치 (D2 M3, d2 §③·§⑥) — 매 영업일 07:30 KST.
- /// 전일 지수(IndexDailyPrice)·등락 상위/하위 종목(StockDailyPrice)·주요 공시(Disclosure)를 취합해
- /// briefing 보드에 시스템 계정(MemberID=null)으로 IsNotice Post 를 발행하고 DailyBriefing 기록을 남긴다.
- /// BriefingDate 로 멱등 — 같은 날 이미 발행됐으면 skip.
- ///
- /// BackgroundJobs:DailyBriefing 플래그로 토글(기본 false), Web.Api 전용(중복 실행 방지).
- /// 조립/발행 로직은 순수 엔진(DailyBriefingComposer)에 위임 — 여기서는 스케줄만 담당한다.
- /// </summary>
- internal sealed class DailyBriefingPublisher(
- IServiceScopeFactory scopeFactory,
- ILogger<DailyBriefingPublisher> logger
- ) : DailyScheduledService(logger)
- {
- /// <summary>KST 실행 시각 — 장 시작(09:00) 전.</summary>
- private static readonly TimeOnly RunTime = new(7, 30);
- protected override string JobName => "DailyBriefing";
- protected override TimeOnly TargetTime => RunTime;
- protected override async Task<bool> RunOnceAsync(DateOnly todayKst, CancellationToken ct)
- {
- using var scope = scopeFactory.CreateScope();
- var db = scope.ServiceProvider.GetRequiredService<IAppDbContext>();
- var result = await DailyBriefingComposer.PublishAsync(db, todayKst, ct);
- if (result.AlreadyExisted)
- {
- Logger.LogInformation("[{Job}] 이미 발행됨 — skip. date={Date}, postID={PostID}", JobName, todayKst, result.PostID);
- }
- else
- {
- Logger.LogInformation("[{Job}] 발행 완료 — date={Date}, postID={PostID}", JobName, todayKst, result.PostID);
- }
- return true;
- }
- }
|