fix problème possible de "logique delete + create pouvait créer des conditions de concurrence"

This commit is contained in:
Yannick Le Duc
2025-08-27 00:25:32 +02:00
parent ba3a7c3ea1
commit 8cfa14a693
7 changed files with 231 additions and 27 deletions

View File

@@ -36,6 +36,36 @@ function generateShortIdClient(): string {
return `${result}${timestamp}`;
}
// Fonction utilitaire pour gérer les erreurs Supabase
function handleSupabaseError(error: any, operation: string): never {
console.error(`Erreur Supabase lors de ${operation}:`, error);
// Extraire les détails de l'erreur
let errorMessage = `Erreur lors de ${operation}`;
if (error?.message) {
errorMessage = error.message;
} else if (error?.error_description) {
errorMessage = error.error_description;
} else if (error?.details) {
errorMessage = error.details;
} else if (typeof error === 'string') {
errorMessage = error;
}
// Ajouter des informations de débogage
const debugInfo = {
operation,
error,
timestamp: new Date().toISOString(),
userAgent: typeof window !== 'undefined' ? window.navigator.userAgent : 'server'
};
console.error('Informations de débogage:', debugInfo);
throw new Error(errorMessage);
}
// Services pour les campagnes
export const campaignService = {
async getAll(): Promise<Campaign[]> {
@@ -349,7 +379,7 @@ export const voteService = {
.eq('campaign_id', campaignId)
.eq('participant_id', participantId);
if (error) throw error;
if (error) handleSupabaseError(error, 'récupération des votes par participant');
return data || [];
},
@@ -359,7 +389,7 @@ export const voteService = {
.select('*')
.eq('proposition_id', propositionId);
if (error) throw error;
if (error) handleSupabaseError(error, 'récupération des votes par proposition');
return data || [];
},
@@ -371,7 +401,7 @@ export const voteService = {
.select()
.single();
if (error) throw error;
if (error) handleSupabaseError(error, 'création de vote');
return data;
},
@@ -384,7 +414,7 @@ export const voteService = {
.select()
.single();
if (error) throw error;
if (error) handleSupabaseError(error, 'mise à jour de vote');
return data;
},
@@ -395,7 +425,7 @@ export const voteService = {
.select()
.single();
if (error) throw error;
if (error) handleSupabaseError(error, 'upsert de vote');
return data;
},
@@ -405,7 +435,7 @@ export const voteService = {
.delete()
.eq('id', id);
if (error) throw error;
if (error) handleSupabaseError(error, 'suppression de vote');
},
async getByCampaign(campaignId: string): Promise<Vote[]> {
@@ -414,7 +444,7 @@ export const voteService = {
.select('*')
.eq('campaign_id', campaignId);
if (error) throw error;
if (error) handleSupabaseError(error, 'récupération des votes par campagne');
return data || [];
},
@@ -443,6 +473,22 @@ export const voteService = {
total_voted_amount: totalVotedAmount
};
});
},
// Méthode pour remplacer tous les votes d'un participant de manière atomique
async replaceVotes(
campaignId: string,
participantId: string,
votes: Array<{ proposition_id: string; amount: number }>
): Promise<void> {
// Utiliser une transaction pour garantir l'atomicité
const { error } = await supabase.rpc('replace_participant_votes', {
p_campaign_id: campaignId,
p_participant_id: participantId,
p_votes: votes
});
if (error) handleSupabaseError(error, 'remplacement des votes du participant');
}
};