I have done a Groovy script that I run in a document with the admin account.
This Groovy script is supposed to delete some versions of the documents associated to each user.
I don’t understand why this script is sometime working well and sometime does nothing without any notifications of errors in the log.
The script :
{{groovy}}
import com.xpn.xwiki.criteria.impl.RevisionCriteria;
import com.xpn.xwiki.doc.XWikiDocumentArchive;
import com.xpn.xwiki.XWikiException;
import com.xpn.xwiki.XWikiContext;
import org.xwiki.model.EntityType;
import org.xwiki.model.reference.EntityReference;
import org.xwiki.model.reference.DocumentReference;
import org.suigeneris.jrcs.rcs.Version;
import org.xwiki.logging.LogLevel;
import org.xwiki.logging.LoggerManager;
import ch.qos.logback.classic.Level;
import java.util.Collection;
import java.text.NumberFormat;
def logger = services.logging.getLogger(doc.fullName);
logger.setLevel(Level.INFO);
Integer cptUsers = 0; // Nombre d'utilisateurs parcourus .
Integer cptRevisions = 0; // Nombre de révisions parcourues.
Integer cptRevisionsDeleted = 0; // Nombre de révisions supprimées.
String dateFormat1 = "yyyy/MM/dd HH:mm:ss";
// Nombre d'enregistement traité par lot
Integer countLimit = 100;
// Nombre d'enregistrement à passer pour le traitement
Integer offset = 0
Integer etape = 0;
Integer sousEtape = 0;
Integer sousEtapeTotal = 0;
// Identifiant de l'utilisateur dont on veut supprimer les versions
String userVersion = null;
Integer miseAJour = 0;
def parametre = request.getParameter("etape");
if (parametre != null) { etape = Integer.parseInt(parametre); }
parametre = request.getParameter("sousEtape");
if (parametre != null) { sousEtape = Integer.parseInt(parametre); }
parametre = request.getParameter("offset");
if (parametre != null) { offset = Integer.parseInt(parametre); }
parametre = request.getParameter("cptUsers");
if (parametre != null) { cptUsers = Integer.parseInt(parametre); }
parametre = request.getParameter("cptRevisions");
if (parametre != null) { cptRevisions = Integer.parseInt(parametre); }
parametre = request.getParameter("cptRevisionsDeleted");
if (parametre != null) { cptRevisionsDeleted = Integer.parseInt(parametre); }
parametre = request.getParameter("miseAJour");
if (parametre != null) { miseAJour = Integer.parseInt(parametre); }
parametre = request.getParameter("sousEtapeTotal");
if (parametre != null) { sousEtapeTotal = Integer.parseInt(parametre); }
if (etape == 0) {
String txt = "Niveau de trace pour '${logger.getName()}' : '${logger.getLevel()}'." + " (Groovy version : " + GroovySystem.getVersion() + ", Java version : " + System.getProperty("java.version") + ")";
println txt;
logger.info(txt);
Runtime runtime = Runtime.getRuntime();
NumberFormat format = NumberFormat.getInstance();
long maxMemory = runtime.maxMemory();
long allocatedMemory = runtime.totalMemory();
long freeMemory = runtime.freeMemory();
println "Mémoire disponible : " + format.format(freeMemory / (1024*1024)) + " Mo";
println "Mémoire allouées : " + format.format(allocatedMemory / (1024*1024)) + " Mo";
println "Mémoire maximum : " + format.format(maxMemory / (1024*1024)) + " Mo";
println "Mémoire totale disponible : " + format.format((freeMemory + (maxMemory - allocatedMemory)) / (1024*1024)) + " Mo";
println "Suppression de toutes les révisions (sauf la dernière) qui ont été effectuées par le user global 'build' ou 'admin' sur le profil de chaque utilisateur principal.";
logger.info("Suppression de toutes les révisions (sauf la dernière) qui ont été effectuées par le user global 'build' ou 'admin' sur le profil de chaque utilisateur principal.");
if (countLimit != 0) {
println "Traitement limité par paquet de ${countLimit} utilisateurs.";
}
}
logger.debug("Ligne 101");
switch (etape){
case 0:
userVersion = "XWiki.build";
break;
case 1:
userVersion = "XWiki.build";
break;
case 2:
userVersion = "XWiki.admin";
break;
default :
userVersion = null;
break;
}
// Cette classe permet de restreindre la liste des versions à seulement celle modifié par l'auteur userVersion
RevisionCriteria myRevisionCriteria = new RevisionCriteria();
myRevisionCriteria.setAuthor(userVersion);
def query = "select distinct doc.fullName from XWikiDocument as doc, BaseObject as obj, DBStringListProperty as prop join prop.list list where obj.name=doc.fullName and obj.className='XWiki.LDAPProfileClass' order by doc.fullName asc";
if ((etape == 1 || etape == 2) && sousEtape == 1) {
// Comptage du nombre total d'enregistrements
def counter = services.query.xwql(query).addFilter('count').execute().get(0);
if (counter != null){
cptUsers = counter;
sousEtapeTotal = cptUsers / countLimit;
if (cptUsers % countLimit ) {sousEtapeTotal = sousEtapeTotal + 1;}
}
println "Nombre d'utilisateurs trouvés : ${cptUsers}";
logger.info("Nombre d'utilisateurs trouvés : ${cptUsers}");
}
if (etape == 1 || etape == 2) {
def txt = "Etape ${etape}/2 sous-étape ${sousEtape}/${sousEtapeTotal} pour les versions créées par l'utilisateur '${userVersion}'";
if (miseAJour == 1) {
txt = txt + " en mise à jour.";
} else {
txt = txt + " en simulation.";
}
println txt;
logger.info(txt);
}
if (etape == 1 || etape == 2) {
def allDocs = services.query.xwql(query)
.setLimit(countLimit)
.setOffset(offset)
.execute();
if (allDocs.isEmpty()){
// Pas d'enregistrement trouvé
println "Il n'y a pas de profil utilisateur global trouvés.";
logger.info("Il n'y a pas de profil utilisateur global trouvés.");
} else {
for (item in allDocs) {
def aDoc = xwiki.getDocument(item)
def revisionTxt = ""
def maxRevision = ""
List<String> revisionList;
try {
revisionList = aDoc.getRevisions(myRevisionCriteria);
} catch (XWikiException e){
logger.error("Impossible d'obtenir les versions du document '${aDoc}'.");
}
def documentArchive = aDoc.getDocumentArchive();
if (revisionList.isEmpty()) {
logger.debug("Pour '${aDoc}' il n'y a pas de version créées par '${userVersion}'.");
} else {
println "===Document ${aDoc}==="
maxRevision = aDoc.version;
if (miseAJour == 0) {
println "La dernière version est la '${maxRevision}' et elle sera conservée.";
}
cptRevisions = cptRevisions + revisionList.size();
if (revisionList.size() > 1) {
if (miseAJour == 0){
revisionTxt = "Les versions suivantes seront supprimées : ";
} else {
revisionTxt = "Suppression des versions : "
}
for (revision in revisionList) {
if (revision != maxRevision) {
cptRevisionsDeleted = cptRevisionsDeleted + 1
def editedDoc = xwiki.getDocument(revision)
def rcsVersion = new Version(revision);
//def VersionToDelete aVersionToDelete = new VersionToDelete(documentArchive, rcsVersion)
if (miseAJour == 1 ){
//aVersionToDelete.remove(xcontext.context);
try {
documentArchive.removeVersions(rcsVersion, rcsVersion, xcontext.context);
} catch (XWikiException e){
logger.error("Impossible de supprimer la version '${rcsVersion}' du document '${aDoc}'. Exception '${e}'");
}
}
revisionTxt = revisionTxt + "${revision},";
}
}
println revisionTxt;
logger.info("Document ${aDoc}. "+ revisionTxt);
}
}
}
if (miseAJour == 1 ){
println "Nombre cumulé de versions supprimées : ${cptRevisionsDeleted} sur ${cptRevisions}";
} else {
println "Nombre cumulé de versions à supprimer : ${cptRevisionsDeleted} sur ${cptRevisions}";
}
}
}
if (etape == 1 || etape == 2 ){
offset = offset + countLimit;
sousEtape = sousEtape + 1;
if ((sousEtape > sousEtapeTotal) && etape == 1) {
offset = 0;
etape = 2;
sousEtape = 1;
sousEtapeTotal = 0;
}
if (sousEtape <= sousEtapeTotal || sousEtapeTotal == 0) {
String nextStep = "Prochaine étape: ${etape}/2 sous-étape ${sousEtape}/${sousEtapeTotal} (offset ${offset}/${cptUsers})";
if (miseAJour == 1) {
nextStep = nextStep + " en mise à jour.";
} else {
nextStep = nextStep + " en simulation.";
}
println nextStep;
logger.info(nextStep);
}
else {
println ""
println "Fin du traitement atteinte."
logger.info("Fin du traitement atteinte.");
println "Nombre de versions à supprimer ou supprrimés : ${cptRevisionsDeleted} sur ${cptRevisions} parcourues";
logger.info("Nombre de versions à supprimer ou supprrimés : ${cptRevisionsDeleted} sur ${cptRevisions} parcourues");
}
}
if (etape == 0){
println ""
println "{{html clean='false' wiki='false'}}";
println "<form><div class='buttonwrapper'><input class='button' type='submit' name='preview' value='Effectuer la suppression' /></div>";
println "<input type='hidden' name='etape' value='1'/>";
println "<input type='hidden' name='sousEtape' value='1'/>";
println "<input type='hidden' name='sousEtapeTotal' value='" + sousEtapeTotal + "'/>";
println "<input type='hidden' name='cptUsers' value='" + cptUsers + "' />";
println "<input type='hidden' name='cptRevisions' value='" + cptRevisions + "'/>";
println "<input type='hidden' name='cptRevisionsDeleted' value='" + cptRevisionsDeleted + "'/>";
println "<input type='hidden' name='offset' value='" + offset + "'/>";
println "<input type='hidden' name='miseAJour' value='1' /></form>";
println ""
println "<form><div class='buttonwrapper'><input class='button' type='submit' name='preview' value='Simuler la suppression' /></div>";
println "<input type='hidden' name='etape' value='1' />";
println "<input type='hidden' name='sousEtape' value='1' />";
println "<input type='hidden' name='sousEtapeTotal' value='" + sousEtapeTotal + "'/>";
println "<input type='hidden' name='cptUsers' value='" + cptUsers + "'/>";
println "<input type='hidden' name='cptRevisions' value='" + cptRevisions + "'/>";
println "<input type='hidden' name='cptRevisionsDeleted' value='" + cptRevisionsDeleted + "'/>";
println "<input type='hidden' name='offset' value='" + offset + "'/>";
println "<input type='hidden' name='miseAJour' value='0' /></form>";
println "{{/html}}";
}
// Bouton continuer
if ((sousEtape <= sousEtapeTotal || sousEtapeTotal == 0) && (etape == 1 || etape == 2)) {
println ""
println "{{html clean='false' wiki='false'}}";
println "<form><div class='buttonwrapper'><input class='button' type='submit' name='preview' value='Continuer' /></div>";
println "<input type='hidden' name='etape' value='" + etape + "'/>";
println "<input type='hidden' name='sousEtape' value='" + sousEtape + "'/>";
println "<input type='hidden' name='sousEtapeTotal' value='" + sousEtapeTotal + "'/>";
println "<input type='hidden' name='cptUsers' value='" + cptUsers + "'/>";
println "<input type='hidden' name='cptRevisions' value='" + cptRevisions + "'/>";
println "<input type='hidden' name='cptRevisionsDeleted' value='" + cptRevisionsDeleted + "'/>";
println "<input type='hidden' name='offset' value='" + offset + "'/>";
println "<input type='hidden' name='miseAJour' value='" + miseAJour + "'/></form>";
println "{{/html}}";
}
// Bouton Annuler
println " "
println "{{html clean='false' wiki='false'}}";
println "<form><div class='buttonwrapper'><input class='button' type='submit' name='preview' value='Re-initialiser le traitement'/></div>";
println "<input type='hidden' name='etape' value='0'/>";
println "<input type='hidden' name='sousEtape' value='0'/>";
println "<input type='hidden' name='sousEtapeTotal' value='0'/>";
println "<input type='hidden' name='cptUsers' value='0'/>";
println "<input type='hidden' name='cptRevisions' value='0'/>";
println "<input type='hidden' name='cptRevisionsDeleted' value='0'/>";
println "<input type='hidden' name='offset' value='0'/>";
println "<input type='hidden' name='miseAJour' value='0' /></form>";
println "{{/html}}";
logger.debug("Ligne 319 - Fin du script.");
{{/groovy}}
It looks like the method removeVersions(org.suigeneris.jrcs.rcs.Version newerVersion, org.suigeneris.jrcs.rcs.Version olderVersion, XWikiContext context)
of the class XWikiDocumentArchive was not always working…
There is no error in the log.
The version of XWiki is 9.10.1 and is running in docker. The database is PostgreSQL.
Thanks.