001/* 002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.storage.sql; 020 021import java.util.Calendar; 022 023import org.apache.commons.logging.Log; 024import org.apache.commons.logging.LogFactory; 025import org.nuxeo.ecm.core.event.Event; 026import org.nuxeo.ecm.core.event.EventListener; 027import org.nuxeo.ecm.core.repository.RepositoryService; 028import org.nuxeo.ecm.core.storage.sql.coremodel.SQLRepositoryService; 029import org.nuxeo.runtime.api.Framework; 030 031/** 032 * Sync listener that calls the soft delete cleanup method of the repositories. Designed to be called periodically. 033 * 034 * @since 5.7 035 */ 036public class SoftDeleteCleanupListener implements EventListener { 037 038 private static final Log log = LogFactory.getLog(SoftDeleteCleanupListener.class); 039 040 public static final int DEFAULT_MAX = 1000; 041 042 /** 043 * Property for the maximum number of documents to delete in one call. Zero means all the documents. Default is 044 * {@value #DEFAULT_MAX}. 045 */ 046 public static final String DEFAULT_MAX_PROP = "org.nuxeo.vcs.softdelete.cleanup.max"; 047 048 public static final int DEFAULT_DELAY = 5 * 60; // 5 min 049 050 /** 051 * Property for the minimum delay (in seconds) since when a document must have been soft-deleted before it can be 052 * hard-deleted. Zero means no delay. Default is {@value #DEFAULT_DELAY}. 053 */ 054 public static final String DEFAULT_DELAY_PROP = "org.nuxeo.vcs.softdelete.cleanup.age"; 055 056 /** 057 * Gets the maximum number of documents to delete in one call. Zero means all the documents. 058 */ 059 protected int getMax() { 060 String max = Framework.getProperty(DEFAULT_MAX_PROP); 061 if (max == null) { 062 return DEFAULT_MAX; 063 } 064 try { 065 return Integer.parseInt(max); 066 } catch (NumberFormatException e) { 067 log.error("Invalid property " + DEFAULT_MAX_PROP, e); 068 return DEFAULT_MAX; 069 } 070 } 071 072 /** 073 * Gets the minimum delay (in seconds) since when a document must have been soft-deleted before it can be 074 * hard-deleted. Zero means no delay. 075 */ 076 protected int getDelaySeconds() { 077 String delay = Framework.getProperty(DEFAULT_DELAY_PROP); 078 if (delay == null) { 079 return DEFAULT_DELAY; 080 } 081 try { 082 return Integer.parseInt(delay); 083 } catch (NumberFormatException e) { 084 log.error("Invalid property " + DEFAULT_DELAY_PROP, e); 085 return DEFAULT_DELAY; 086 } 087 } 088 089 @Override 090 public void handleEvent(Event event) { 091 RepositoryService repositoryService = Framework.getService(RepositoryService.class); 092 if (repositoryService == null) { 093 // RepositoryService failed to start, no need to go further 094 return; 095 } 096 int max = getMax(); 097 int delay = getDelaySeconds(); 098 Calendar beforeTime; 099 if (delay <= 0) { 100 beforeTime = null; 101 } else { 102 beforeTime = Calendar.getInstance(); 103 beforeTime.add(Calendar.SECOND, -delay); 104 } 105 SQLRepositoryService sqlRepositoryService = Framework.getService(SQLRepositoryService.class); 106 for (RepositoryManagement repoMgmt : sqlRepositoryService.getRepositories()) { 107 log.debug("Calling repository soft-delete cleanup for repository: " + repoMgmt.getName() + ", max=" + max 108 + ", beforeTimeDelay=" + delay); 109 int n = repoMgmt.cleanupDeletedDocuments(max, beforeTime); 110 log.debug("Number of documents deleted: " + n); 111 } 112 } 113 114}