fix(event_file): use for_type/for_id for hosted_file_link deletion
hosted_file_link is created against the parent object (e.g. event_presenter), not against event_file itself. The delete endpoint was passing link_to_type= 'event_file', finding 0 rows, and bailing before the orphan cleanup ran. Fix: read for_type + for_id from the event_file row and use those for link deletion. Also inline the orphan cleanup so a missing link (old orphan from the pre-fix period) is treated as a non-fatal warning rather than a hard failure — cleanup proceeds regardless. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -14,7 +14,7 @@ from app.config import settings
|
|||||||
from app.db_sql import redis_lookup_id_random, sql_select, sql_update, sql_delete, get_id_random
|
from app.db_sql import redis_lookup_id_random, sql_select, sql_update, sql_delete, get_id_random
|
||||||
from app.methods.hosted_file_methods import (
|
from app.methods.hosted_file_methods import (
|
||||||
create_hosted_file_obj, load_hosted_file_obj, save_file,
|
create_hosted_file_obj, load_hosted_file_obj, save_file,
|
||||||
create_hosted_file_link, delete_hosted_file_link, handle_delete_hosted_file
|
create_hosted_file_link, delete_hosted_file_link, get_hosted_file_link_rec_list
|
||||||
)
|
)
|
||||||
from app.methods.event_file_methods import create_event_file_obj, load_event_file_obj
|
from app.methods.event_file_methods import create_event_file_obj, load_event_file_obj
|
||||||
from app.lib_general_v3 import (
|
from app.lib_general_v3 import (
|
||||||
@@ -296,26 +296,63 @@ async def delete_event_file_action(
|
|||||||
if not ef_id_int:
|
if not ef_id_int:
|
||||||
raise HTTPException(status_code=404, detail="Event file not found.")
|
raise HTTPException(status_code=404, detail="Event file not found.")
|
||||||
|
|
||||||
ef_rec = sql_select(sql="SELECT hosted_file_id FROM event_file WHERE id = :id", data={'id': ef_id_int})
|
# Fetch hosted_file_id + the parent the link was originally created against.
|
||||||
|
# hosted_file_link uses for_type/for_id as link target, NOT 'event_file'.
|
||||||
|
ef_rec = sql_select(
|
||||||
|
sql="SELECT hosted_file_id, for_type, for_id FROM event_file WHERE id = :id",
|
||||||
|
data={'id': ef_id_int}
|
||||||
|
)
|
||||||
hf_id_int = ef_rec.get('hosted_file_id') if ef_rec else None
|
hf_id_int = ef_rec.get('hosted_file_id') if ef_rec else None
|
||||||
|
for_type = ef_rec.get('for_type') if ef_rec else None
|
||||||
|
for_id_int = ef_rec.get('for_id') if ef_rec else None
|
||||||
|
|
||||||
link_cleaned = False
|
link_cleaned = False
|
||||||
if hf_id_int:
|
orphan_cleaned = False
|
||||||
link_cleaned = handle_delete_hosted_file(
|
|
||||||
account_id=account.account_id,
|
|
||||||
hosted_file_id=hf_id_int,
|
|
||||||
link_to_type='event_file',
|
|
||||||
link_to_id=ef_id_int,
|
|
||||||
rm_orphan=rm_orphan,
|
|
||||||
)
|
|
||||||
if not link_cleaned:
|
|
||||||
log.warning(f"handle_delete_hosted_file returned False for hosted_file {hf_id_int} / event_file {ef_id_int}")
|
|
||||||
|
|
||||||
|
if hf_id_int:
|
||||||
|
# Step 1: Remove the hosted_file_link using the correct parent type/id.
|
||||||
|
# A missing link (old orphan from pre-fix period) is non-fatal — log and continue.
|
||||||
|
if for_type and for_id_int:
|
||||||
|
link_result = delete_hosted_file_link(
|
||||||
|
account_id=account.account_id,
|
||||||
|
hosted_file_id=hf_id_int,
|
||||||
|
link_to_type=for_type,
|
||||||
|
link_to_id=for_id_int,
|
||||||
|
)
|
||||||
|
if link_result:
|
||||||
|
link_cleaned = True
|
||||||
|
else:
|
||||||
|
log.warning(f"hosted_file_link not found (already removed or never created): hosted_file={hf_id_int} {for_type}:{for_id_int}")
|
||||||
|
|
||||||
|
# Step 2: Orphan check — clean up physical file + hosted_file record if no links remain.
|
||||||
|
if rm_orphan:
|
||||||
|
remaining = get_hosted_file_link_rec_list(hosted_file_id=hf_id_int)
|
||||||
|
if not remaining:
|
||||||
|
hf_obj = load_hosted_file_obj(hosted_file_id=hf_id_int)
|
||||||
|
if hf_obj:
|
||||||
|
file_path = os.path.join(
|
||||||
|
settings.FILES_PATH['hosted_files_root'],
|
||||||
|
hf_obj.subdirectory_path or '',
|
||||||
|
f'{hf_obj.hash_sha256}.file'
|
||||||
|
)
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
try:
|
||||||
|
pathlib.Path(file_path).unlink()
|
||||||
|
log.info(f"Deleted physical file: {file_path}")
|
||||||
|
except OSError as e:
|
||||||
|
log.error(f"Failed to delete physical file {file_path}: {e}")
|
||||||
|
else:
|
||||||
|
log.warning(f"Physical file already absent from disk: {file_path}")
|
||||||
|
sql_delete(table_name='hosted_file', record_id=hf_id_int)
|
||||||
|
orphan_cleaned = True
|
||||||
|
|
||||||
|
# Step 3: Always remove the event_file row.
|
||||||
sql_delete(table_name='event_file', record_id=ef_id_int)
|
sql_delete(table_name='event_file', record_id=ef_id_int)
|
||||||
|
|
||||||
return mk_resp(data={
|
return mk_resp(data={
|
||||||
'event_file_deleted': True,
|
'event_file_deleted': True,
|
||||||
'hosted_file_link_cleaned': bool(link_cleaned),
|
'hosted_file_link_cleaned': link_cleaned,
|
||||||
|
'orphan_cleaned': orphan_cleaned,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user