diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java index 75c10efaa56..93cb4797eba 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirSystemDao.java @@ -53,6 +53,7 @@ import ca.uhn.fhir.parser.DataFormatException; import ca.uhn.fhir.rest.api.RestOperationTypeEnum; import ca.uhn.fhir.rest.server.IBundleProvider; import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException; +import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException; import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails; public abstract class BaseHapiFhirSystemDao extends BaseHapiFhirDaoimplements IFhirSystemDao { @@ -75,6 +76,65 @@ public abstract class BaseHapiFhirSystemDao extends BaseHapiFhirDao() { + @SuppressWarnings("unchecked") + @Override + public Integer doInTransaction(TransactionStatus theStatus) { + TypedQuery q = myEntityManager.createQuery("SELECT t FROM " + ResourceTable.class.getSimpleName() + " t WHERE t.myIndexStatus IS null", ResourceTable.class); + + int maxResult = 500; + if (theCount != null) { + maxResult = Math.min(theCount, 2000); + } + + q.setMaxResults(maxResult); + List resources = q.getResultList(); + + ourLog.info("Indexing {} resources", resources.size()); + + int count = 0; + long start = System.currentTimeMillis(); + + for (ResourceTable resourceTable : resources) { + final IBaseResource resource; + try { + resource = toResource(resourceTable); + } catch (DataFormatException e) { + ourLog.warn("Failure parsing resource: {}", e.toString()); + throw new UnprocessableEntityException(Long.toString(resourceTable.getId())); + } + @SuppressWarnings("rawtypes") + final IFhirResourceDao dao = getDao(resource.getClass()); + if (dao == null) { + ourLog.warn("No DAO for type: {}", resource.getClass()); + throw new UnprocessableEntityException(Long.toString(resourceTable.getId())); + } + + if (resource.getIdElement().isIdPartValid() == false) { + ourLog.warn("Not going to try and index an invalid ID: {}", resource.getIdElement()); + throw new UnprocessableEntityException(Long.toString(resourceTable.getId())); + } + + try { + dao.update(resource, null, true); + } catch (Exception e) { + ourLog.error("Failed to index resource {}: {}", new Object[] { resource.getIdElement(), e.toString() }); + throw new UnprocessableEntityException(Long.toString(resourceTable.getId())); + } + count++; + } + + long delay = System.currentTimeMillis() - start; + ourLog.info("Indexed {} / {} resources in {}ms", new Object[] { count, resources.size(), delay }); + + return resources.size(); + } + }); + } + @Override public TagList getAllTags() { // Notify interceptors @@ -132,85 +192,31 @@ public abstract class BaseHapiFhirSystemDao extends BaseHapiFhirDao() { @Override public Void doInTransaction(TransactionStatus theStatus) { + ourLog.info("Marking resource with PID {} as indexing_failed", new Object[] { theId }); Query q = myEntityManager.createQuery("UPDATE ResourceTable t SET t.myIndexStatus = :status WHERE t.myId = :id"); q.setParameter("status", INDEX_STATUS_INDEXING_FAILED); - q.setParameter("id", theResourceTable.getId()); + q.setParameter("id", theId); q.executeUpdate(); return null; } }); } - @SuppressWarnings("unchecked") @Override - @Transactional() - public int performReindexingPass(Integer theCount) { - TypedQuery q = myEntityManager.createQuery("SELECT t FROM " + ResourceTable.class.getSimpleName() + " t WHERE t.myIndexStatus IS null", ResourceTable.class); - - int maxResult = 500; - if (theCount != null) { - maxResult = Math.min(theCount, 2000); + @Transactional(propagation=Propagation.NOT_SUPPORTED) + public int performReindexingPass(final Integer theCount) { + try { + return doPerformReindexingPass(theCount); + } catch (UnprocessableEntityException e) { + markResourceAsIndexingFailed(Long.parseLong(e.getMessage())); + return -1; } - - q.setMaxResults(maxResult); - List resources = q.getResultList(); - - ourLog.info("Indexing {} resources", resources.size()); - - int count = 0; - long start = System.currentTimeMillis(); - - for (ResourceTable resourceTable : resources) { - final IBaseResource resource; - try { - resource = toResource(resourceTable); - } catch (DataFormatException e) { - ourLog.warn("Failure parsing resource: {}", e.toString()); - markResourceAsIndexingFailed(resourceTable); - continue; - } - @SuppressWarnings("rawtypes") - final IFhirResourceDao dao = getDao(resource.getClass()); - if (dao == null) { - ourLog.warn("No DAO for type: {}", resource.getClass()); - markResourceAsIndexingFailed(resourceTable); - continue; - } - - if (resource.getIdElement().isIdPartValid() == false) { - ourLog.warn("Not going to try and index an invalid ID: {}", resource.getIdElement()); - markResourceAsIndexingFailed(resourceTable); - continue; - } - - try { - TransactionTemplate txTemplate = new TransactionTemplate(myTxManager); - txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRES_NEW); - txTemplate.execute(new TransactionCallback() { - @Override - public Void doInTransaction(TransactionStatus theStatus) { - dao.update(resource, null, true); - return null; - } - }); - } catch (Exception e) { - ourLog.error("Failed to index resource {}: {}", new Object[] { resource.getIdElement(), e.toString() }); - markResourceAsIndexingFailed(resourceTable); - } - count++; - } - - long delay = System.currentTimeMillis() - start; - ourLog.info("Indexed {} / {} resources in {}ms", new Object[] { count, resources.size(), delay }); - - return resources.size(); } protected ResourceTable tryToLoadEntity(IdDt nextId) {