package com.thinkbiganalytics.metadata.jpa.feed; /*- * #%L * thinkbig-operational-metadata-jpa * %% * Copyright (C) 2017 ThinkBig Analytics * %% * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * #L% */ import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; import com.thinkbiganalytics.DateTimeUtil; import com.thinkbiganalytics.metadata.api.feed.*; import com.thinkbiganalytics.metadata.api.jobrepo.job.BatchJobExecution; import com.thinkbiganalytics.metadata.api.jobrepo.job.BatchJobExecutionProvider; import com.thinkbiganalytics.metadata.api.jobrepo.job.JobStatusCount; import com.thinkbiganalytics.metadata.jpa.jobrepo.job.JpaBatchJobExecutionStatusCounts; import com.thinkbiganalytics.metadata.jpa.jobrepo.job.QJpaBatchJobExecution; import com.thinkbiganalytics.metadata.jpa.jobrepo.job.QJpaBatchJobInstance; import com.thinkbiganalytics.metadata.jpa.support.GenericQueryDslFilter; import com.thinkbiganalytics.security.AccessController; import com.thinkbiganalytics.support.FeedNameUtil; import org.joda.time.DateTime; import org.joda.time.ReadablePeriod; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.inject.Inject; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** * Provider allowing access to feeds {@link OpsManagerFeed} */ @Service public class OpsFeedManagerFeedProvider implements OpsManagerFeedProvider { private static final Logger log = LoggerFactory.getLogger(OpsFeedManagerFeedProvider.class); @Inject BatchJobExecutionProvider batchJobExecutionProvider; private OpsManagerFeedRepository repository; private FeedHealthRepository feedHealthRepository; private LatestFeedJobExectionRepository latestFeedJobExectionRepository; private BatchFeedSummaryCountsRepository batchFeedSummaryCountsRepository; @Autowired private JPAQueryFactory factory; @Inject private AccessController controller; /** * list of delete feed listeners **/ private List<DeleteFeedListener> deleteFeedListeners = new ArrayList<>(); @Autowired public OpsFeedManagerFeedProvider(OpsManagerFeedRepository repository, BatchFeedSummaryCountsRepository batchFeedSummaryCountsRepository, FeedHealthRepository feedHealthRepository, LatestFeedJobExectionRepository latestFeedJobExectionRepository) { this.repository = repository; this.batchFeedSummaryCountsRepository = batchFeedSummaryCountsRepository; this.feedHealthRepository = feedHealthRepository; this.latestFeedJobExectionRepository = latestFeedJobExectionRepository; } @Override public OpsManagerFeed.ID resolveId(Serializable id) { if (id instanceof OpsManagerFeedId) { return (OpsManagerFeedId) id; } else { return new OpsManagerFeedId(id); } } @Override public OpsManagerFeed findByName(String name) { return repository.findByName(name); } public OpsManagerFeed findById(OpsManagerFeed.ID id) { return repository.findOne(id); } public List<? extends OpsManagerFeed> findByFeedIds(List<OpsManagerFeed.ID> ids) { if (ids != null && !ids.isEmpty()) { return repository.findByFeedIds(ids); } return null; } public void save(List<? extends OpsManagerFeed> feeds) { repository.save((List<JpaOpsManagerFeed>) feeds); } @Override public OpsManagerFeed save(OpsManagerFeed.ID feedManagerId, String systemName) { OpsManagerFeed feed = findById(feedManagerId); if (feed == null) { feed = new JpaOpsManagerFeed(); ((JpaOpsManagerFeed) feed).setName(systemName); ((JpaOpsManagerFeed) feed).setId((OpsManagerFeedId) feedManagerId); repository.save((JpaOpsManagerFeed) feed); } return feed; } @Override public void delete(OpsManagerFeed.ID id) { OpsManagerFeed feed = findById(id); if (feed != null) { log.info("Deleting feed {} ({}) and all job executions. ", feed.getName(), feed.getId()); //first delete all jobs for this feed deleteFeedJobs(FeedNameUtil.category(feed.getName()), FeedNameUtil.feed(feed.getName())); repository.delete(feed.getId()); //notify the listeners notifyOnFeedDeleted(feed); log.info("Successfully deleted the feed {} ({}) and all job executions. ", feed.getName(), feed.getId()); } } public boolean isFeedRunning(OpsManagerFeed.ID id) { OpsManagerFeed feed = findById(id); if (feed != null) { return batchJobExecutionProvider.isFeedRunning(feed.getName()); } return false; } public List<OpsManagerFeed> findAll(String filter) { QJpaOpsManagerFeed feed = QJpaOpsManagerFeed.jpaOpsManagerFeed; return Lists.newArrayList(repository.findAll(GenericQueryDslFilter.buildFilter(feed, filter))); } public List<String> getFeedNames() { return repository.getFeedNames(); } public List<? extends FeedHealth> getFeedHealth() { return feedHealthRepository.findAll(); } private List<? extends FeedHealth> findFeedHealth(String feedName) { return feedHealthRepository.findByFeedName(feedName); } public FeedHealth getFeedHealth(String feedName) { List<? extends FeedHealth> feedHealthList = findFeedHealth(feedName); if (feedHealthList != null && !feedHealthList.isEmpty()) { return feedHealthList.get(0); } else { return null; } } public List<? extends LatestFeedJobExecution> findLatestCheckDataJobs() { return latestFeedJobExectionRepository.findCheckDataJobs(); } public List<JobStatusCount> getJobStatusCountByDateFromNow(String feedName, ReadablePeriod period) { QJpaBatchJobExecution jobExecution = QJpaBatchJobExecution.jpaBatchJobExecution; QJpaBatchJobInstance jobInstance = QJpaBatchJobInstance.jpaBatchJobInstance; QJpaOpsManagerFeed feed = QJpaOpsManagerFeed.jpaOpsManagerFeed; List<BatchJobExecution.JobStatus> runningStatus = ImmutableList.of(BatchJobExecution.JobStatus.STARTED, BatchJobExecution.JobStatus.STARTING); com.querydsl.core.types.dsl.StringExpression jobState = new CaseBuilder().when(jobExecution.status.eq(BatchJobExecution.JobStatus.FAILED)).then("FAILED") .when(jobExecution.status.in(runningStatus)).then("RUNNING") .otherwise(jobExecution.status.stringValue()); JPAQuery query = factory.select( Projections.constructor(JpaBatchJobExecutionStatusCounts.class, jobState.as("status"), Expressions.constant(feedName), jobExecution.startYear, jobExecution.startMonth, jobExecution.startDay, jobExecution.count().as("count"))) .from(jobExecution) .innerJoin(jobInstance).on(jobExecution.jobInstance.jobInstanceId.eq(jobInstance.jobInstanceId)) .innerJoin(feed).on(jobInstance.feed.id.eq(feed.id)) .where(jobExecution.startTime.goe(DateTime.now().minus(period)) .and(feed.name.eq(feedName)) .and(FeedAclIndexQueryAugmentor.generateExistsExpression(feed.id, controller.isEntityAccessControlled()))) .groupBy(jobExecution.status, jobExecution.startYear, jobExecution.startMonth, jobExecution.startDay); return (List<JobStatusCount>) query.fetch(); } /** * This will call the stored procedure delete_feed_jobs and remove all data, jobs, steps for the feed. */ public void deleteFeedJobs(String category, String feed) { repository.deleteFeedJobs(category, feed); } /** * This will call the stored procedure abandon_feed_jobs */ public void abandonFeedJobs(String feed) { String exitMessage = String.format("Job manually abandoned @ %s", DateTimeUtil.getNowFormattedWithTimeZone()); repository.abandonFeedJobs(feed, exitMessage); } /** * Subscribe to feed deletion events * * @param listener a delete feed listener */ public void subscribeFeedDeletion(DeleteFeedListener listener) { deleteFeedListeners.add(listener); } public void notifyOnFeedDeleted(OpsManagerFeed feed) { deleteFeedListeners.stream().forEach(listener -> listener.onFeedDelete(feed)); } }