Commit 5db76afe authored by shishir suman's avatar shishir suman
Browse files

fixes to creating scheduler to escalate tickets

Showing with 120 additions and 10 deletions
+120 -10
......@@ -61,6 +61,9 @@ public class Ticket {
@Column(name = "is_escalated")
private boolean escalated;
@Column(name = "is_escalated_to_admin")
private boolean escalatedToAdmin;
@Column(name = "escalated_date")
private Timestamp escalatedDate;
......
......@@ -93,4 +93,7 @@ public class Ticket {
@Field(name = "rating")
private Long rating = 0L;
@Field(name ="is_escalated_to_admin")
private Boolean escalatedToAdmin;
}
......@@ -57,4 +57,12 @@ public class NightlyJobScheduler {
emailService.sendSimpleMail(emailDetails);
}
}
@Scheduled(cron = "0 0 4 * * ?")
public void escalateTickets(){
log.info("Starting the escalation job");
long lastUpdateTimeBeforeEscalation = LocalDateTime.now().minusDays(1).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
long response = searchService.escalateTickets(lastUpdateTimeBeforeEscalation);
log.info("No of tickets escalated "+response);
}
}
......@@ -7,6 +7,10 @@ import java.util.Map;
public interface SearchService {
TicketResponse search(SearchRequest searchRequest);
Map<String, Object> searchTickets(SearchRequest searchRequest);
Map<String, Object> dashboardReport(SearchRequest searchRequest);
long escalateTickets(Long epochTime);
}
\ No newline at end of file
......@@ -4,6 +4,8 @@ import org.upsmf.grievance.model.Ticket;
import org.upsmf.grievance.dto.TicketRequest;
import org.upsmf.grievance.dto.UpdateTicketRequest;
import javax.transaction.Transactional;
public interface TicketService {
Ticket save(Ticket ticket);
......@@ -13,4 +15,7 @@ public interface TicketService {
Ticket update(UpdateTicketRequest updateTicketRequest) throws Exception;
Ticket getTicketById(long id);
@Transactional
void updateTicket(Long ticketId);
}
package org.upsmf.grievance.service.impl;
import lombok.extern.slf4j.Slf4j;
import org.apache.lucene.search.TotalHits;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.RequestOptions;
......@@ -11,10 +12,12 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.task.TaskExecutor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
import org.springframework.stereotype.Service;
import org.upsmf.grievance.config.EsConfig;
import org.upsmf.grievance.constants.Constants;
......@@ -26,6 +29,7 @@ import org.upsmf.grievance.model.es.Ticket;
import org.upsmf.grievance.model.reponse.TicketResponse;
import org.upsmf.grievance.repository.es.TicketRepository;
import org.upsmf.grievance.service.SearchService;
import org.upsmf.grievance.service.TicketService;
import java.io.IOException;
import java.time.Instant;
......@@ -45,6 +49,9 @@ public class SearchServiceImpl implements SearchService {
@Value("${pending.15.days}")
private long PENDING_15_DAYS;
@Value("${ticket.escalation.days}")
private long ticketEscalationDays;
@Value("${affiliation}")
private String AFFILIATION;
......@@ -79,6 +86,9 @@ public class SearchServiceImpl implements SearchService {
@Autowired
private EsConfig esConfig;
@Autowired
private TicketService ticketService;
@Override
public TicketResponse search(SearchRequest searchRequest) {
//Calculate
......@@ -154,6 +164,56 @@ public class SearchServiceImpl implements SearchService {
return finalResponse;
}
@Override
public long escalateTickets(Long lastUpdatedEpoch) {
BoolQueryBuilder finalQuery = createTicketEscalationQuery(lastUpdatedEpoch);
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(finalQuery);
SearchResponse searchResponse = getSearchResponseFromES(searchSourceBuilder);
if(searchResponse != null) {
TotalHits totalHits = searchResponse.getHits().getTotalHits();
if(totalHits != null && totalHits.value > 0) {
searchSourceBuilder = new SearchSourceBuilder()
.query(finalQuery).size(Integer.parseInt(String.valueOf(totalHits.value)));
searchResponse = getSearchResponseFromES(searchSourceBuilder);
if(searchResponse != null && searchResponse.getHits()!= null
&& searchResponse.getHits().getTotalHits() != null
&& searchResponse.getHits().getTotalHits().value > 0) {
escalatePendingTickets(searchResponse);
}
}
}
return searchResponse.getHits().getTotalHits().value;
}
private void escalatePendingTickets(SearchResponse searchResponse) {
Iterator<SearchHit> hits = searchResponse.getHits().iterator();
TaskExecutor taskExecutor = new ConcurrentTaskScheduler();
while(hits.hasNext()) {
Map<String, Object> searchHit = hits.next().getSourceAsMap();
taskExecutor.execute(new Runnable() {
@Override
public void run() {
ticketService.updateTicket(Long.parseLong(searchHit.get("ticket_id").toString()));
}
});
}
}
private SearchResponse getSearchResponseFromES(SearchSourceBuilder searchSourceBuilder) {
SearchResponse searchResponse;
org.elasticsearch.action.search.SearchRequest search = new org.elasticsearch.action.search.SearchRequest("ticket");
search.searchType(SearchType.QUERY_THEN_FETCH);
search.source(searchSourceBuilder);
try {
searchResponse = esConfig.elasticsearchClient().search(search, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
return searchResponse;
}
private void getfinalResponse(SearchRequest searchRequest, String cc) {
SearchResponse searchJunkResponse = getDashboardSearchResponse(searchRequest, "isJunk", cc, null);
SearchResponse searchOpenStatusResponse = getDashboardSearchResponse(searchRequest, "openStatus", cc, null);
......@@ -259,14 +319,7 @@ public class SearchServiceImpl implements SearchService {
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(finalQuery);
org.elasticsearch.action.search.SearchRequest search = new org.elasticsearch.action.search.SearchRequest("ticket");
search.searchType(SearchType.QUERY_THEN_FETCH);
search.source(searchSourceBuilder);
try {
searchResponse = esConfig.elasticsearchClient().search(search, RequestOptions.DEFAULT);
} catch (IOException e) {
throw new RuntimeException(e);
}
searchResponse = getSearchResponseFromES(searchSourceBuilder);
return searchResponse;
}
......@@ -537,6 +590,18 @@ public class SearchServiceImpl implements SearchService {
return finalQuery;
}
private BoolQueryBuilder createTicketEscalationQuery(Long lastUpdatedEpoch) {
BoolQueryBuilder finalQuery = QueryBuilders.boolQuery();
// search query
RangeQueryBuilder createdDateKeywordMatchQuery = QueryBuilders.rangeQuery("updated_date_ts").lte(lastUpdatedEpoch);
MatchQueryBuilder escalatedMatchQuery = QueryBuilders.matchQuery("is_escalated", false);
MatchQueryBuilder statusMatchQuery = QueryBuilders.matchQuery("status", "OPEN");
BoolQueryBuilder keywordSearchQuery = QueryBuilders.boolQuery();
keywordSearchQuery.must(createdDateKeywordMatchQuery).must(escalatedMatchQuery).must(statusMatchQuery);
finalQuery.must(keywordSearchQuery);
return finalQuery;
}
private BoolQueryBuilder getPriority(String priority, BoolQueryBuilder finalQuery) {
if (priority !=null && !priority.isBlank()) {
MatchQueryBuilder priorityMatchQuery = QueryBuilders.matchQuery("priority", priority);
......
......@@ -2,6 +2,7 @@ package org.upsmf.grievance.service.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.Synchronized;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
......@@ -26,6 +27,7 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
......@@ -309,6 +311,7 @@ public class TicketServiceImpl implements TicketService {
.priority(ticket.getPriority())
.escalatedBy(ticket.getEscalatedBy())
.escalatedTo(ticket.getEscalatedTo())
.escalatedToAdmin(ticket.isEscalatedToAdmin())
.rating(Long.valueOf(0)).build();
}
......@@ -382,7 +385,26 @@ public class TicketServiceImpl implements TicketService {
if (request.getPriority() == null || !isValidPriority(request.getPriority())) {
throw new IllegalArgumentException("Invalid ticket priority");
}
}
@Override
@Transactional
@Synchronized
public void updateTicket(Long ticketId) {
Ticket ticket = getTicketById(ticketId);
ticket.setUpdatedDate(new Timestamp(new Date().getTime()));
ticket.setEscalatedDate(new Timestamp(new Date().getTime()));
ticket.setEscalatedToAdmin(true);
ticketRepository.save(ticket);
ticket = getTicketById(ticket.getId());
// check if ticket exists in ES
Optional<org.upsmf.grievance.model.es.Ticket> esTicketDetails = esTicketRepository.findOneByTicketId(ticket.getId());
org.upsmf.grievance.model.es.Ticket updatedESTicket = convertToESTicketObj(ticket);
if(esTicketDetails.isPresent()) {
// TODO revisit this
esTicketRepository.deleteById(esTicketDetails.get().getId());
updatedESTicket.setRating(esTicketDetails.get().getRating());
}
org.upsmf.grievance.model.es.Ticket curentUpdatedTicket=esTicketRepository.save(updatedESTicket);
}
}
......@@ -53,7 +53,7 @@ spring.servlet.multipart.max-request-size=10MB
# Dashboard
pending.21.days=21
pending.15.days=15
ticket.escalation.days=14
ticket.escalation.days=7
email.ids=nodalofficer@yopmail.com,grievance@yopmail.com
subject.daily.report=Daily Report
subject.bi.weekly.report=Bi Weekly Report
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment