Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.nova.nova_server.domain.batch.common.service;

import com.nova.nova_server.domain.batch.articleingestion.service.ArticleFlowFactory;
import com.nova.nova_server.domain.batch.statistics.StatisticStepFactory;
import com.nova.nova_server.domain.batch.summary.service.SummaryStepFactory;
import com.nova.nova_server.domain.post.service.ArticleApiService;
import com.nova.nova_server.domain.post.service.ArticleApiServiceFactory;
Expand All @@ -27,6 +28,7 @@ public class BatchJobService {
private final ArticleApiServiceFactory articleApiServiceFactory;
private final ArticleFlowFactory articleFlowFactory;
private final SummaryStepFactory summaryStepFactory;
private final StatisticStepFactory statisticStepFactory;

public void runArticleIngestionBatch() {
List<ArticleApiService> articleApiServices = articleApiServiceFactory.createAllAvailableServices();
Expand All @@ -49,10 +51,14 @@ public void runSummaryBatch() {
public void runArticleIngestionAndSummaryBatch() {
List<ArticleApiService> articleApiServices = articleApiServiceFactory.createAllAvailableServices();
Flow flow = articleFlowFactory.createCombinedFlow(articleApiServices);
Step step = summaryStepFactory.createStep();
Step summaryStep = summaryStepFactory.createStep();
Step statisticsStep = statisticStepFactory.createStep();

Job job = new JobBuilder("articleIngestionAndSummaryBatch", jobRepository)
.start(flow)
.next(step)
.next(summaryStep)
// 통계 배치
.next(statisticsStep)
.build()
.build();
runBatch(job);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.nova.nova_server.domain.batch.statistics;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

import java.sql.Date;
import java.time.LocalDate;
import java.time.LocalDateTime;

@Slf4j
@Component
@RequiredArgsConstructor
public class KeywordStatisticsTasklet implements Tasklet {

private final JdbcTemplate jdbcTemplate;

@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

LocalDate targetDate = LocalDate.now().minusDays(1);
LocalDateTime startDateTime = targetDate.atStartOfDay();
LocalDateTime endDateTime = targetDate.plusDays(1).atStartOfDay();

log.info("Starting Keyword Statistics Aggregation for date: {}", targetDate);

String deleteSql = "DELETE FROM keyword_statistics WHERE stat_date = ?";
int deletedCount = jdbcTemplate.update(deleteSql, Date.valueOf(targetDate));
log.info("Deleted {} existing statistics records for date: {}", deletedCount, targetDate);

// 통계 집계 및 저장
String insertSql = """
INSERT INTO keyword_statistics (keyword_id, stat_date, mention_count, created_at, updated_at)
SELECT
keyword_id,
?,
COUNT(*),
NOW(),
NOW()
FROM card_news_keyword
WHERE created_at >= ? AND created_at < ?
GROUP BY keyword_id
""";

int insertedCount = jdbcTemplate.update(insertSql,
Date.valueOf(targetDate),
startDateTime,
endDateTime);

log.info("Inserted {} aggregated statistics records for date: {}", insertedCount, targetDate);

return RepeatStatus.FINISHED;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.nova.nova_server.domain.batch.statistics;

import lombok.RequiredArgsConstructor;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;

@Component
@RequiredArgsConstructor
public class StatisticStepFactory {

private final JobRepository jobRepository;
private final PlatformTransactionManager transactionManager;
private final KeywordStatisticsTasklet keywordStatisticsTasklet;

public Step createStep() {
return new StepBuilder("keywordStatisticsStep", jobRepository)
.tasklet(keywordStatisticsTasklet, transactionManager)
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public class TrendController implements com.nova.nova_server.domain.trend.docs.T

@GetMapping("/keywords/keywordtop")
public ApiResponse<TrendResponse> getTopKeywords() {
return ApiResponse.success(trendService.getTopKeywords(LocalDate.now()));
return ApiResponse.success(trendService.getTopKeywords(LocalDate.now().minusDays(1)));
}

@GetMapping("/interests/skilltop")
Expand Down