Fix page creation labels and webhook race condition
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 56s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 56s
- Updated shared submodule: page-aware blog_new template labels - _upsert_post: handle concurrent webhook INSERTs via savepoint + retry Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -164,13 +164,8 @@ async def _upsert_tag(sess: AsyncSession, gt: Dict[str, Any]) -> Tag:
|
||||
return obj
|
||||
|
||||
|
||||
async def _upsert_post(sess: AsyncSession, gp: Dict[str, Any], author_map: Dict[str, Author], tag_map: Dict[str, Tag]) -> Post:
|
||||
res = await sess.execute(select(Post).where(Post.ghost_id == gp["id"]))
|
||||
obj = res.scalar_one_or_none()
|
||||
if obj is None:
|
||||
obj = Post(ghost_id=gp["id"]) # type: ignore[call-arg]
|
||||
sess.add(obj)
|
||||
|
||||
def _apply_ghost_fields(obj: Post, gp: Dict[str, Any], author_map: Dict[str, Author], tag_map: Dict[str, Tag]) -> None:
|
||||
"""Apply Ghost API fields to a Post ORM object."""
|
||||
obj.deleted_at = None # revive if soft-deleted
|
||||
|
||||
obj.uuid = gp.get("uuid") or obj.uuid
|
||||
@@ -213,7 +208,29 @@ async def _upsert_post(sess: AsyncSession, gp: Dict[str, Any], author_map: Dict[
|
||||
pt = gp.get("primary_tag")
|
||||
obj.primary_tag_id = tag_map[pt["id"].strip()].id if (pt and pt["id"] in tag_map) else None # type: ignore[index]
|
||||
|
||||
await sess.flush()
|
||||
|
||||
async def _upsert_post(sess: AsyncSession, gp: Dict[str, Any], author_map: Dict[str, Author], tag_map: Dict[str, Tag]) -> Post:
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
res = await sess.execute(select(Post).where(Post.ghost_id == gp["id"]))
|
||||
obj = res.scalar_one_or_none()
|
||||
if obj is None:
|
||||
obj = Post(ghost_id=gp["id"]) # type: ignore[call-arg]
|
||||
sess.add(obj)
|
||||
|
||||
_apply_ghost_fields(obj, gp, author_map, tag_map)
|
||||
|
||||
try:
|
||||
async with sess.begin_nested():
|
||||
await sess.flush()
|
||||
except IntegrityError:
|
||||
# Race condition: another request inserted this ghost_id concurrently.
|
||||
# Expunge the failed object, re-select the existing row, and update it.
|
||||
sess.expunge(obj)
|
||||
res = await sess.execute(select(Post).where(Post.ghost_id == gp["id"]))
|
||||
obj = res.scalar_one()
|
||||
_apply_ghost_fields(obj, gp, author_map, tag_map)
|
||||
await sess.flush()
|
||||
|
||||
# Backfill user_id from primary author email if not already set
|
||||
if obj.user_id is None and obj.primary_author_id is not None:
|
||||
|
||||
2
shared
2
shared
Submodule shared updated: 9a1a4996bc...24432cd52a
Reference in New Issue
Block a user