fix: improve JiraService pagination and cleanup logic
- Updated pagination logging to include total issues retrieved. - Increased safety limit for pagination from 5000 to 10000 tickets to prevent infinite loops. - Removed deprecated cleanupEpics method to streamline synchronization process. - Added check for actual changes before updating tasks to avoid unnecessary database operations.
This commit is contained in:
@@ -94,15 +94,17 @@ export class JiraService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
allIssues.push(...data.issues);
|
allIssues.push(...data.issues);
|
||||||
console.log(`✅ ${data.issues.length} tickets récupérés (total: ${allIssues.length})`);
|
console.log(`✅ ${data.issues.length} tickets récupérés (total: ${allIssues.length}/${data.total || '?'})`);
|
||||||
|
|
||||||
// Vérifier s'il y a plus de pages
|
// Vérifier s'il y a plus de pages
|
||||||
hasMorePages = data.issues.length === maxResults && allIssues.length < (data.total || Number.MAX_SAFE_INTEGER);
|
hasMorePages = data.issues.length === maxResults && allIssues.length < (data.total || Number.MAX_SAFE_INTEGER);
|
||||||
startAt += maxResults;
|
startAt += maxResults;
|
||||||
|
|
||||||
// Sécurité: éviter les boucles infinies
|
console.log(`📊 Pagination: hasMorePages=${hasMorePages}, startAt=${startAt}, maxResults=${maxResults}`);
|
||||||
if (allIssues.length > 5000) {
|
|
||||||
console.warn('⚠️ Limite de sécurité atteinte (5000 tickets). Arrêt de la pagination.');
|
// Sécurité: éviter les boucles infinies (augmenté avec la nouvelle taille de page)
|
||||||
|
if (allIssues.length > 10000) {
|
||||||
|
console.warn('⚠️ Limite de sécurité atteinte (10000 tickets). Arrêt de la pagination.');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,61 +147,6 @@ export class JiraService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Nettoie les epics Jira de la base (ne doivent plus être synchronisés)
|
|
||||||
*/
|
|
||||||
async cleanupEpics(): Promise<number> {
|
|
||||||
try {
|
|
||||||
console.log('🧹 Nettoyage des epics Jira...');
|
|
||||||
|
|
||||||
// D'abord, listons toutes les tâches Jira pour voir lesquelles sont des epics
|
|
||||||
const allJiraTasks = await prisma.task.findMany({
|
|
||||||
where: { source: 'jira' }
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`🔍 ${allJiraTasks.length} tâches Jira trouvées:`);
|
|
||||||
allJiraTasks.forEach(task => {
|
|
||||||
// @ts-expect-error - jiraType existe mais n'est pas encore dans les types générés
|
|
||||||
console.log(` - ${task.jiraKey}: "${task.title}" [${task.jiraType || 'N/A'}] (ID: ${task.id})`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Trouver les tâches Jira qui sont des epics
|
|
||||||
// Maintenant on peut utiliser le type Jira mappé directement !
|
|
||||||
const epicsToDelete = await prisma.task.findMany({
|
|
||||||
where: {
|
|
||||||
source: 'jira',
|
|
||||||
// @ts-expect-error - jiraType existe mais n'est pas encore dans les types générés
|
|
||||||
jiraType: 'Epic' // Maintenant standardisé grâce au mapping
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (epicsToDelete.length > 0) {
|
|
||||||
// Supprimer les relations de tags d'abord
|
|
||||||
await prisma.taskTag.deleteMany({
|
|
||||||
where: {
|
|
||||||
taskId: { in: epicsToDelete.map(task => task.id) }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Supprimer les tâches epics
|
|
||||||
const result = await prisma.task.deleteMany({
|
|
||||||
where: {
|
|
||||||
id: { in: epicsToDelete.map(task => task.id) }
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`✅ ${result.count} epics supprimés de la base`);
|
|
||||||
return result.count;
|
|
||||||
} else {
|
|
||||||
console.log('✅ Aucun epic trouvé à nettoyer');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Erreur lors du nettoyage des epics:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronise les tickets Jira avec la base locale
|
* Synchronise les tickets Jira avec la base locale
|
||||||
*/
|
*/
|
||||||
@@ -216,9 +163,6 @@ export class JiraService {
|
|||||||
try {
|
try {
|
||||||
console.log('🔄 Début de la synchronisation Jira...');
|
console.log('🔄 Début de la synchronisation Jira...');
|
||||||
|
|
||||||
// Nettoyer les epics existants (une seule fois)
|
|
||||||
await this.cleanupEpics();
|
|
||||||
|
|
||||||
// S'assurer que le tag "From Jira" existe
|
// S'assurer que le tag "From Jira" existe
|
||||||
await this.ensureJiraTagExists();
|
await this.ensureJiraTagExists();
|
||||||
|
|
||||||
@@ -317,6 +261,29 @@ export class JiraService {
|
|||||||
return 'skipped';
|
return 'skipped';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Vérifier s'il y a vraiment des changements
|
||||||
|
const hasChanges =
|
||||||
|
existingTask.title !== taskData.title ||
|
||||||
|
existingTask.description !== taskData.description ||
|
||||||
|
existingTask.status !== taskData.status ||
|
||||||
|
existingTask.priority !== taskData.priority ||
|
||||||
|
(existingTask.dueDate?.getTime() || null) !== (taskData.dueDate?.getTime() || null) ||
|
||||||
|
existingTask.jiraProject !== taskData.jiraProject ||
|
||||||
|
existingTask.jiraKey !== taskData.jiraKey ||
|
||||||
|
// @ts-expect-error - jiraType existe mais n'est pas encore dans les types générés
|
||||||
|
existingTask.jiraType !== taskData.jiraType ||
|
||||||
|
existingTask.assignee !== taskData.assignee;
|
||||||
|
|
||||||
|
if (!hasChanges) {
|
||||||
|
console.log(`⏭️ Aucun changement pour ${jiraTask.key}, skip mise à jour`);
|
||||||
|
|
||||||
|
// S'assurer que les tags Jira sont assignés (pour les anciennes tâches) même en skip
|
||||||
|
await this.assignJiraTag(existingTask.id);
|
||||||
|
await this.assignProjectTag(existingTask.id, jiraTask.project.key);
|
||||||
|
|
||||||
|
return 'skipped';
|
||||||
|
}
|
||||||
|
|
||||||
// Mettre à jour seulement les champs Jira (pas les modifs locales)
|
// Mettre à jour seulement les champs Jira (pas les modifs locales)
|
||||||
await prisma.task.update({
|
await prisma.task.update({
|
||||||
where: { id: existingTask.id },
|
where: { id: existingTask.id },
|
||||||
@@ -331,7 +298,7 @@ export class JiraService {
|
|||||||
// @ts-expect-error - jiraType existe mais n'est pas encore dans les types générés
|
// @ts-expect-error - jiraType existe mais n'est pas encore dans les types générés
|
||||||
jiraType: taskData.jiraType,
|
jiraType: taskData.jiraType,
|
||||||
assignee: taskData.assignee,
|
assignee: taskData.assignee,
|
||||||
updatedAt: taskData.updatedAt
|
updatedAt: taskData.updatedAt // Seulement si changements réels
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user