Я испытываю критическую проблему с моим приложением NextJS/Firebase, где приблизительно 40% случайных регистраций пользователей приводят к «Orphaned» пользователям - пользователи, которые существуют в аутентификации Firebase, но не соответствуют Firestor. Сообщения: < /p>
- Пользователи на 100% успешно созданы в аутентификации Firebase < /li>
Но приблизительно 40% попыток случайных регистраций не создают документ Firestore < /li>
Пользователи не вызывают этого процесса. Форма - Эти пользователи не могут получить одобренную регистрацию, одобренные с административной стороны, потому что наше приложение проверяет документы Firestore
здесь функция регистрации пользователя в outcontext.js :
// New user registration
const register = async (email, password, userData) => {
setErrorMessage('');
let user = null;
try {
setLoading(true);
// 1. Create user in Firebase Auth
const userCredential = await createUserWithEmailAndPassword(auth, email, password);
user = userCredential.user;
// 2. Create user document data
const userDocData = {
email: email,
name: userData.name || '',
surname: userData.surname || '',
phone: userData.phone || '',
role: userData.role || 'student',
status: 'pending',
createdAt: serverTimestamp(),
updatedAt: serverTimestamp(),
package: userData.role === 'student' ? {
remainingClasses: 0,
paymentStatus: false
} : null
};
// 3. Create document in Firestore
const batch = writeBatch(db);
batch.set(doc(db, 'users', user.uid), userDocData);
await batch.commit();
// 4. Verify document creation
const checkDoc = await getDoc(doc(db, 'users', user.uid));
if (!checkDoc.exists()) {
throw new Error('User document was not created');
}
// 5. Logout after successful registration
await signOut(auth);
return user;
} catch (error) {
// If Auth user created but Firestore document failed, delete Auth user
if (user) {
try {
// Try to delete any partially created document
try {
await deleteDoc(doc(db, 'users', user.uid));
} catch (docError) {
console.error("Error deleting document:", docError);
}
// Delete Auth user
await deleteUser(user);
} catch (deleteError) {
console.error('Error deleting user after failed registration:', deleteError);
}
}
// Handle specific errors
switch (error.code) {
case 'auth/email-already-in-use':
setErrorMessage('Αυτή η διεύθυνση email χρησιμοποιείται ήδη.');
break;
case 'auth/invalid-email':
setErrorMessage('Μη έγκυρη διεύθυνση email.');
break;
case 'auth/weak-password':
setErrorMessage('Ο κωδικός πρέπει να έχει τουλάχιστον 6 χαρακτήρες.');
break;
default:
setErrorMessage('Σφάλμα κατά την εγγραφή. Παρακαλώ δοκιμάστε ξανά.');
break;
}
throw error;
} finally {
setLoading(false);
}
};
< /code>
Я также попытался реализовать механизм повторной попытки с экспоненциальным отбором: < /p>
Код: Выделить всё
// 3. Create document with retry mechanism
let success = false;
let attempts = 0;
while (!success && attempts < 5) {
try {
attempts++;
console.log(`Attempt ${attempts} to create Firestore document`);
const batch = writeBatch(db);
batch.set(doc(db, 'users', user.uid), userDocData);
await batch.commit();
// Immediate verification
const checkDoc = await getDoc(doc(db, 'users', user.uid));
if (checkDoc.exists()) {
success = true;
console.log(`Successfully created Firestore document on attempt ${attempts}`);
} else {
console.warn(`Document check failed after batch commit (attempt ${attempts})`);
// Wait before retrying (exponential backoff)
await new Promise(resolve => setTimeout(resolve, 1000 * attempts));
}
} catch (error) {
console.error(`Firestore error on attempt ${attempts}:`, error);
// Wait before retrying
await new Promise(resolve => setTimeout(resolve, 1000 * attempts));
}
}
if (!success) {
throw new Error(`Failed to create Firestore document after ${attempts} attempts`);
}
Код: Выделить всё
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, async (user) => {
if (user) {
try {
// Check if document exists
const userDoc = await getDoc(doc(db, 'users', user.uid));
// If document doesn't exist, create it (fix orphaned users)
if (!userDoc.exists()) {
console.log("Orphaned user detected. Synchronizing...");
await setDoc(doc(db, 'users', user.uid), {
email: user.email,
name: '',
surname: '',
phone: '',
role: 'student',
status: 'pending',
createdAt: serverTimestamp(),
updatedAt: serverTimestamp(),
package: {
remainingClasses: 0,
paymentStatus: false
}
});
// Continue with normal checks...
}
} catch (error) {
console.error('Error fetching user data:', error);
setCurrentUser(null);
}
} else {
setCurrentUser(null);
}
setLoading(false);
});
return () => unsubscribe();
}, [auth, db, router]);
[*] Использование writebatch вместо setdoc - та же проблема возникает
Добавление механизма повторного повторного периода с до документов - все еще не провалит. /> Добавление надлежащей очистки для удаления пользователей аутентификации -осиротечной аутентификации < /li>
Добавление подробного журнала - без ошибок в журналах, когда возникает проблема < /li>
< /ol>
. /> Использование клиента sdk < /li>
Использование паттерна инициализации с экземпляром Singleton < /li>
< /ul>
Вопрос < /h2>
Что может вызвать это противоречивое поведение, когда пользователи авторов Firebase созданы, но документы Firestore не удастся ~ 40% из времени? Мне нужно надежное решение, так как это влияет на значительную часть наших пользовательских регистраций. Будет ли использование облачных функций Firebase для создания пользователей обеспечить лучшую надежность?
Подробнее здесь: https://stackoverflow.com/questions/797 ... -documents
Мобильная версия