Fixed error portal insert
This commit is contained in:
parent
fbb6f61705
commit
e6db0f094c
1 changed files with 26 additions and 62 deletions
84
main.py
84
main.py
|
|
@ -1985,76 +1985,40 @@ async def ws_receive_snapshots(
|
||||||
ew = float(ew)
|
ew = float(ew)
|
||||||
z = float(z)
|
z = float(z)
|
||||||
|
|
||||||
# Round coordinates for comparison (0.1 tolerance to match DB constraint)
|
# Round coordinates for display (0.1 tolerance to match DB constraint)
|
||||||
ns_rounded = round(ns, 1)
|
ns_rounded = round(ns, 1)
|
||||||
ew_rounded = round(ew, 1)
|
ew_rounded = round(ew, 1)
|
||||||
|
|
||||||
# Check if portal exists at these coordinates
|
# Use PostgreSQL UPSERT to handle race conditions atomically
|
||||||
existing_portal = await database.fetch_one(
|
# This completely eliminates duplicate key errors
|
||||||
|
result = await database.fetch_one(
|
||||||
"""
|
"""
|
||||||
SELECT id FROM portals
|
INSERT INTO portals (portal_name, ns, ew, z, discovered_at, discovered_by)
|
||||||
WHERE ROUND(ns::numeric, 1) = :ns_rounded
|
VALUES (:portal_name, :ns, :ew, :z, :timestamp, :character_name)
|
||||||
AND ROUND(ew::numeric, 1) = :ew_rounded
|
ON CONFLICT (ROUND(ns::numeric, 1), ROUND(ew::numeric, 1))
|
||||||
LIMIT 1
|
DO UPDATE SET
|
||||||
|
discovered_at = EXCLUDED.discovered_at,
|
||||||
|
discovered_by = EXCLUDED.discovered_by,
|
||||||
|
portal_name = EXCLUDED.portal_name
|
||||||
|
RETURNING (xmax = 0) AS was_inserted
|
||||||
""",
|
""",
|
||||||
{
|
{
|
||||||
"ns_rounded": ns_rounded,
|
"portal_name": portal_name,
|
||||||
"ew_rounded": ew_rounded
|
"ns": ns,
|
||||||
|
"ew": ew,
|
||||||
|
"z": z,
|
||||||
|
"timestamp": timestamp,
|
||||||
|
"character_name": character_name
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if not existing_portal:
|
# Log whether this was a new discovery or an update
|
||||||
# Store new portal in database with ON CONFLICT handling
|
# xmax = 0 means it was an INSERT (new portal)
|
||||||
# This prevents race conditions and duplicate key errors
|
# xmax != 0 means it was an UPDATE (existing portal)
|
||||||
try:
|
if result and result["was_inserted"]:
|
||||||
await database.execute(
|
logger.info(f"New portal discovered: {portal_name} at {ns_rounded}, {ew_rounded} by {character_name}")
|
||||||
portals.insert().values(
|
|
||||||
portal_name=portal_name,
|
|
||||||
ns=ns,
|
|
||||||
ew=ew,
|
|
||||||
z=z,
|
|
||||||
discovered_at=timestamp,
|
|
||||||
discovered_by=character_name
|
|
||||||
)
|
|
||||||
)
|
|
||||||
logger.info(f"New portal discovered: {portal_name} at {ns_rounded}, {ew_rounded} by {character_name}")
|
|
||||||
except Exception as insert_error:
|
|
||||||
# If insert fails due to duplicate, update the existing portal
|
|
||||||
if "duplicate key" in str(insert_error).lower():
|
|
||||||
await database.execute(
|
|
||||||
"""
|
|
||||||
UPDATE portals
|
|
||||||
SET discovered_at = :timestamp, discovered_by = :character_name
|
|
||||||
WHERE ROUND(ns::numeric, 1) = :ns_rounded
|
|
||||||
AND ROUND(ew::numeric, 1) = :ew_rounded
|
|
||||||
""",
|
|
||||||
{
|
|
||||||
"timestamp": timestamp,
|
|
||||||
"character_name": character_name,
|
|
||||||
"ns_rounded": ns_rounded,
|
|
||||||
"ew_rounded": ew_rounded
|
|
||||||
}
|
|
||||||
)
|
|
||||||
logger.debug(f"Portal already exists (race condition), updated: {portal_name} at {ns_rounded}, {ew_rounded}")
|
|
||||||
else:
|
|
||||||
raise
|
|
||||||
else:
|
else:
|
||||||
# Update timestamp for existing portal to keep it alive
|
logger.debug(f"Portal timestamp updated: {portal_name} at {ns_rounded}, {ew_rounded} by {character_name}")
|
||||||
await database.execute(
|
|
||||||
"""
|
|
||||||
UPDATE portals
|
|
||||||
SET discovered_at = :timestamp, discovered_by = :character_name
|
|
||||||
WHERE ROUND(ns::numeric, 1) = :ns_rounded
|
|
||||||
AND ROUND(ew::numeric, 1) = :ew_rounded
|
|
||||||
""",
|
|
||||||
{
|
|
||||||
"timestamp": timestamp,
|
|
||||||
"character_name": character_name,
|
|
||||||
"ns_rounded": ns_rounded,
|
|
||||||
"ew_rounded": ew_rounded
|
|
||||||
}
|
|
||||||
)
|
|
||||||
logger.info(f"Portal timestamp updated: {portal_name} at {ns_rounded}, {ew_rounded} by {character_name}")
|
|
||||||
|
|
||||||
# Broadcast to browser clients for map updates
|
# Broadcast to browser clients for map updates
|
||||||
await _broadcast_to_browser_clients(data)
|
await _broadcast_to_browser_clients(data)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue