logs-update-shout
All checks were successful
Deploy on push / deploy (push) Successful in 58s

This commit is contained in:
Untone 2025-02-02 21:41:03 +03:00
parent 670a477f9a
commit fd6b0ce5fd

View File

@ -58,7 +58,8 @@ async def get_my_shout(_, info, shout_id: int):
if isinstance(shout.media, str): if isinstance(shout.media, str):
try: try:
shout.media = json.loads(shout.media) shout.media = json.loads(shout.media)
except: except Exception as e:
logger.error(f"Error parsing shout media: {e}")
shout.media = [] shout.media = []
if not isinstance(shout.media, list): if not isinstance(shout.media, list):
shout.media = [shout.media] if shout.media else [] shout.media = [shout.media] if shout.media else []
@ -212,89 +213,136 @@ async def create_shout(_, info, inp):
return {"error": error_msg} return {"error": error_msg}
def patch_main_topic(session, main_topic, shout): def patch_main_topic(session, main_topic_slug, shout):
logger.info(f"Starting patch_main_topic for shout#{shout.id} with slug '{main_topic_slug}'")
with session.begin(): with session.begin():
shout = session.query(Shout).options(joinedload(Shout.topics)).filter(Shout.id == shout.id).first() # Получаем текущий главный топик
if not shout: old_main = (
return
old_main_topic = (
session.query(ShoutTopic).filter(and_(ShoutTopic.shout == shout.id, ShoutTopic.main.is_(True))).first() session.query(ShoutTopic).filter(and_(ShoutTopic.shout == shout.id, ShoutTopic.main.is_(True))).first()
) )
if old_main:
logger.info(f"Found current main topic: {old_main.topic}")
main_topic = session.query(Topic).filter(Topic.slug == main_topic).first() # Находим новый главный топик
main_topic = session.query(Topic).filter(Topic.slug == main_topic_slug).first()
if not main_topic:
logger.error(f"Main topic with slug '{main_topic_slug}' not found")
return
if main_topic: logger.info(f"Found new main topic: {main_topic.id}")
new_main_topic = (
session.query(ShoutTopic)
.filter(and_(ShoutTopic.shout == shout.id, ShoutTopic.topic == main_topic.id))
.first()
)
if old_main_topic and new_main_topic and old_main_topic is not new_main_topic: # Находим связь с новым главным топиком
ShoutTopic.update(old_main_topic, {"main": False}) new_main = (
session.add(old_main_topic) session.query(ShoutTopic)
.filter(and_(ShoutTopic.shout == shout.id, ShoutTopic.topic == main_topic.id))
.first()
)
ShoutTopic.update(new_main_topic, {"main": True}) if old_main and new_main and old_main is not new_main:
session.add(new_main_topic) logger.info("Updating main topic flags")
old_main.main = False
session.add(old_main)
new_main.main = True
session.add(new_main)
session.flush()
logger.info(f"Main topic updated for shout#{shout.id}")
def patch_topics(session, shout, topics_input): def patch_topics(session, shout, topics_input):
logger.info(f"Starting patch_topics for shout#{shout.id}")
logger.info(f"Received topics_input: {topics_input}")
# Создаем новые топики если есть
new_topics_to_link = [Topic(**new_topic) for new_topic in topics_input if new_topic["id"] < 0] new_topics_to_link = [Topic(**new_topic) for new_topic in topics_input if new_topic["id"] < 0]
if new_topics_to_link: if new_topics_to_link:
logger.info(f"Creating new topics: {[t.dict() for t in new_topics_to_link]}")
session.add_all(new_topics_to_link) session.add_all(new_topics_to_link)
session.commit() session.flush() # Получаем ID для новых топиков
for new_topic_to_link in new_topics_to_link: # Получаем текущие связи
created_unlinked_topic = ShoutTopic(shout=shout.id, topic=new_topic_to_link.id) current_links = session.query(ShoutTopic).filter(ShoutTopic.shout == shout.id).all()
session.add(created_unlinked_topic) logger.info(f"Current topic links: {[{t.topic: t.main} for t in current_links]}")
existing_topics_input = [topic_input for topic_input in topics_input if topic_input.get("id", 0) > 0] # Удаляем старые связи
existing_topic_to_link_ids = [ if current_links:
existing_topic_input["id"] logger.info(f"Removing old topic links for shout#{shout.id}")
for existing_topic_input in existing_topics_input for link in current_links:
if existing_topic_input["id"] not in [topic.id for topic in shout.topics] session.delete(link)
] session.flush()
for existing_topic_to_link_id in existing_topic_to_link_ids: # Создаем новые связи
created_unlinked_topic = ShoutTopic(shout=shout.id, topic=existing_topic_to_link_id) for topic_input in topics_input:
session.add(created_unlinked_topic) topic_id = topic_input["id"]
if topic_id < 0:
# Для новых топиков берем ID из созданных
topic = next(t for t in new_topics_to_link if t.slug == topic_input["slug"])
topic_id = topic.id
topic_to_unlink_ids = [ logger.info(f"Creating new topic link: shout#{shout.id} -> topic#{topic_id}")
topic.id new_link = ShoutTopic(
for topic in shout.topics shout=shout.id,
if topic.id not in [topic_input["id"] for topic_input in existing_topics_input] topic=topic_id,
] main=False, # main topic устанавливается отдельно через patch_main_topic
)
session.add(new_link)
session.query(ShoutTopic).filter( try:
and_(ShoutTopic.shout == shout.id, ShoutTopic.topic.in_(topic_to_unlink_ids)) session.flush()
).delete(synchronize_session=False) logger.info(f"Successfully updated topics for shout#{shout.id}")
except Exception as e:
logger.error(f"Error flushing topic changes: {e}", exc_info=True)
raise
# Проверяем результат
new_links = session.query(ShoutTopic).filter(ShoutTopic.shout == shout.id).all()
logger.info(f"New topic links: {[{t.topic: t.main} for t in new_links]}")
@mutation.field("update_shout") @mutation.field("update_shout")
@login_required @login_required
async def update_shout(_, info, shout_id: int, shout_input=None, publish=False): async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
logger.info(f"Starting update_shout with id={shout_id}, publish={publish}")
logger.debug(f"Full shout_input: {shout_input}")
user_id = info.context.get("user_id") user_id = info.context.get("user_id")
roles = info.context.get("roles", []) roles = info.context.get("roles", [])
author_dict = info.context.get("author") author_dict = info.context.get("author")
if not author_dict: if not author_dict:
logger.error("Author profile not found")
return {"error": "author profile was not found"} return {"error": "author profile was not found"}
author_id = author_dict.get("id") author_id = author_dict.get("id")
shout_input = shout_input or {} shout_input = shout_input or {}
current_time = int(time.time()) current_time = int(time.time())
shout_id = shout_id or shout_input.get("id", shout_id) shout_id = shout_id or shout_input.get("id", shout_id)
slug = shout_input.get("slug") slug = shout_input.get("slug")
if not user_id: if not user_id:
logger.error("Unauthorized update attempt")
return {"error": "unauthorized"} return {"error": "unauthorized"}
try: try:
with local_session() as session: with local_session() as session:
if author_id: if author_id:
logger.info(f"author for shout#{shout_id} detected author #{author_id}") logger.info(f"Processing update for shout#{shout_id} by author #{author_id}")
shout_by_id = session.query(Shout).filter(Shout.id == shout_id).first() shout_by_id = session.query(Shout).filter(Shout.id == shout_id).first()
if not shout_by_id: if not shout_by_id:
logger.error(f"shout#{shout_id} not found") logger.error(f"shout#{shout_id} not found")
return {"error": "shout not found"} return {"error": "shout not found"}
logger.info(f"shout#{shout_id} found")
logger.info(f"Found shout#{shout_id}")
# Логируем текущие топики
current_topics = (
[{"id": t.id, "slug": t.slug, "title": t.title} for t in shout_by_id.topics]
if shout_by_id.topics
else []
)
logger.info(f"Current topics for shout#{shout_id}: {current_topics}")
if slug != shout_by_id.slug: if slug != shout_by_id.slug:
same_slug_shout = session.query(Shout).filter(Shout.slug == slug).first() same_slug_shout = session.query(Shout).filter(Shout.slug == slug).first()
@ -307,24 +355,34 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
logger.info(f"shout#{shout_id} slug patched") logger.info(f"shout#{shout_id} slug patched")
if filter(lambda x: x.id == author_id, [x for x in shout_by_id.authors]) or "editor" in roles: if filter(lambda x: x.id == author_id, [x for x in shout_by_id.authors]) or "editor" in roles:
logger.info(f"shout#{shout_id} is author or editor") logger.info(f"Author #{author_id} has permission to edit shout#{shout_id}")
# topics patch # topics patch
topics_input = shout_input.get("topics") topics_input = shout_input.get("topics")
if topics_input: if topics_input:
logger.info(f"topics_input: {topics_input}") logger.info(f"Received topics_input for shout#{shout_id}: {topics_input}")
patch_topics(session, shout_by_id, topics_input) try:
patch_topics(session, shout_by_id, topics_input)
logger.info(f"Successfully patched topics for shout#{shout_id}")
except Exception as e:
logger.error(f"Error patching topics: {e}", exc_info=True)
return {"error": f"Failed to update topics: {str(e)}"}
del shout_input["topics"] del shout_input["topics"]
for tpc in topics_input: for tpc in topics_input:
await cache_by_id(Topic, tpc["id"], cache_topic) await cache_by_id(Topic, tpc["id"], cache_topic)
else:
logger.warning(f"No topics_input received for shout#{shout_id}")
# main topic # main topic
main_topic = shout_input.get("main_topic") main_topic = shout_input.get("main_topic")
if main_topic: if main_topic:
logger.info(f"Updating main topic for shout#{shout_id} to {main_topic}")
patch_main_topic(session, main_topic, shout_by_id) patch_main_topic(session, main_topic, shout_by_id)
shout_input["updated_at"] = current_time shout_input["updated_at"] = current_time
if publish: if publish:
logger.info(f"publishing shout#{shout_id} with input: {shout_input}") logger.info(f"Publishing shout#{shout_id}")
shout_input["published_at"] = current_time shout_input["published_at"] = current_time
# Проверяем наличие связи с автором # Проверяем наличие связи с автором
logger.info(f"Checking author link for shout#{shout_id} and author#{author_id}") logger.info(f"Checking author link for shout#{shout_id} and author#{author_id}")
@ -343,11 +401,25 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
else: else:
logger.info("Author link already exists") logger.info("Author link already exists")
# Логируем финальное состояние перед сохранением
logger.info(f"Final shout_input for update: {shout_input}")
Shout.update(shout_by_id, shout_input) Shout.update(shout_by_id, shout_input)
session.add(shout_by_id) session.add(shout_by_id)
session.commit()
shout_dict = shout_by_id.dict() try:
session.commit()
logger.info(f"Successfully committed updates for shout#{shout_id}")
except Exception as e:
logger.error(f"Commit failed: {e}", exc_info=True)
return {"error": f"Failed to save changes: {str(e)}"}
# После обновления проверяем топики
updated_topics = (
[{"id": t.id, "slug": t.slug, "title": t.title} for t in shout_by_id.topics]
if shout_by_id.topics
else []
)
logger.info(f"Updated topics for shout#{shout_id}: {updated_topics}")
# Инвалидация кэша после обновления # Инвалидация кэша после обновления
try: try:
@ -379,25 +451,23 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
logger.warning(f"Cache invalidation error: {cache_error}", exc_info=True) logger.warning(f"Cache invalidation error: {cache_error}", exc_info=True)
if not publish: if not publish:
await notify_shout(shout_dict, "update") await notify_shout(shout_by_id.dict(), "update")
else: else:
await notify_shout(shout_dict, "published") await notify_shout(shout_by_id.dict(), "published")
# search service indexing # search service indexing
search_service.index(shout_by_id) search_service.index(shout_by_id)
for a in shout_by_id.authors: for a in shout_by_id.authors:
await cache_by_id(Author, a.id, cache_author) await cache_by_id(Author, a.id, cache_author)
logger.info(f"shout#{shout_id} updated") logger.info(f"shout#{shout_id} updated")
return {"shout": shout_dict, "error": None} return {"shout": shout_by_id.dict(), "error": None}
else: else:
logger.warning(f"updater for shout#{shout_id} is not author or editor") logger.warning(f"Access denied: author #{author_id} cannot edit shout#{shout_id}")
return {"error": "access denied", "shout": None} return {"error": "access denied", "shout": None}
except Exception as exc: except Exception as exc:
import traceback logger.error(f"Unexpected error in update_shout: {exc}", exc_info=True)
logger.error(f"Failed input data: {shout_input}")
traceback.print_exc() return {"error": "cant update shout"}
logger.error(exc)
logger.error(f" cannot update with data: {shout_input}")
return {"error": "cant update shout"} return {"error": "cant update shout"}