published_at-revert
This commit is contained in:
parent
f6863b32e8
commit
ddc2d69e54
|
@ -100,147 +100,133 @@ async def create_shout(_, info, inp):
|
|||
logger.debug(f"Context user_id: {user_id}, author: {author_dict}")
|
||||
|
||||
if not author_dict:
|
||||
logger.error("Author profile not found in context")
|
||||
return {"error": "author profile was not found"}
|
||||
|
||||
try:
|
||||
with local_session() as session:
|
||||
current_time = int(time.time())
|
||||
is_draft = inp.get("is_draft", False)
|
||||
if not is_draft:
|
||||
inp["published_at"] = current_time
|
||||
author_id = author_dict.get("id")
|
||||
if user_id and author_id:
|
||||
try:
|
||||
with local_session() as session:
|
||||
author_id = int(author_id)
|
||||
current_time = int(time.time())
|
||||
slug = inp.get("slug") or f"draft-{current_time}"
|
||||
|
||||
logger.info(f"Creating shout with slug: {slug}")
|
||||
|
||||
# Создаем объект Shout напрямую, без промежуточного словаря
|
||||
new_shout = Shout(
|
||||
title=inp.get("title", ""),
|
||||
subtitle=inp.get("subtitle", ""),
|
||||
lead=inp.get("lead", ""),
|
||||
description=inp.get("description", ""),
|
||||
body=inp.get("body", ""),
|
||||
layout=inp.get("layout", "article"),
|
||||
created_by=author_id,
|
||||
slug=slug,
|
||||
published_at=None,
|
||||
community=1,
|
||||
created_at=current_time,
|
||||
stat={ # Добавляем начальную статистику
|
||||
"views": 0,
|
||||
"comments": 0,
|
||||
"reactions": 0,
|
||||
"shares": 0,
|
||||
"bookmarks": 0
|
||||
}
|
||||
)
|
||||
|
||||
# Устанавливаем обязательные поля
|
||||
inp["created_at"] = current_time
|
||||
inp["updated_at"] = current_time
|
||||
inp["created_by"] = author_dict.get("id")
|
||||
inp["community"] = inp.get("community", 1)
|
||||
# Check for duplicate slug
|
||||
logger.debug(f"Checking for existing slug: {slug}")
|
||||
same_slug_shout = session.query(Shout).filter(Shout.slug == new_shout.slug).first()
|
||||
c = 1
|
||||
while same_slug_shout is not None:
|
||||
logger.debug(f"Found duplicate slug, trying iteration {c}")
|
||||
new_shout.slug = f"{slug}-{c}"
|
||||
same_slug_shout = session.query(Shout).filter(Shout.slug == new_shout.slug).first()
|
||||
c += 1
|
||||
|
||||
# Генерация уникального slug с ограничением длины
|
||||
base_slug = inp.get("slug") or f"draft-{current_time}"
|
||||
slug = base_slug[:50] # Сразу ограничиваем длину базового slug
|
||||
counter = 1
|
||||
max_attempts = 10
|
||||
|
||||
while counter <= max_attempts:
|
||||
existing_slug = session.query(Shout).filter(Shout.slug == slug).first()
|
||||
if not existing_slug:
|
||||
break
|
||||
slug = f"{base_slug[:40]}-{counter}" # Оставляем место для счетчика
|
||||
counter += 1
|
||||
|
||||
if counter > max_attempts:
|
||||
# Если не удалось создать уникальный slug, используем короткий вариант
|
||||
slug = f"d-{current_time}-{author_dict.get('id')}"
|
||||
|
||||
inp["slug"] = slug
|
||||
inp["lang"] = inp.get("lang", "ru")
|
||||
|
||||
# Добавляем обязательные поля контента
|
||||
inp["title"] = inp.get("title", "Без названия")
|
||||
inp["body"] = inp.get("body", "")
|
||||
|
||||
logger.info("Creating new shout object")
|
||||
new_shout = Shout(**inp)
|
||||
session.add(new_shout)
|
||||
session.flush()
|
||||
|
||||
try:
|
||||
session.commit()
|
||||
logger.info(f"Created shout with ID: {new_shout.id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating shout object: {e}", exc_info=True)
|
||||
return {"error": f"Database error: {str(e)}"}
|
||||
|
||||
# Get created shout
|
||||
try:
|
||||
logger.debug(f"Retrieving created shout with slug: {new_shout.slug}")
|
||||
shout = session.query(Shout).where(Shout.slug == new_shout.slug).first()
|
||||
if not shout:
|
||||
logger.error("Created shout not found in database")
|
||||
return {"error": "Shout creation failed - not found after commit"}
|
||||
except Exception as e:
|
||||
logger.error(f"Error retrieving created shout: {e}", exc_info=True)
|
||||
return {"error": f"Error retrieving created shout: {str(e)}"}
|
||||
|
||||
# Link author
|
||||
try:
|
||||
logger.debug(f"Linking author {author_dict.get('id')} to shout {shout.id}")
|
||||
existing_sa = session.query(ShoutAuthor).filter_by(shout=shout.id, author=author_dict.get("id")).first()
|
||||
if not existing_sa:
|
||||
sa = ShoutAuthor(shout=shout.id, author=author_dict.get("id"))
|
||||
session.add(sa)
|
||||
logger.info(f"Added author {author_dict.get('id')} to shout {shout.id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error linking author: {e}", exc_info=True)
|
||||
return {"error": f"Error linking author: {str(e)}"}
|
||||
|
||||
# Link topics
|
||||
try:
|
||||
logger.debug(f"Linking topics: {inp.get('topics', [])}")
|
||||
topics = session.query(Topic).filter(Topic.slug.in_(inp.get("topics", []))).all()
|
||||
for topic in topics:
|
||||
existing_st = session.query(ShoutTopic).filter_by(shout=shout.id, topic=topic.id).first()
|
||||
if not existing_st:
|
||||
t = ShoutTopic(topic=topic.id, shout=shout.id)
|
||||
session.add(t)
|
||||
logger.info(f"Added topic {topic.id} to shout {shout.id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error linking topics: {e}", exc_info=True)
|
||||
return {"error": f"Error linking topics: {str(e)}"}
|
||||
|
||||
try:
|
||||
session.commit()
|
||||
logger.info("Final commit successful")
|
||||
except Exception as e:
|
||||
logger.error(f"Error in final commit: {e}", exc_info=True)
|
||||
return {"error": f"Error in final commit: {str(e)}"}
|
||||
|
||||
try:
|
||||
logger.debug("Following created shout")
|
||||
await follow(None, info, "shout", shout.slug)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error following shout: {e}", exc_info=True)
|
||||
# Don't return error as this is not critical
|
||||
|
||||
# После успешного создания обновляем статистику автора
|
||||
try:
|
||||
author = session.query(Author).filter(Author.id == author_dict.get("id")).first()
|
||||
if author and author.stat:
|
||||
author.stat["shouts"] = author.stat.get("shouts", 0) + 1
|
||||
session.add(author)
|
||||
try:
|
||||
logger.info("Creating new shout object")
|
||||
session.add(new_shout)
|
||||
session.commit()
|
||||
await cache_author(author.dict())
|
||||
except Exception as e:
|
||||
logger.warning(f"Error updating author stats: {e}", exc_info=True)
|
||||
# Не возвращаем ошибку, так как это некритично
|
||||
logger.info(f"Created shout with ID: {new_shout.id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating shout object: {e}", exc_info=True)
|
||||
return {"error": f"Database error: {str(e)}"}
|
||||
|
||||
# Преобразуем связанные сущности в словари
|
||||
try:
|
||||
shout_dict = shout.dict()
|
||||
shout_dict["authors"] = [
|
||||
{"id": author.id, "name": author.name, "slug": author.slug, "pic": author.pic}
|
||||
for author in shout.authors
|
||||
]
|
||||
shout_dict["topics"] = [
|
||||
{"id": topic.id, "name": topic.name, "slug": topic.slug} for topic in shout.topics
|
||||
]
|
||||
logger.info(f"Successfully created shout {shout.id} with authors and topics as dicts")
|
||||
# Get created shout
|
||||
try:
|
||||
logger.debug(f"Retrieving created shout with slug: {slug}")
|
||||
shout = session.query(Shout).where(Shout.slug == slug).first()
|
||||
if not shout:
|
||||
logger.error("Created shout not found in database")
|
||||
return {"error": "Shout creation failed - not found after commit"}
|
||||
except Exception as e:
|
||||
logger.error(f"Error retrieving created shout: {e}", exc_info=True)
|
||||
return {"error": f"Error retrieving created shout: {str(e)}"}
|
||||
|
||||
# Инвалидируем кэш
|
||||
await invalidate_shouts_cache(["feed", f"author_{author_dict.get('id')}", "random_top", "unrated"])
|
||||
# Link author
|
||||
try:
|
||||
logger.debug(f"Linking author {author_id} to shout {shout.id}")
|
||||
existing_sa = session.query(ShoutAuthor).filter_by(shout=shout.id, author=author_id).first()
|
||||
if not existing_sa:
|
||||
sa = ShoutAuthor(shout=shout.id, author=author_id)
|
||||
session.add(sa)
|
||||
logger.info(f"Added author {author_id} to shout {shout.id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error linking author: {e}", exc_info=True)
|
||||
return {"error": f"Error linking author: {str(e)}"}
|
||||
|
||||
# Обновляем кэш связанных сущностей
|
||||
# TODO: await cache_related_entities(shout)
|
||||
# Link topics
|
||||
try:
|
||||
logger.debug(f"Linking topics: {inp.get('topics', [])}")
|
||||
topics = session.query(Topic).filter(Topic.slug.in_(inp.get("topics", []))).all()
|
||||
for topic in topics:
|
||||
existing_st = session.query(ShoutTopic).filter_by(shout=shout.id, topic=topic.id).first()
|
||||
if not existing_st:
|
||||
t = ShoutTopic(topic=topic.id, shout=shout.id)
|
||||
session.add(t)
|
||||
logger.info(f"Added topic {topic.id} to shout {shout.id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Error linking topics: {e}", exc_info=True)
|
||||
return {"error": f"Error linking topics: {str(e)}"}
|
||||
|
||||
return {"shout": shout_dict, "error": None}
|
||||
except Exception as e:
|
||||
logger.warning(f"Error converting related entities to dicts: {e}", exc_info=True)
|
||||
# Если преобразование не удалось, возвращаем исходный объект
|
||||
try:
|
||||
session.commit()
|
||||
logger.info("Final commit successful")
|
||||
except Exception as e:
|
||||
logger.error(f"Error in final commit: {e}", exc_info=True)
|
||||
return {"error": f"Error in final commit: {str(e)}"}
|
||||
|
||||
try:
|
||||
logger.debug("Following created shout")
|
||||
await follow(None, info, "shout", shout.slug)
|
||||
except Exception as e:
|
||||
logger.warning(f"Error following shout: {e}", exc_info=True)
|
||||
# Don't return error as this is not critical
|
||||
|
||||
# После успешного создания обновляем статистику автора
|
||||
try:
|
||||
author = session.query(Author).filter(Author.id == author_id).first()
|
||||
if author and author.stat:
|
||||
author.stat["shouts"] = (author.stat.get("shouts", 0) + 1)
|
||||
session.add(author)
|
||||
session.commit()
|
||||
await cache_author(author.dict())
|
||||
except Exception as e:
|
||||
logger.warning(f"Error updating author stats: {e}", exc_info=True)
|
||||
# Не возвращаем ошибку, так как это некритично
|
||||
|
||||
logger.info(f"Successfully created shout {shout.id}")
|
||||
return {"shout": shout}
|
||||
|
||||
except Exception as exc:
|
||||
logger.error(f"Error in create_shout: {exc}", exc_info=True)
|
||||
return {"error": str(exc)}
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error in create_shout: {e}", exc_info=True)
|
||||
return {"error": f"Unexpected error: {str(e)}"}
|
||||
|
||||
error_msg = "cant create shout" if user_id else "unauthorized"
|
||||
logger.error(f"Create shout failed: {error_msg}")
|
||||
return {"error": error_msg}
|
||||
|
||||
|
||||
def patch_main_topic(session, main_topic, shout):
|
||||
|
@ -328,24 +314,13 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
|
|||
logger.info(f"shout#{shout_id} found")
|
||||
|
||||
if slug != shout_by_id.slug:
|
||||
base_slug = slug[:50]
|
||||
new_slug = base_slug
|
||||
counter = 1
|
||||
max_attempts = 10
|
||||
|
||||
while counter <= max_attempts:
|
||||
same_slug_shout = (
|
||||
session.query(Shout).filter(and_(Shout.slug == new_slug, Shout.id != shout_id)).first()
|
||||
)
|
||||
if not same_slug_shout:
|
||||
break
|
||||
new_slug = f"{base_slug[:40]}-{counter}"
|
||||
counter += 1
|
||||
|
||||
if counter > max_attempts:
|
||||
new_slug = f"d-{current_time}-{shout_id}"
|
||||
|
||||
shout_input["slug"] = new_slug
|
||||
same_slug_shout = session.query(Shout).filter(Shout.slug == slug).first()
|
||||
c = 1
|
||||
while same_slug_shout is not None:
|
||||
c += 1
|
||||
slug = f"{slug}-{c}"
|
||||
same_slug_shout = session.query(Shout).filter(Shout.slug == slug).first()
|
||||
shout_input["slug"] = slug
|
||||
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:
|
||||
|
@ -371,17 +346,11 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
|
|||
session.commit()
|
||||
|
||||
shout_dict = shout_by_id.dict()
|
||||
# Преобразуем связанные сущности в словари
|
||||
try:
|
||||
shout_dict["authors"] = [author.dict() for author in shout_by_id.authors]
|
||||
shout_dict["topics"] = [topic.dict() for topic in shout_by_id.topics]
|
||||
except Exception as e:
|
||||
logger.warning(f"Error converting related entities to dicts: {e}", exc_info=True)
|
||||
|
||||
# Инвалидация кэша после обновления
|
||||
try:
|
||||
logger.info("Invalidating cache after shout update")
|
||||
|
||||
|
||||
cache_keys = [
|
||||
"feed", # лента
|
||||
f"author_{author_id}", # публикации автора
|
||||
|
@ -393,7 +362,7 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
|
|||
for topic in shout_by_id.topics:
|
||||
cache_keys.append(f"topic_{topic.id}")
|
||||
cache_keys.append(f"topic_shouts_{topic.id}")
|
||||
|
||||
|
||||
# Добавляем ключи для новых тем (если есть в shout_input)
|
||||
if shout_input.get("topics"):
|
||||
for topic in shout_input["topics"]:
|
||||
|
@ -402,13 +371,13 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
|
|||
cache_keys.append(f"topic_shouts_{topic.id}")
|
||||
|
||||
await invalidate_shouts_cache(cache_keys)
|
||||
|
||||
|
||||
# Обновляем кэш тем и авторов
|
||||
for topic in shout_by_id.topics:
|
||||
await cache_by_id(Topic, topic.id, cache_topic)
|
||||
for author in shout_by_id.authors:
|
||||
await cache_author(author.dict())
|
||||
|
||||
|
||||
logger.info("Cache invalidated successfully")
|
||||
except Exception as cache_error:
|
||||
logger.warning(f"Cache invalidation error: {cache_error}", exc_info=True)
|
||||
|
@ -424,7 +393,7 @@ async def update_shout(_, info, shout_id: int, shout_input=None, publish=False):
|
|||
logger.info(f"shout#{shout_id} updated")
|
||||
return {"shout": shout_dict, "error": None}
|
||||
else:
|
||||
logger.warning(f"shout#{shout_id} is not author or editor")
|
||||
logger.warning(f"updater for shout#{shout_id} is not author or editor")
|
||||
return {"error": "access denied", "shout": None}
|
||||
|
||||
except Exception as exc:
|
||||
|
|
Loading…
Reference in New Issue
Block a user