Uploaded image for project: 'OpenOLAT'
  1. OpenOLAT
  2. OO-5401

Repo lifecycle: making auto deletion more robust against exceptions

    XMLWordPrintable

    Details

    • Type: Improvement
    • Status: Closed
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: 15.4.4
    • Fix Version/s: 15.3.14, 15.4.6
    • Component/s: None
    • Labels:
      None

      Description

      The automatic deletion of repository entries from trash stops when an error occurs, in our case it was this one (fixed in OO-5405):

      [schedulerFactoryBean_Worker-5] ERROR  SqlExceptionHelper ^%^ I-J1718 ^%^ org.hibernate.engine.jdbc.spi.SqlExceptionHelper ^%^  ^%^  ^%^  ^%^  ^%^ FEHLER: Aktualisieren oder Löschen in Tabelle »o_pf_binder« verletzt Fremdschlüssel-Constraint »pf_assign_binder_idx« von Tabelle »o_pf_assignment«
        Detail: Auf Schlüssel (id)=(2621) wird noch aus Tabelle »o_pf_assignment« verwiesen.
      2021-04-14 05:45:42.257 [schedulerFactoryBean_Worker-5] ERROR  AutomaticLifecycleService ^%^ I-J1719 ^%^ org.olat.repository.manager.AutomaticLifecycleService ^%^  ^%^  ^%^  ^%^  ^%^ javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement 	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154) 	at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) 	at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1681) 	at org.olat.modules.portfolio.manager.BinderDAO.deleteBinderTemplate(BinderDAO.java:493) 	at org.olat.modules.portfolio.manager.PortfolioServiceImpl.deleteBinderTemplate(PortfolioServiceImpl.java:319) 	at org.olat.modules.portfolio.handler.BinderTemplateHandler.cleanupOnDelete(BinderTemplateHandler.java:225) 	at org.olat.repository.manager.RepositoryServiceImpl.deletePermanently(RepositoryServiceImpl.java:558) 	at org.olat.repository.manager.AutomaticLifecycleService.definitivelyDelete(AutomaticLifecycleService.java:154) 	at org.olat.repository.manager.AutomaticLifecycleService.definitivelyDelete(AutomaticLifecycleService.java:133) 	at org.olat.repository.manager.AutomaticLifecycleService.manage(AutomaticLifecycleService.java:76) 	at org.olat.repository.manager.AutomaticLifecycleJob.executeWithDB(AutomaticLifecycleJob.java:45) 	at org.olat.core.commons.services.scheduler.JobWithDB.executeInternal(JobWithDB.java:59)
      

      To avoid that I inserted a try-catch-block and write the exception message to olat.log. Also I moved the info about the deletion after the check for references. It's confusing when you read in the logs that a repository entry is being definitly deleted but nothing happens.

      diff --git a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
      index bf396e4..8ccae0b 100644
      --- a/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
      +++ b/src/main/java/org/olat/repository/manager/RepositoryServiceImpl.java
      @@ -511,69 +511,75 @@
       			return errors;
       		}
       
      -		log.info(Tracing.M_AUDIT, "deleteRepositoryEntry after load entry={}", entry);
       		RepositoryHandler handler = repositoryHandlerFactory.getRepositoryHandler(entry);
       		OLATResource resource = entry.getOlatResource();
       		//delete old context
       		if (handler != null && !handler.readyToDelete(entry, identity, roles, locale, errors)) {
      +			log.info(Tracing.M_AUDIT, "deleteRepositoryEntry aborted: references detected for entry={}", entry);
       			return errors;
       		}
       
      -		userCourseInformationsManager.deleteUserCourseInformations(entry);
      -		certificatesManager.deleteRepositoryEntry(entry);
      +		log.info(Tracing.M_AUDIT, "deleteRepositoryEntry after load entry={}", entry);
      +		try {
      +			userCourseInformationsManager.deleteUserCourseInformations(entry);
      +			certificatesManager.deleteRepositoryEntry(entry);
       
      -		// delete all bookmarks referencing deleted entry
      -		CoreSpringFactory.getImpl(MarkManager.class).deleteMarks(entry);
      -		// delete all catalog entries referencing deleted entry
      -		catalogManager.resourceableDeleted(entry);
      -		// delete assessment modes
      -		assessmentModeDao.delete(entry);
      -		// delete reminders
      -		reminderDao.delete(entry);
      -		//delete reservations
      -		reservationDao.deleteReservations(resource);
      -		//delete references
      -		referenceManager.deleteAllReferencesOf(resource);
      -		//delete all pending tasks
      -		persistentTaskDao.delete(resource);
      -		dbInstance.commit();
      -		//delete lectures
      -		CoreSpringFactory.getImpl(LectureService.class).delete(entry);
      -		dbInstance.commit();
      -		//delete license
      -		CoreSpringFactory.getImpl(LicenseService.class).delete(resource);
      -		dbInstance.commit();
      -		//delete all consents
      -		CoreSpringFactory.getImpl(CourseDisclaimerManager.class).removeAllConsents(entry);
      -		//detach portfolio if there are some lost
      -		CoreSpringFactory.getImpl(PortfolioService.class).detachCourseFromBinders(entry);
      -		dbInstance.commit();
      -		//detach from curriculum
      -		CoreSpringFactory.getImpl(CurriculumService.class).removeRepositoryEntry(entry);
      -		dbInstance.commit();
      +			// delete all bookmarks referencing deleted entry
      +			CoreSpringFactory.getImpl(MarkManager.class).deleteMarks(entry);
      +			// delete all catalog entries referencing deleted entry
      +			catalogManager.resourceableDeleted(entry);
      +			// delete assessment modes
      +			assessmentModeDao.delete(entry);
      +			// delete reminders
      +			reminderDao.delete(entry);
      +			//delete reservations
      +			reservationDao.deleteReservations(resource);
      +			//delete references
      +			referenceManager.deleteAllReferencesOf(resource);
      +			//delete all pending tasks
      +			persistentTaskDao.delete(resource);
      +			dbInstance.commit();
      +			//delete lectures
      +			CoreSpringFactory.getImpl(LectureService.class).delete(entry);
      +			dbInstance.commit();
      +			//delete license
      +			CoreSpringFactory.getImpl(LicenseService.class).delete(resource);
      +			dbInstance.commit();
      +			//delete all consents
      +			CoreSpringFactory.getImpl(CourseDisclaimerManager.class).removeAllConsents(entry);
      +			//detach portfolio if there are some lost
      +			CoreSpringFactory.getImpl(PortfolioService.class).detachCourseFromBinders(entry);
      +			dbInstance.commit();
      +			//detach from curriculum
      +			CoreSpringFactory.getImpl(CurriculumService.class).removeRepositoryEntry(entry);
      +			dbInstance.commit();
       
      -		// inform handler to do any cleanup work... handler must delete the
      -		// referenced resourceable as well.
      -		if (handler != null) {
      -			handler.cleanupOnDelete(entry, resource);
      +			// inform handler to do any cleanup work... handler must delete the
      +			// referenced resourceable as well.
      +			if (handler != null) {
      +				handler.cleanupOnDelete(entry, resource);
      +			}
      +			dbInstance.commitAndCloseSession();
      +
      +			//delete all test sessions
      +			assessmentTestSessionDao.deleteAllUserTestSessionsByCourse(entry);
      +			dbInstance.commit();
      +			//nullify the reference
      +			assessmentEntryDao.removeEntryForReferenceEntry(entry);
      +			assessmentEntryDao.deleteEntryForRepositoryEntry(entry);
      +			dbInstance.commit();
      +			repositoryEntryToOrganisationDao.delete(entry);
      +			repositoryEntryToTaxonomyLevelDao.deleteRelation(entry);
      +			dbInstance.commit();
      +
      +			if(debug) log.debug("deleteRepositoryEntry after reload entry={}", entry);
      +			deleteRepositoryEntryAndBaseGroups(entry);
      +
      +			log.info(Tracing.M_AUDIT, "deleteRepositoryEntry Done");
      +		} catch (Exception e) {
      +			errors.setError(e.getMessage());
      +			log.info(Tracing.M_AUDIT, "deleteRepositoryEntry Error={}", e.getMessage());
       		}
      -		dbInstance.commitAndCloseSession();
      -
      -		//delete all test sessions
      -		assessmentTestSessionDao.deleteAllUserTestSessionsByCourse(entry);
      -		dbInstance.commit();
      -		//nullify the reference
      -		assessmentEntryDao.removeEntryForReferenceEntry(entry);
      -		assessmentEntryDao.deleteEntryForRepositoryEntry(entry);
      -		dbInstance.commit();
      -		repositoryEntryToOrganisationDao.delete(entry);
      -		repositoryEntryToTaxonomyLevelDao.deleteRelation(entry);
      -		dbInstance.commit();
      -
      -		if(debug) log.debug("deleteRepositoryEntry after reload entry={}", entry);
      -		deleteRepositoryEntryAndBaseGroups(entry);
      -
      -		log.info(Tracing.M_AUDIT, "deleteRepositoryEntry Done");
       		return errors;
       	}
       

      The next confusing thing are the mesages about closing/deleting courses. Not only courses are closed/deleted but also all repository entries. So I changed "course" to the resource type name:

      diff --git a/src/main/java/org/olat/repository/manager/AutomaticLifecycleService.java b/src/main/java/org/olat/repository/manager/AutomaticLifecycleService.java
      index 95538aa..0608a3a 100644
      --- a/src/main/java/org/olat/repository/manager/AutomaticLifecycleService.java
      +++ b/src/main/java/org/olat/repository/manager/AutomaticLifecycleService.java
      @@ -86,7 +86,7 @@
       				try {
       					boolean closeManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.close);
       					if(!closeManaged) {
      -						log.info(Tracing.M_AUDIT, "Automatic closing course: {} [{}]", entry.getDisplayname(), entry.getKey());
      +						log.info(Tracing.M_AUDIT, "Automatic closing {}: {} [{}]", entry.getResourceableTypeName(), entry.getDisplayname(), entry.getKey());
       						repositoryService.closeRepositoryEntry(entry, null, false);
       						dbInstance.commit();
       					}
      @@ -108,7 +108,7 @@
       				try {
       					boolean deleteManaged = RepositoryEntryManagedFlag.isManaged(entry, RepositoryEntryManagedFlag.delete);
       					if(!deleteManaged) {
      -						log.info(Tracing.M_AUDIT, "Automatic deleting (soft) course: {} [{}]", entry.getDisplayname(), entry.getKey() );
      +						log.info(Tracing.M_AUDIT, "Automatic deleting (soft) {}: {} [{}]", entry.getResourceableTypeName(), entry.getDisplayname(), entry.getKey() );
       						repositoryService.deleteSoftly(entry, null, true, false);
       						dbInstance.commit();
       					}
      @@ -150,7 +150,7 @@
       		if(administrator != null) {
       			Roles roles = securityManager.getRoles(administrator);
       			Locale locale = I18nManager.getInstance().getLocaleOrDefault(administrator.getUser().getPreferences().getLanguage());
      -			log.info(Tracing.M_AUDIT, "Automatic deleting (definitively) course: {} [{}]", entry.getDisplayname(), entry.getKey());
      +			log.info(Tracing.M_AUDIT, "Automatic deleting (definitively) {}: {} [{}]", entry.getResourceableTypeName(), entry.getDisplayname(), entry.getKey());
       			ErrorList errors = repositoryService.deletePermanently(entry, administrator, roles, locale);
       			deleted = !errors.hasErrors();
       		} else {
      
      

       

        Figma for Jira By 42nd

          Attachments

            Activity

              People

              Assignee:
              uhensler Urs Hensler
              Reporter:
              stephan Stephan Clemenz
              Tester:
              Mandy Menzel
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:

                  Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - 0 minutes
                  0m
                  Logged:
                  Time Spent - 30 minutes
                  30m