From 80c7f993ed55511fd22c8cf5386ed5c96ead243f Mon Sep 17 00:00:00 2001 From: Charishma0249 Date: Tue, 17 May 2022 11:43:58 -0400 Subject: [PATCH 01/15] [CITE-132] Addressing review comments-Implementing future cancel changes --- .../core/service/IAsyncCitationProcessor.java | 5 +- .../core/service/ICitationManager.java | 6 ++ .../service/impl/AsyncCitationProcessor.java | 61 +++++++++++++++++-- .../core/service/impl/CitationManager.java | 27 +++++++- .../core/service/jobs/ISyncJobManager.java | 4 ++ .../service/jobs/impl/SyncJobManager.java | 15 +++++ 6 files changed, 111 insertions(+), 7 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/IAsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/IAsyncCitationProcessor.java index d1782688c..e3812ccb6 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/IAsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/IAsyncCitationProcessor.java @@ -1,10 +1,13 @@ package edu.asu.diging.citesphere.core.service; +import java.util.Map; +import java.util.concurrent.Future; + import edu.asu.diging.citesphere.core.exceptions.ZoteroHttpStatusException; import edu.asu.diging.citesphere.user.IUser; public interface IAsyncCitationProcessor { - void sync(IUser user, String groupId, long contentVersion, String collectionId) throws ZoteroHttpStatusException; + Future sync(IUser user, String groupId, long contentVersion, String collectionId) throws ZoteroHttpStatusException; } \ No newline at end of file diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java index 6084a0355..65fa91da7 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java @@ -1,7 +1,9 @@ package edu.asu.diging.citesphere.core.service; import java.util.List; +import java.util.Map; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import org.springframework.data.util.CloseableIterator; import org.springframework.social.zotero.api.ZoteroUpdateItemsStatuses; @@ -26,6 +28,10 @@ public interface ICitationManager { + Map> getAsyncMap(); + + void cancel(); + List getGroups(IUser user); CitationResults getGroupItems(IUser user, String groupId, String collectionId, int page, String sortBy, List conceptIds) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index 29eec8845..86b8f142a 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -3,10 +3,12 @@ import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; @@ -17,6 +19,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import edu.asu.diging.citesphere.core.exceptions.ZoteroHttpStatusException; @@ -72,7 +75,7 @@ public void init() { inactiveJobStatuses.add(JobStatus.DONE); inactiveJobStatuses.add(JobStatus.FAILURE); } - + /* * (non-Javadoc) * @@ -83,16 +86,16 @@ public void init() { */ @Override @Async - public void sync(IUser user, String groupId, long contentVersion, String collectionId) throws ZoteroHttpStatusException { + public Future sync(IUser user, String groupId, long contentVersion, String collectionId) throws ZoteroHttpStatusException { GroupSyncJob prevJob = jobManager.getMostRecentJob(groupId + ""); // it's un-intuitive to test for not inactive statuses here, but it's more likely we'll add // more activate job statuses than inactive ones, so it's less error prone to use the list that // is less likely to change. if (prevJob != null && !inactiveJobStatuses.contains(prevJob.getStatus())) { // there is already a job running, let's not start another one - return; + return new AsyncResult(null); } - + logger.info("Starting sync for " + groupId); GroupSyncJob job = new GroupSyncJob(); job.setCreatedOn(OffsetDateTime.now()); @@ -100,6 +103,13 @@ public void sync(IUser user, String groupId, long contentVersion, String collect job.setStatus(JobStatus.PREPARED); jobRepo.save(job); jobManager.addJob(job); +// jobManager.addJobsToAsyncMap(job.getId(), new AsyncResult(job.getId())); + Thread currentThread = Thread.currentThread(); + + if(checkIfThreadIsInterrupted(currentThread)) { + setJobToCanceledState(job, groupId); + return new AsyncResult(job.getId()); + } // we'll retrieve the latest group version first in case there are more changes // in between @@ -119,26 +129,67 @@ public void sync(IUser user, String groupId, long contentVersion, String collect jobRepo.save(job); AtomicInteger counter = new AtomicInteger(); + + if(checkIfThreadIsInterrupted(currentThread)) { + setJobToCanceledState(job, groupId); + return new AsyncResult(job.getId()); + } + syncCitations(user, groupId, job, versions, counter); + + if(checkIfThreadIsInterrupted(currentThread)) { + setJobToCanceledState(job, groupId); + return new AsyncResult(job.getId()); + } + syncCollections(user, groupId, job, collectionVersions, groupVersion, counter); + if(checkIfThreadIsInterrupted(currentThread)) { + setJobToCanceledState(job, groupId); + return new AsyncResult(job.getId()); + } + removeDeletedItems(deletedElements, job); - + + if(checkIfThreadIsInterrupted(currentThread)) { + setJobToCanceledState(job, groupId); + return new AsyncResult(job.getId()); + } // while this thread has been running, the group might have been updated by another thread // so, we have to make sure there is no group with the same group id but other object id // or we'll end up with two groups with the same group id. Optional group = groupRepo.findFirstByGroupId(new Long(groupId)); + if (group.isPresent()) { group.get().setContentVersion(groupVersion); groupRepo.save((CitationGroup) group.get()); } + if(checkIfThreadIsInterrupted(currentThread)) { + setJobToCanceledState(job, groupId); + return new AsyncResult(job.getId()); + } + job.setStatus(JobStatus.DONE); job.setFinishedOn(OffsetDateTime.now()); jobRepo.save(job); + + Future result = new AsyncResult(job.getId()); + return result; } + private boolean checkIfThreadIsInterrupted(Thread thread) { + return thread.isInterrupted(); + } + + private void setJobToCanceledState(GroupSyncJob job, String groupId) { + logger.info("Aborting sync for " + groupId); + job.setStatus(JobStatus.CANCELED); + job.setFinishedOn(OffsetDateTime.now()); + jobRepo.save(job); + } + private void syncCitations(IUser user, String groupId, GroupSyncJob job, Map versions, AtomicInteger counter) throws ZoteroHttpStatusException { List keysToRetrieve = new ArrayList<>(); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index 847bde584..02354c2ee 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -7,6 +7,7 @@ import java.util.Map; import java.util.Optional; import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; import java.util.function.BiFunction; import javax.annotation.PostConstruct; @@ -18,6 +19,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.data.util.CloseableIterator; +import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.social.zotero.api.ZoteroUpdateItemsStatuses; import org.springframework.social.zotero.exception.ZoteroConnectionException; import org.springframework.stereotype.Service; @@ -85,9 +87,14 @@ public class CitationManager implements ICitationManager { private IAsyncCitationProcessor asyncCitationProcessor; private Map> sortFunctions; + + private Map> asyncMap; + Future future = new AsyncResult(null); + @PostConstruct public void init() { + asyncMap = new HashMap<>(); sortFunctions = new HashMap<>(); sortFunctions.put("title", ((o1, o2) -> { String o1Title = o1 != null && o1.getTitle() != null ? o1.getTitle() : ""; @@ -96,6 +103,10 @@ public void init() { })); } + @Override + public Map> getAsyncMap() { + return asyncMap; + } @Override public ICitation getCitation(String key) { Optional optional = citationStore.findById(key); @@ -305,7 +316,15 @@ public CloseableIterator getAllGroupItems(IUser user, String groupId, } boolean isModified = zoteroManager.isGroupModified(user, groupId, group.getContentVersion()); if (isModified) { - asyncCitationProcessor.sync(user, group.getGroupId() + "", group.getContentVersion(), collectionId); + future = asyncCitationProcessor.sync(user, group.getGroupId() + "", group.getContentVersion(), collectionId); + + try { + String jobid = future.get(); + asyncMap.put(jobid, future); + } + catch(Exception ex) { + logger.info("Exception occured " + ex); + } throw new SyncInProgressException(); } @@ -314,6 +333,12 @@ public CloseableIterator getAllGroupItems(IUser user, String groupId, throw new GroupDoesNotExistException("Group " + groupId + " does not exist."); } + + @Override + public void cancel() { + boolean val = future.cancel(true); + + } @Override public CitationResults getGroupItems(IUser user, String groupId, String collectionId, int page, String sortBy, List conceptIds) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java index bb245da6c..2f3ab9e75 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java @@ -1,8 +1,10 @@ package edu.asu.diging.citesphere.core.service.jobs; import java.util.List; +import java.util.concurrent.Future; import org.springframework.data.domain.Pageable; +import org.springframework.scheduling.annotation.AsyncResult; import edu.asu.diging.citesphere.core.model.jobs.impl.GroupSyncJob; import edu.asu.diging.citesphere.user.IUser; @@ -18,5 +20,7 @@ public interface ISyncJobManager { long getJobsCount(IUser user); void cancelJob(String jobId); + +// void addJobsToAsyncMap(String job, AsyncResult result); } \ No newline at end of file diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java index fa4fb77df..1deb6c170 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java @@ -1,10 +1,12 @@ package edu.asu.diging.citesphere.core.service.jobs.impl; import java.time.OffsetDateTime; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Future; import java.util.stream.Collectors; import javax.annotation.PostConstruct; @@ -12,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import org.springframework.scheduling.annotation.AsyncResult; import edu.asu.diging.citesphere.core.model.jobs.IJob; import edu.asu.diging.citesphere.core.model.jobs.JobStatus; @@ -32,12 +35,20 @@ public class SyncJobManager implements ISyncJobManager { @Autowired private ICitationManager citationManager; + +// private Map> asyncMap; @PostConstruct public void init() { +// asyncMap = new HashMap<>(); currentJobs = new ConcurrentHashMap<>(); } +// @Override +// public void addJobsToAsyncMap(String job, AsyncResult result) { +// asyncMap.put(job, result); +// } + /* (non-Javadoc) * @see edu.asu.diging.citesphere.core.service.jobs.impl.ISyncJobManager#addJobId(edu.asu.diging.citesphere.core.model.jobs.impl.GroupSyncJob) */ @@ -87,6 +98,10 @@ public void cancelJob(String jobId) { job.setStatus(JobStatus.CANCELED); job.setFinishedOn(OffsetDateTime.now()); jobRepo.save(job); + +// Future future = citationManager.getAsyncMap().get(jobId); +// future.cancel(true); + citationManager.cancel(); } } } From 3a42c7b8caa2be8ed74154cc02bc8547bea1f9e8 Mon Sep 17 00:00:00 2001 From: Charishma0249 Date: Tue, 17 May 2022 20:02:40 -0400 Subject: [PATCH 02/15] [CITE-132]Addressing review comments-implementing java future cancel job --- .../core/service/IAsyncCitationProcessor.java | 1 - .../core/service/ICitationManager.java | 6 +-- .../service/impl/AsyncCitationProcessor.java | 2 - .../core/service/impl/CitationManager.java | 38 +++++++------------ .../core/service/jobs/ISyncJobManager.java | 5 --- .../service/jobs/impl/SyncJobManager.java | 24 +++--------- 6 files changed, 20 insertions(+), 56 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/IAsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/IAsyncCitationProcessor.java index e3812ccb6..130aaa3f3 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/IAsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/IAsyncCitationProcessor.java @@ -1,6 +1,5 @@ package edu.asu.diging.citesphere.core.service; -import java.util.Map; import java.util.concurrent.Future; import edu.asu.diging.citesphere.core.exceptions.ZoteroHttpStatusException; diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java index 65fa91da7..d17ed73bb 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java @@ -1,9 +1,7 @@ package edu.asu.diging.citesphere.core.service; import java.util.List; -import java.util.Map; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; import org.springframework.data.util.CloseableIterator; import org.springframework.social.zotero.api.ZoteroUpdateItemsStatuses; @@ -27,10 +25,8 @@ import edu.asu.diging.citesphere.user.IUser; public interface ICitationManager { - - Map> getAsyncMap(); - void cancel(); + boolean cancel(); List getGroups(IUser user); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index 86b8f142a..f3436f864 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -3,7 +3,6 @@ import java.time.OffsetDateTime; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -103,7 +102,6 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri job.setStatus(JobStatus.PREPARED); jobRepo.save(job); jobManager.addJob(job); -// jobManager.addJobsToAsyncMap(job.getId(), new AsyncResult(job.getId())); Thread currentThread = Thread.currentThread(); if(checkIfThreadIsInterrupted(currentThread)) { diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index 02354c2ee..8eb3d755f 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -19,7 +19,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.PropertySource; import org.springframework.data.util.CloseableIterator; -import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.social.zotero.api.ZoteroUpdateItemsStatuses; import org.springframework.social.zotero.exception.ZoteroConnectionException; import org.springframework.stereotype.Service; @@ -87,14 +86,11 @@ public class CitationManager implements ICitationManager { private IAsyncCitationProcessor asyncCitationProcessor; private Map> sortFunctions; - - private Map> asyncMap; - Future future = new AsyncResult(null); + Future future; @PostConstruct public void init() { - asyncMap = new HashMap<>(); sortFunctions = new HashMap<>(); sortFunctions.put("title", ((o1, o2) -> { String o1Title = o1 != null && o1.getTitle() != null ? o1.getTitle() : ""; @@ -103,10 +99,6 @@ public void init() { })); } - @Override - public Map> getAsyncMap() { - return asyncMap; - } @Override public ICitation getCitation(String key) { Optional optional = citationStore.findById(key); @@ -316,15 +308,7 @@ public CloseableIterator getAllGroupItems(IUser user, String groupId, } boolean isModified = zoteroManager.isGroupModified(user, groupId, group.getContentVersion()); if (isModified) { - future = asyncCitationProcessor.sync(user, group.getGroupId() + "", group.getContentVersion(), collectionId); - - try { - String jobid = future.get(); - asyncMap.put(jobid, future); - } - catch(Exception ex) { - logger.info("Exception occured " + ex); - } + asyncCitationProcessor.sync(user, group.getGroupId() + "", group.getContentVersion(), collectionId); throw new SyncInProgressException(); } @@ -333,12 +317,6 @@ public CloseableIterator getAllGroupItems(IUser user, String groupId, throw new GroupDoesNotExistException("Group " + groupId + " does not exist."); } - - @Override - public void cancel() { - boolean val = future.cancel(true); - - } @Override public CitationResults getGroupItems(IUser user, String groupId, String collectionId, int page, String sortBy, List conceptIds) @@ -376,7 +354,7 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti // then update content results.setNotModified(false); - asyncCitationProcessor.sync(user, group.getGroupId() + "", previousVersion, collectionId); + future = asyncCitationProcessor.sync(user, group.getGroupId() + "", previousVersion, collectionId); } else { results.setNotModified(true); } @@ -405,6 +383,16 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti return results; } + + @Override + public boolean cancel() { + boolean result = false; + if(future != null) { + result = future.cancel(true); + } + + return result; + } @Override public void forceGroupItemsRefresh(IUser user, String groupId, String collectionId, int page, String sortBy) { diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java index 2f3ab9e75..153fe9921 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java @@ -1,10 +1,8 @@ package edu.asu.diging.citesphere.core.service.jobs; import java.util.List; -import java.util.concurrent.Future; import org.springframework.data.domain.Pageable; -import org.springframework.scheduling.annotation.AsyncResult; import edu.asu.diging.citesphere.core.model.jobs.impl.GroupSyncJob; import edu.asu.diging.citesphere.user.IUser; @@ -20,7 +18,4 @@ public interface ISyncJobManager { long getJobsCount(IUser user); void cancelJob(String jobId); - -// void addJobsToAsyncMap(String job, AsyncResult result); - } \ No newline at end of file diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java index 1deb6c170..a85af142a 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java @@ -1,12 +1,10 @@ package edu.asu.diging.citesphere.core.service.jobs.impl; import java.time.OffsetDateTime; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.Future; import java.util.stream.Collectors; import javax.annotation.PostConstruct; @@ -14,9 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import org.springframework.scheduling.annotation.AsyncResult; -import edu.asu.diging.citesphere.core.model.jobs.IJob; import edu.asu.diging.citesphere.core.model.jobs.JobStatus; import edu.asu.diging.citesphere.core.model.jobs.impl.GroupSyncJob; import edu.asu.diging.citesphere.core.repository.jobs.GroupSyncJobRepository; @@ -35,19 +31,12 @@ public class SyncJobManager implements ISyncJobManager { @Autowired private ICitationManager citationManager; - -// private Map> asyncMap; @PostConstruct public void init() { -// asyncMap = new HashMap<>(); currentJobs = new ConcurrentHashMap<>(); } -// @Override -// public void addJobsToAsyncMap(String job, AsyncResult result) { -// asyncMap.put(job, result); -// } /* (non-Javadoc) * @see edu.asu.diging.citesphere.core.service.jobs.impl.ISyncJobManager#addJobId(edu.asu.diging.citesphere.core.model.jobs.impl.GroupSyncJob) @@ -95,13 +84,12 @@ public void cancelJob(String jobId) { if (job == null) { job = jobOptional.get(); } - job.setStatus(JobStatus.CANCELED); - job.setFinishedOn(OffsetDateTime.now()); - jobRepo.save(job); - -// Future future = citationManager.getAsyncMap().get(jobId); -// future.cancel(true); - citationManager.cancel(); + + if(!citationManager.cancel()) { + job.setStatus(JobStatus.CANCELED); + job.setFinishedOn(OffsetDateTime.now()); + jobRepo.save(job); + } } } } From 65d89c3ad31f4af6c4d78699d5bec0c02fbac4aa Mon Sep 17 00:00:00 2001 From: Charishma0249 Date: Wed, 18 May 2022 12:01:03 -0400 Subject: [PATCH 03/15] [CITE-132] Addressed review comments - code cleanup --- .../service/impl/AsyncCitationProcessor.java | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index f3436f864..9dead3ae8 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -104,8 +104,7 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri jobManager.addJob(job); Thread currentThread = Thread.currentThread(); - if(checkIfThreadIsInterrupted(currentThread)) { - setJobToCanceledState(job, groupId); + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } @@ -128,29 +127,25 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri AtomicInteger counter = new AtomicInteger(); - if(checkIfThreadIsInterrupted(currentThread)) { - setJobToCanceledState(job, groupId); + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } syncCitations(user, groupId, job, versions, counter); - if(checkIfThreadIsInterrupted(currentThread)) { - setJobToCanceledState(job, groupId); + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } syncCollections(user, groupId, job, collectionVersions, groupVersion, counter); - if(checkIfThreadIsInterrupted(currentThread)) { - setJobToCanceledState(job, groupId); + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } removeDeletedItems(deletedElements, job); - if(checkIfThreadIsInterrupted(currentThread)) { - setJobToCanceledState(job, groupId); + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } @@ -164,8 +159,7 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri groupRepo.save((CitationGroup) group.get()); } - if(checkIfThreadIsInterrupted(currentThread)) { - setJobToCanceledState(job, groupId); + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } @@ -177,8 +171,13 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri return result; } - private boolean checkIfThreadIsInterrupted(Thread thread) { - return thread.isInterrupted(); + private boolean checkIfThreadIsInterrupted(Thread thread, GroupSyncJob job, String groupId) { + + if(thread.isInterrupted()) { + setJobToCanceledState(job, groupId); + return true; + } + return false; } private void setJobToCanceledState(GroupSyncJob job, String groupId) { From 2f0a2fce1a81e042f73e839bbbd5047f645a341a Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Tue, 23 Apr 2024 15:34:35 -0700 Subject: [PATCH 04/15] [CITE-132] update cancel method return and updated cancel check in SyncJobManager --- .../citesphere/core/service/impl/CitationManager.java | 7 +++---- .../citesphere/core/service/jobs/impl/SyncJobManager.java | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index e2a8c377a..3c74e922a 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -435,12 +435,11 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti @Override public boolean cancel() { - boolean result = false; if(future != null) { - result = future.cancel(true); - } + return future.cancel(true); + } - return result; + return false; } @Override diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java index a85af142a..4de01895a 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java @@ -85,7 +85,7 @@ public void cancelJob(String jobId) { job = jobOptional.get(); } - if(!citationManager.cancel()) { + if(citationManager.cancel()) { job.setStatus(JobStatus.CANCELED); job.setFinishedOn(OffsetDateTime.now()); jobRepo.save(job); From 3d493f842722d3d6ec1178d477105e6951a706a6 Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Fri, 26 Apr 2024 16:18:20 -0700 Subject: [PATCH 05/15] [CITE-132] Using concurrent Hashmap for storing future --- .../core/service/ICitationManager.java | 2 +- .../service/impl/AsyncCitationProcessor.java | 2 +- .../core/service/impl/CitationManager.java | 25 ++++++++++++++----- .../service/jobs/impl/SyncJobManager.java | 8 +++--- 4 files changed, 24 insertions(+), 13 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java index 4460892f8..68fcadf21 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java @@ -26,7 +26,7 @@ public interface ICitationManager { - boolean cancel(); + boolean cancel(String groupId); List getGroups(IUser user); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index 9dead3ae8..b2eb77327 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -88,7 +88,7 @@ public void init() { public Future sync(IUser user, String groupId, long contentVersion, String collectionId) throws ZoteroHttpStatusException { GroupSyncJob prevJob = jobManager.getMostRecentJob(groupId + ""); // it's un-intuitive to test for not inactive statuses here, but it's more likely we'll add - // more activate job statuses than inactive ones, so it's less error prone to use the list that + // more active job statuses than inactive ones, so it's less error prone to use the list that // is less likely to change. if (prevJob != null && !inactiveJobStatuses.contains(prevJob.getStatus())) { // there is already a job running, let's not start another one diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index 3c74e922a..a44504b74 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.BiFunction; @@ -87,7 +88,7 @@ public class CitationManager implements ICitationManager { private Map> sortFunctions; - Future future; + Map> futureMap = new ConcurrentHashMap<>(); @PostConstruct public void init() { @@ -370,6 +371,8 @@ public CloseableIterator getAllGroupItems(IUser user, String groupId, @Override public CitationResults getGroupItems(IUser user, String groupId, String collectionId, int page, String sortBy, List conceptIds) throws GroupDoesNotExistException, ZoteroHttpStatusException { + + System.out.println("I am coming here"); ICitationGroup group = null; Optional groupOptional = groupRepository.findFirstByGroupId(new Long(groupId)); @@ -386,6 +389,12 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti if (group == null) { throw new GroupDoesNotExistException("There is no group with id " + groupId); } + + Future existingFuture = futureMap.get(groupId); + if (existingFuture != null && !existingFuture.isDone()) { + existingFuture.cancel(true); + futureMap.remove(groupId); + } boolean isModified = zoteroManager.isGroupModified(user, groupId, group.getContentVersion()); CitationResults results = new CitationResults(); @@ -403,11 +412,13 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti // then update content results.setNotModified(false); - future = asyncCitationProcessor.sync(user, group.getGroupId() + "", previousVersion, collectionId); + Future future = asyncCitationProcessor.sync(user, group.getGroupId() + "", previousVersion, collectionId); + futureMap.put(groupId, future); } else { results.setNotModified(true); } - + + System.out.println(futureMap.toString()); List citations = null; long total = 0; if (collectionId != null && !collectionId.trim().isEmpty()) { @@ -434,11 +445,13 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti } @Override - public boolean cancel() { - if(future != null) { + public boolean cancel(String groupId) { + System.out.println("I am also coming here"); + Future future = futureMap.get(groupId); + if (future != null) { + futureMap.remove(groupId); return future.cancel(true); } - return false; } diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java index 4de01895a..ae9faca5b 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java @@ -79,13 +79,11 @@ public long getJobsCount(IUser user) { @Override public void cancelJob(String jobId) { Optional jobOptional = jobRepo.findById(jobId); + String groupId; if (jobOptional.isPresent()) { GroupSyncJob job = currentJobs.get(jobOptional.get().getGroupId()); - if (job == null) { - job = jobOptional.get(); - } - - if(citationManager.cancel()) { + groupId = job.getGroupId(); + if(citationManager.cancel(groupId)) { job.setStatus(JobStatus.CANCELED); job.setFinishedOn(OffsetDateTime.now()); jobRepo.save(job); From 2e5c9699d94cd8b1650467199680c7d8e3eb9797 Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Fri, 26 Apr 2024 16:21:33 -0700 Subject: [PATCH 06/15] [CITE 132] Removed Sysout statements --- .../citesphere/core/service/impl/CitationManager.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index a44504b74..588c7e8b3 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -371,8 +371,6 @@ public CloseableIterator getAllGroupItems(IUser user, String groupId, @Override public CitationResults getGroupItems(IUser user, String groupId, String collectionId, int page, String sortBy, List conceptIds) throws GroupDoesNotExistException, ZoteroHttpStatusException { - - System.out.println("I am coming here"); ICitationGroup group = null; Optional groupOptional = groupRepository.findFirstByGroupId(new Long(groupId)); @@ -417,8 +415,7 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti } else { results.setNotModified(true); } - - System.out.println(futureMap.toString()); + List citations = null; long total = 0; if (collectionId != null && !collectionId.trim().isEmpty()) { @@ -446,7 +443,6 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti @Override public boolean cancel(String groupId) { - System.out.println("I am also coming here"); Future future = futureMap.get(groupId); if (future != null) { futureMap.remove(groupId); From 10d93520891cac1e58746a36c84c15e63f20ef88 Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Fri, 3 May 2024 12:45:36 -0700 Subject: [PATCH 07/15] [CITE 132] removed extra spaces, tabs --- .../citesphere/core/service/ICitationManager.java | 4 ++-- .../core/service/impl/AsyncCitationProcessor.java | 14 +++++++------- .../core/service/impl/CitationManager.java | 8 ++++---- .../core/service/jobs/impl/SyncJobManager.java | 3 +-- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java index 68fcadf21..ce70ff81a 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/ICitationManager.java @@ -25,9 +25,9 @@ import edu.asu.diging.citesphere.user.IUser; public interface ICitationManager { - + boolean cancel(String groupId); - + List getGroups(IUser user); CitationResults getGroupItems(IUser user, String groupId, String collectionId, int page, String sortBy, List conceptIds) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index b2eb77327..15a23488a 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -74,7 +74,7 @@ public void init() { inactiveJobStatuses.add(JobStatus.DONE); inactiveJobStatuses.add(JobStatus.FAILURE); } - + /* * (non-Javadoc) * @@ -94,7 +94,7 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri // there is already a job running, let's not start another one return new AsyncResult(null); } - + logger.info("Starting sync for " + groupId); GroupSyncJob job = new GroupSyncJob(); job.setCreatedOn(OffsetDateTime.now()); @@ -103,7 +103,7 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri jobRepo.save(job); jobManager.addJob(job); Thread currentThread = Thread.currentThread(); - + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } @@ -153,7 +153,7 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri // so, we have to make sure there is no group with the same group id but other object id // or we'll end up with two groups with the same group id. Optional group = groupRepo.findFirstByGroupId(new Long(groupId)); - + if (group.isPresent()) { group.get().setContentVersion(groupVersion); groupRepo.save((CitationGroup) group.get()); @@ -162,11 +162,11 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } - + job.setStatus(JobStatus.DONE); job.setFinishedOn(OffsetDateTime.now()); jobRepo.save(job); - + Future result = new AsyncResult(job.getId()); return result; } @@ -186,7 +186,7 @@ private void setJobToCanceledState(GroupSyncJob job, String groupId) { job.setFinishedOn(OffsetDateTime.now()); jobRepo.save(job); } - + private void syncCitations(IUser user, String groupId, GroupSyncJob job, Map versions, AtomicInteger counter) throws ZoteroHttpStatusException { List keysToRetrieve = new ArrayList<>(); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index 588c7e8b3..635247391 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -89,7 +89,7 @@ public class CitationManager implements ICitationManager { private Map> sortFunctions; Map> futureMap = new ConcurrentHashMap<>(); - + @PostConstruct public void init() { sortFunctions = new HashMap<>(); @@ -387,7 +387,7 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti if (group == null) { throw new GroupDoesNotExistException("There is no group with id " + groupId); } - + Future existingFuture = futureMap.get(groupId); if (existingFuture != null && !existingFuture.isDone()) { existingFuture.cancel(true); @@ -415,7 +415,7 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti } else { results.setNotModified(true); } - + List citations = null; long total = 0; if (collectionId != null && !collectionId.trim().isEmpty()) { @@ -440,7 +440,7 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti return results; } - + @Override public boolean cancel(String groupId) { Future future = futureMap.get(groupId); diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java index ae9faca5b..b19eb31b7 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/impl/SyncJobManager.java @@ -36,8 +36,7 @@ public class SyncJobManager implements ISyncJobManager { public void init() { currentJobs = new ConcurrentHashMap<>(); } - - + /* (non-Javadoc) * @see edu.asu.diging.citesphere.core.service.jobs.impl.ISyncJobManager#addJobId(edu.asu.diging.citesphere.core.model.jobs.impl.GroupSyncJob) */ From 03e5ec3010a993f32c1d922aa0fa9f037d50bcfc Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Fri, 3 May 2024 12:54:40 -0700 Subject: [PATCH 08/15] [CITE 132] spaces fixes --- .../core/service/impl/AsyncCitationProcessor.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index 15a23488a..df765c0f4 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -130,25 +130,25 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } - + syncCitations(user, groupId, job, versions, counter); - + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } - + syncCollections(user, groupId, job, collectionVersions, groupVersion, counter); if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } - + removeDeletedItems(deletedElements, job); - + if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { return new AsyncResult(job.getId()); } - + // while this thread has been running, the group might have been updated by another thread // so, we have to make sure there is no group with the same group id but other object id // or we'll end up with two groups with the same group id. @@ -179,7 +179,7 @@ private boolean checkIfThreadIsInterrupted(Thread thread, GroupSyncJob job, Stri } return false; } - + private void setJobToCanceledState(GroupSyncJob job, String groupId) { logger.info("Aborting sync for " + groupId); job.setStatus(JobStatus.CANCELED); From d36fdadefc6dc801bf670e14f7f68a04436706b6 Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Fri, 3 May 2024 13:01:29 -0700 Subject: [PATCH 09/15] [CITE 132] spaces fixes --- .../asu/diging/citesphere/core/service/jobs/ISyncJobManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java index 153fe9921..bb245da6c 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/jobs/ISyncJobManager.java @@ -18,4 +18,5 @@ public interface ISyncJobManager { long getJobsCount(IUser user); void cancelJob(String jobId); + } \ No newline at end of file From b80eb69c7c28633e1953b4905b363397d5c39076 Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Tue, 14 May 2024 12:42:47 -0700 Subject: [PATCH 10/15] [CITE-132] refactor CheckIfInterrupted method --- .../service/impl/AsyncCitationProcessor.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index df765c0f4..a5e7ff189 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -102,9 +102,8 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri job.setStatus(JobStatus.PREPARED); jobRepo.save(job); jobManager.addJob(job); - Thread currentThread = Thread.currentThread(); - if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { + if(checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { return new AsyncResult(job.getId()); } @@ -127,25 +126,25 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri AtomicInteger counter = new AtomicInteger(); - if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { + if(checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { return new AsyncResult(job.getId()); } syncCitations(user, groupId, job, versions, counter); - if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { + if(checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { return new AsyncResult(job.getId()); } syncCollections(user, groupId, job, collectionVersions, groupVersion, counter); - if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { + if(checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { return new AsyncResult(job.getId()); } removeDeletedItems(deletedElements, job); - if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { + if(checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { return new AsyncResult(job.getId()); } @@ -159,7 +158,7 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri groupRepo.save((CitationGroup) group.get()); } - if(checkIfThreadIsInterrupted(currentThread, job, groupId)) { + if(checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { return new AsyncResult(job.getId()); } @@ -167,12 +166,11 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri job.setFinishedOn(OffsetDateTime.now()); jobRepo.save(job); - Future result = new AsyncResult(job.getId()); - return result; + return new AsyncResult(job.getId()); } - private boolean checkIfThreadIsInterrupted(Thread thread, GroupSyncJob job, String groupId) { - + private boolean checkIfThreadIsInterruptedAndCancelJob(GroupSyncJob job, String groupId) { + Thread thread = Thread.currentThread(); if(thread.isInterrupted()) { setJobToCanceledState(job, groupId); return true; From 1b033b9ec82e53d6e1e7a5623ef4eeb73265553f Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Tue, 14 May 2024 13:52:05 -0700 Subject: [PATCH 11/15] [CITE-132] cancelling of job is not required in getGroupItems --- .../citesphere/core/service/impl/CitationManager.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index 635247391..633028df8 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -388,12 +388,6 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti throw new GroupDoesNotExistException("There is no group with id " + groupId); } - Future existingFuture = futureMap.get(groupId); - if (existingFuture != null && !existingFuture.isDone()) { - existingFuture.cancel(true); - futureMap.remove(groupId); - } - boolean isModified = zoteroManager.isGroupModified(user, groupId, group.getContentVersion()); CitationResults results = new CitationResults(); if (isModified) { From 55723b7caedd44c5bf529a23b3efc2d5f2c8ff78 Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Wed, 22 May 2024 10:17:20 -0700 Subject: [PATCH 12/15] [CITE-132] cancelling job within sync --- .../core/service/impl/AsyncCitationProcessor.java | 13 +++++++++++-- .../core/service/jobs/impl/SyncJobManager.java | 4 +--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index a5e7ff189..b5110ddfd 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -170,8 +170,7 @@ public Future sync(IUser user, String groupId, long contentVersion, Stri } private boolean checkIfThreadIsInterruptedAndCancelJob(GroupSyncJob job, String groupId) { - Thread thread = Thread.currentThread(); - if(thread.isInterrupted()) { + if(Thread.currentThread().isInterrupted()) { setJobToCanceledState(job, groupId); return true; } @@ -189,6 +188,11 @@ private void syncCitations(IUser user, String groupId, GroupSyncJob job, Map keysToRetrieve = new ArrayList<>(); for (String key : versions.keySet()) { + + if (checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { + return; + } + Optional citation = citationStore.findById(key); if (citation.isPresent()) { @@ -220,6 +224,11 @@ private void syncCollections(IUser user, String groupId, GroupSyncJob job, Map jobOptional = jobRepo.findById(jobId); - String groupId; if (jobOptional.isPresent()) { GroupSyncJob job = currentJobs.get(jobOptional.get().getGroupId()); - groupId = job.getGroupId(); - if(citationManager.cancel(groupId)) { + if(citationManager.cancel(job.getGroupId())) { job.setStatus(JobStatus.CANCELED); job.setFinishedOn(OffsetDateTime.now()); jobRepo.save(job); From 706db1100aa7003cf28105b7540cd1d1c4edd6a6 Mon Sep 17 00:00:00 2001 From: sathish2379 Date: Wed, 22 May 2024 10:23:47 -0700 Subject: [PATCH 13/15] [CITE-132] correcting indentations --- .../citesphere/core/service/impl/AsyncCitationProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java index b5110ddfd..83eed1a26 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/AsyncCitationProcessor.java @@ -189,7 +189,7 @@ private void syncCitations(IUser user, String groupId, GroupSyncJob job, Map keysToRetrieve = new ArrayList<>(); for (String key : versions.keySet()) { - if (checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { + if (checkIfThreadIsInterruptedAndCancelJob(job, groupId)) { return; } @@ -225,7 +225,7 @@ private void syncCollections(IUser user, String groupId, GroupSyncJob job, Map Date: Fri, 25 Jul 2025 18:11:05 -0500 Subject: [PATCH 14/15] [CITE-132] Handle race condition for sync --- .../core/service/impl/CitationManager.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index 633028df8..faaf5261a 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -39,6 +39,9 @@ import edu.asu.diging.citesphere.core.service.ICitationManager; import edu.asu.diging.citesphere.core.service.ICitationStore; import edu.asu.diging.citesphere.core.service.IGroupManager; +import edu.asu.diging.citesphere.core.service.jobs.ISyncJobManager; +import edu.asu.diging.citesphere.core.model.jobs.JobStatus; +import edu.asu.diging.citesphere.core.model.jobs.impl.GroupSyncJob; import edu.asu.diging.citesphere.core.zotero.IZoteroManager; import edu.asu.diging.citesphere.data.bib.CitationGroupRepository; import edu.asu.diging.citesphere.data.bib.ICitationDao; @@ -86,6 +89,9 @@ public class CitationManager implements ICitationManager { @Autowired private IAsyncCitationProcessor asyncCitationProcessor; + @Autowired + private ISyncJobManager syncJobManager; + private Map> sortFunctions; Map> futureMap = new ConcurrentHashMap<>(); @@ -390,6 +396,8 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti boolean isModified = zoteroManager.isGroupModified(user, groupId, group.getContentVersion()); CitationResults results = new CitationResults(); + boolean syncStarted = false; + if (isModified) { long previousVersion = group.getContentVersion(); // first update the group info @@ -406,12 +414,33 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti results.setNotModified(false); Future future = asyncCitationProcessor.sync(user, group.getGroupId() + "", previousVersion, collectionId); futureMap.put(groupId, future); + syncStarted = true; } else { results.setNotModified(true); } List citations = null; long total = 0; + + // If sync was started, check its status before querying database + if (syncStarted) { + // Check sync job status to handle cancellation gracefully + GroupSyncJob syncJob = syncJobManager.getMostRecentJob(groupId); + if (syncJob != null && (syncJob.getStatus() == JobStatus.CANCELED || syncJob.getStatus() == JobStatus.FAILURE)) { + logger.warn("Sync was cancelled or failed for group " + groupId + ", falling back to Zotero direct fetch"); + // Fallback: get items directly from Zotero for this page + try { + CitationResults zoteroResults = zoteroManager.getGroupItems(user, groupId, page, sortBy, group.getContentVersion()); + results.setCitations(zoteroResults.getCitations()); + results.setTotalResults(zoteroResults.getTotalResults()); + return results; + } catch (ZoteroHttpStatusException e) { + logger.error("Failed to fetch from Zotero as fallback", e); + // Continue with database query as last resort + } + } + } + if (collectionId != null && !collectionId.trim().isEmpty()) { citations = (List) citationDao.findCitationsInCollection(groupId, collectionId, (page - 1) * zoteroPageSize, zoteroPageSize, conceptIds); ICitationCollection collection = collectionManager.getCollection(user, groupId, collectionId); From 1ff5c112c2b6ebb990c7a2d9b33560679cff7858 Mon Sep 17 00:00:00 2001 From: Rajvi Patel Date: Thu, 31 Jul 2025 17:17:55 -0700 Subject: [PATCH 15/15] [CITE-132] Comment out code to check race condition --- .../core/service/impl/CitationManager.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java index faaf5261a..288c4f904 100644 --- a/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java +++ b/citesphere/src/main/java/edu/asu/diging/citesphere/core/service/impl/CitationManager.java @@ -423,23 +423,23 @@ public CitationResults getGroupItems(IUser user, String groupId, String collecti long total = 0; // If sync was started, check its status before querying database - if (syncStarted) { - // Check sync job status to handle cancellation gracefully - GroupSyncJob syncJob = syncJobManager.getMostRecentJob(groupId); - if (syncJob != null && (syncJob.getStatus() == JobStatus.CANCELED || syncJob.getStatus() == JobStatus.FAILURE)) { - logger.warn("Sync was cancelled or failed for group " + groupId + ", falling back to Zotero direct fetch"); - // Fallback: get items directly from Zotero for this page - try { - CitationResults zoteroResults = zoteroManager.getGroupItems(user, groupId, page, sortBy, group.getContentVersion()); - results.setCitations(zoteroResults.getCitations()); - results.setTotalResults(zoteroResults.getTotalResults()); - return results; - } catch (ZoteroHttpStatusException e) { - logger.error("Failed to fetch from Zotero as fallback", e); - // Continue with database query as last resort - } - } - } + // if (syncStarted) { + // // Check sync job status to handle cancellation gracefully + // GroupSyncJob syncJob = syncJobManager.getMostRecentJob(groupId); + // if (syncJob != null && (syncJob.getStatus() == JobStatus.CANCELED || syncJob.getStatus() == JobStatus.FAILURE)) { + // logger.warn("Sync was cancelled or failed for group " + groupId + ", falling back to Zotero direct fetch"); + // // Fallback: get items directly from Zotero for this page + // try { + // CitationResults zoteroResults = zoteroManager.getGroupItems(user, groupId, page, sortBy, group.getContentVersion()); + // results.setCitations(zoteroResults.getCitations()); + // results.setTotalResults(zoteroResults.getTotalResults()); + // return results; + // } catch (ZoteroHttpStatusException e) { + // logger.error("Failed to fetch from Zotero as fallback", e); + // // Continue with database query as last resort + // } + // } + // } if (collectionId != null && !collectionId.trim().isEmpty()) { citations = (List) citationDao.findCitationsInCollection(groupId, collectionId, (page - 1) * zoteroPageSize, zoteroPageSize, conceptIds);