fix: exclude account_id and virtual fields from archive_content DB writes

- Adds fields_to_exclude_from_db to Archive_Content_Base to prevent SQL errors on non-existent columns.
- Updates documentation for V3 Create/Update patterns and the x-ae-ignore-extra-fields header.
- Propagates account_id_random to hosted file and media processing methods.
This commit is contained in:
Scott Idem
2026-02-24 11:30:17 -05:00
parent 719ca5240b
commit 9d89d4c8e4
6 changed files with 45 additions and 1 deletions

View File

@@ -272,6 +272,8 @@ async def save_file(
file_info: dict = {}
file_info['saved'] = None
file_info['account_id'] = account_id
file_info['account_id_random'] = account_id_random
file_info['link_to_type'] = link_to_type
file_info['link_to_id'] = link_to_id
file_info['link_to_id_random'] = link_to_id_random
@@ -344,6 +346,8 @@ async def save_file_to_hosted_file(
account_id: int,
link_to_type: str,
link_to_id: int,
account_id_random: str = None,
link_to_id_random: str = None,
):
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(locals())
@@ -353,8 +357,11 @@ async def save_file_to_hosted_file(
file_info: dict = {}
file_info['saved'] = None
file_info['account_id'] = account_id
file_info['account_id_random'] = account_id_random
file_info['link_to_type'] = link_to_type
file_info['link_to_id'] = link_to_id
file_info['link_to_id_random'] = link_to_id_random
file_info['filename'] = filename
file_info['extension'] = extension
file_info['content_type'] = mimetypes.guess_type(filename)[0]

View File

@@ -24,6 +24,7 @@ async def clip_video_method(
account_id: int,
link_to_type: str,
link_to_id: int,
account_id_random: str = None,
filename_no_ext: str = 'automated_hosted_file_clip_video',
to_type: str = 'mp4',
reencode: bool = False,
@@ -66,6 +67,7 @@ async def clip_video_method(
filename = new_filename,
extension = to_type,
account_id = account_id,
account_id_random = account_id_random,
link_to_type = link_to_type,
link_to_id = link_to_id,
)
@@ -87,6 +89,7 @@ async def convert_file_method(
link_to_type: str,
link_to_id: int,
account_id: int,
account_id_random: str = None,
filename_no_ext: str = 'automated_hosted_file_conversion',
to_type: str = 'webp',
):
@@ -115,6 +118,7 @@ async def convert_file_method(
filename = f'{filename_no_ext}.{to_type}',
extension = to_type,
account_id = account_id,
account_id_random = account_id_random,
link_to_type = link_to_type,
link_to_id = link_to_id,
)

View File

@@ -1,6 +1,6 @@
import datetime, pytz
from typing import Dict, List, Optional, Set, Union
from typing import Dict, List, Optional, Set, Union, ClassVar
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
from app.db_sql import redis_lookup_id_random
@@ -92,6 +92,13 @@ class Archive_Content_Base(BaseModel):
hosted_file_content_type: Optional[str]
hosted_file_size: Optional[str]
# Fields that are part of the model (for reading) but should not be saved to the DB table
fields_to_exclude_from_db: ClassVar[list] = [
'account_id', 'account_id_random', 'archive_id_random', 'hosted_file_id_random',
'hosted_file_path', 'api_hosted_file_path_download', 'api_hosted_file_path_stream',
'hosted_file_hash_sha256', 'hosted_file_content_type', 'hosted_file_size'
]
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
@validator('id', always=True)

View File

@@ -1323,6 +1323,20 @@ def post_obj_template(
table_name_select = obj_type_kv_li[obj_type]['table_name']
base_name = obj_type_kv_li[obj_type]['base_name']
# # Prune any keys that are not actual columns on the target table to avoid
# # SQL errors when clients include convenience fields (e.g., account_id)
# try:
# from app import lib_sql_core
# from sqlalchemy import text
# with lib_sql_core.engine.connect() as conn:
# cols_res = conn.execute(text(f"DESCRIBE `{table_name_insert}`;"))
# cols = [r[0] for r in cols_res.fetchall()]
# # keep only keys that match real columns (always allow id_random)
# obj_data = {k: v for k, v in obj_data.items() if k in cols or k == 'id_random'}
# except Exception as _:
# # If DESCRIBE fails for any reason, fall back to original obj_data
# log.debug(f"Could not inspect table columns for {table_name_insert}; proceeding without pruning.")
if sql_insert_result := sql_insert(table_name=table_name_insert, data=obj_data, id_random_length=id_random_length):
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
log.debug(sql_insert_result)

View File

@@ -276,6 +276,7 @@ async def convert_file(
link_to_type = link_to_type,
link_to_id = lid_int,
account_id = commons.x_account_id,
account_id_random = commons.x_account_id_random,
filename_no_ext = filename_no_ext,
to_type = to_type
)
@@ -306,6 +307,7 @@ async def clip_video(
start_time = start_time,
end_time = end_time,
account_id = commons.x_account_id,
account_id_random = commons.x_account_id_random,
link_to_type = link_to_type,
link_to_id = lid_int,
filename_no_ext = filename_no_ext,