fix(db): upsert_node Race-Condition behoben (UNIQUE constraint)
INSERT OR IGNORE + UPDATE statt SELECT → INSERT eliminiert den UNIQUE-constraint-Fehler bei konkurrierenden async-Aufrufen. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
fd9eb99b6a
commit
b431797d32
|
|
@ -1,5 +1,12 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.08.20] - 2026-02-20
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- **`upsert_node` Race-Condition** (`UNIQUE constraint failed: nodes.node_id`):
|
||||||
|
Statt SELECT → INSERT nutzt die Methode jetzt `INSERT OR IGNORE` + `UPDATE`,
|
||||||
|
wodurch konkurrierende Aufrufe keinen Constraint-Fehler mehr auslösen.
|
||||||
|
|
||||||
## [0.08.19] - 2026-02-20
|
## [0.08.19] - 2026-02-20
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
version: "0.08.19"
|
version: "0.08.20"
|
||||||
|
|
||||||
bot:
|
bot:
|
||||||
name: "MeshDD-Bot"
|
name: "MeshDD-Bot"
|
||||||
|
|
|
||||||
|
|
@ -129,29 +129,19 @@ class Database:
|
||||||
|
|
||||||
async def upsert_node(self, node_id: str, **kwargs) -> dict:
|
async def upsert_node(self, node_id: str, **kwargs) -> dict:
|
||||||
now = time.time()
|
now = time.time()
|
||||||
existing = await self.get_node(node_id)
|
# Row anlegen falls nicht vorhanden (first_seen nur beim ersten Mal gesetzt)
|
||||||
|
await self.db.execute(
|
||||||
if existing:
|
"INSERT OR IGNORE INTO nodes (node_id, first_seen, last_seen) VALUES (?, ?, ?)",
|
||||||
updates = {k: v for k, v in kwargs.items() if v is not None}
|
(node_id, now, now),
|
||||||
if not updates:
|
)
|
||||||
return dict(existing)
|
# Nicht-None-Felder + last_seen immer aktualisieren
|
||||||
updates["last_seen"] = now
|
updates = {k: v for k, v in kwargs.items() if v is not None}
|
||||||
set_clause = ", ".join(f"{k} = ?" for k in updates)
|
updates["last_seen"] = now
|
||||||
values = list(updates.values()) + [node_id]
|
set_clause = ", ".join(f"{k} = ?" for k in updates)
|
||||||
await self.db.execute(
|
values = list(updates.values()) + [node_id]
|
||||||
f"UPDATE nodes SET {set_clause} WHERE node_id = ?", values
|
await self.db.execute(
|
||||||
)
|
f"UPDATE nodes SET {set_clause} WHERE node_id = ?", values
|
||||||
else:
|
)
|
||||||
kwargs["node_id"] = node_id
|
|
||||||
kwargs.setdefault("first_seen", now)
|
|
||||||
kwargs["last_seen"] = now
|
|
||||||
cols = ", ".join(kwargs.keys())
|
|
||||||
placeholders = ", ".join("?" for _ in kwargs)
|
|
||||||
await self.db.execute(
|
|
||||||
f"INSERT INTO nodes ({cols}) VALUES ({placeholders})",
|
|
||||||
list(kwargs.values()),
|
|
||||||
)
|
|
||||||
|
|
||||||
await self.db.commit()
|
await self.db.commit()
|
||||||
return dict(await self.get_node(node_id))
|
return dict(await self.get_node(node_id))
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue