Felhő projekt létrehozásakor keletkett hiba javítása
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 6s

This commit is contained in:
2026-08-10 00:11:41 +02:00
parent 071f6c09ac
commit e2cedaf235
2 changed files with 39 additions and 30 deletions
+10
View File
@@ -1581,4 +1581,14 @@ class AppDatabase {
'Projekt helyi törlése: "$name" (id=$localProjectId) — a szerveren '
'már nem szerepel a tagsági listában (törölve vagy kikerültünk).');
}
/// Egy projekt aktuális szinkron-állapota — nyers oszlop-lekérdezés,
/// hogy a Project modellt ne kelljen ezért bővíteni.
Future<String?> getProjectSyncStatus(int id) async {
final db = await database;
final rows = await db.query('projects',
columns: ['sync_status'], where: 'id = ?', whereArgs: [id], limit: 1);
if (rows.isEmpty) return null;
return rows.first['sync_status'] as String?;
}
}
+29 -30
View File
@@ -103,39 +103,38 @@ class ProjectService extends GetxService {
});
throw ProjectRequiresLoginException();
}
// Felhős projektnél: AZONNALI, élő ellenőrzés — nem várjuk meg a
// háttér-reconcile 3 ciklusos türelmi idejét. Az azért van, hogy egy
// ÁTMENETI hálózati/RLS-hiccup ne váltson ki téves törlést — itt
// viszont egyetlen, konkrét projektet kérdezünk le frissen, ahol
// nincs ilyen bizonytalanság: a deleted_at vagy ki van töltve, vagy
// nincs. Egy már bizonyítottan törölt projekthez való csatlakozás
// komoly félreértések forrása lenne (adatrögzítés egy halott
// projektbe), ezt nem érdemes kockáztatni pár perc türelmi idő
// kedvéért.
if (!project.isLocalOnly) {
try {
final row = await Supabase.instance.client
.from('terepi_seged_projects')
.select('deleted_at')
.eq('id', project.uuid)
.maybeSingle()
.timeout(const Duration(seconds: 6));
// Az élő ellenőrzés CSAK olyan projektnél fusson, ami már egyszer
// BIZONYÍTOTTAN felkerült a szerverre (sync_status == 'synced').
// Egy ÉPP MOST létrehozott, még feltöltés alatt álló projektnél a
// szerveren természetesen még nem létezik a sor — ez NEM törlést
// jelent, csak azt, hogy a háttér-feltöltés még fut/nem futott le,
// és tévesen "törölve" hibát adna, ha itt is lefutna a check.
final syncStatus =
await AppDatabase.instance.getProjectSyncStatus(project.id!);
if (syncStatus == 'synced') {
try {
final row = await Supabase.instance.client
.from('terepi_seged_projects')
.select('deleted_at')
.eq('id', project.uuid)
.maybeSingle()
.timeout(const Duration(seconds: 6));
if (row == null || row['deleted_at'] != null) {
AppLogger.event('project_activate_blocked_deleted', '', {
'project_id': project.id,
'device_id': DeviceIdentityService.to.deviceId,
'device_name': DeviceIdentityService.to.deviceLabel.value,
'user_id': Supabase.instance.client.auth.currentUser?.id,
});
throw ProjectNoLongerExistsException();
if (row == null || row['deleted_at'] != null) {
AppLogger.event('project_activate_blocked_deleted', '', {
'project_id': project.id,
'device_id': DeviceIdentityService.to.deviceId,
'device_name': DeviceIdentityService.to.deviceLabel.value,
'user_id': Supabase.instance.client.auth.currentUser?.id,
});
throw ProjectNoLongerExistsException();
}
} on ProjectNoLongerExistsException {
rethrow;
} catch (_) {
// Hálózati hiba/időtúllépés → NEM blokkolunk emiatt (fail-open).
}
} on ProjectNoLongerExistsException {
rethrow;
} catch (_) {
// Hálózati hiba/időtúllépés → NEM blokkolunk emiatt (fail-open,
// offline-first elv) — ha tényleg törölve van, a háttér-reconcile
// úgyis elkapja hamarosan.
}
}