Skip to content

Commit 3945633

Browse files
committed
fix: improve session management and error handling in role seeding process
1 parent 11adac3 commit 3945633

1 file changed

Lines changed: 71 additions & 59 deletions

File tree

fastapi_admin_kit/backends/sqlalchemy.py

Lines changed: 71 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -956,70 +956,82 @@ def seed_roles(
956956
if is_async:
957957

958958
async def _run_async() -> None:
959-
existing = await session.all(sa_select(Role))
960-
if existing and not overwrite:
961-
return
962-
if overwrite:
963-
await session.execute(sa_delete(admin_role_permissions))
964-
await session.execute(sa_delete(Role))
965-
for role_spec in seed_roles:
966-
role = Role(name=role_spec.name, description=role_spec.description)
967-
session.add(role)
968-
await session.flush()
969-
await session.refresh(role, ["permissions"])
970-
if role_spec.permissions:
971-
for table_name, perms in role_spec.permissions.items():
972-
existing_perm = await session.scalar_one_or_none(
973-
sa_select(Permission).filter_by(table_name=table_name)
974-
)
975-
if existing_perm is None:
976-
perm = Permission(
977-
name=table_name,
978-
table_name=table_name,
979-
can_view=perms.get("view", False),
980-
can_create=perms.get("create", False),
981-
can_edit=perms.get("edit", False),
982-
can_delete=perms.get("delete", False),
959+
try:
960+
existing = await session.all(sa_select(Role))
961+
if existing and not overwrite:
962+
return
963+
if overwrite:
964+
await session.execute(sa_delete(admin_role_permissions))
965+
await session.execute(sa_delete(Role))
966+
for role_spec in seed_roles:
967+
role = Role(name=role_spec.name, description=role_spec.description)
968+
session.add(role)
969+
await session.flush()
970+
await session.refresh(role, ["permissions"])
971+
if role_spec.permissions:
972+
for table_name, perms in role_spec.permissions.items():
973+
existing_perm = await session.scalar_one_or_none(
974+
sa_select(Permission).filter_by(table_name=table_name)
983975
)
984-
session.add(perm)
985-
await session.flush()
986-
else:
987-
perm = existing_perm
988-
role.permissions.append(perm)
989-
await session.commit()
976+
if existing_perm is None:
977+
perm = Permission(
978+
name=table_name,
979+
table_name=table_name,
980+
can_view=perms.get("view", False),
981+
can_create=perms.get("create", False),
982+
can_edit=perms.get("edit", False),
983+
can_delete=perms.get("delete", False),
984+
)
985+
session.add(perm)
986+
await session.flush()
987+
else:
988+
perm = existing_perm
989+
role.permissions.append(perm)
990+
await session.commit()
991+
finally:
992+
# Always release the session: an unclosed session that
993+
# performed DB work is GC'd while still holding a pooled
994+
# connection ("non-checked-in connection" SAWarning). The
995+
# early-return path above is the usual trigger — it leaves
996+
# an open read transaction behind. close() rolls back any
997+
# open transaction and returns the connection to the pool.
998+
await session.close()
990999

9911000
return _run_async()
9921001

993-
existing = session.all(sa_select(Role))
994-
if existing and not overwrite:
995-
return None
996-
if overwrite:
997-
session.execute(sa_delete(admin_role_permissions))
998-
session.execute(sa_delete(Role))
999-
for role_spec in seed_roles:
1000-
role = Role(name=role_spec.name, description=role_spec.description)
1001-
session.add(role)
1002-
session.flush()
1003-
if role_spec.permissions:
1004-
for table_name, perms in role_spec.permissions.items():
1005-
existing_perm = session.scalar_one_or_none(
1006-
sa_select(Permission).filter_by(table_name=table_name)
1007-
)
1008-
if existing_perm is None:
1009-
perm = Permission(
1010-
name=table_name,
1011-
table_name=table_name,
1012-
can_view=perms.get("view", False),
1013-
can_create=perms.get("create", False),
1014-
can_edit=perms.get("edit", False),
1015-
can_delete=perms.get("delete", False),
1002+
try:
1003+
existing = session.all(sa_select(Role))
1004+
if existing and not overwrite:
1005+
return None
1006+
if overwrite:
1007+
session.execute(sa_delete(admin_role_permissions))
1008+
session.execute(sa_delete(Role))
1009+
for role_spec in seed_roles:
1010+
role = Role(name=role_spec.name, description=role_spec.description)
1011+
session.add(role)
1012+
session.flush()
1013+
if role_spec.permissions:
1014+
for table_name, perms in role_spec.permissions.items():
1015+
existing_perm = session.scalar_one_or_none(
1016+
sa_select(Permission).filter_by(table_name=table_name)
10161017
)
1017-
session.add(perm)
1018-
session.flush()
1019-
else:
1020-
perm = existing_perm
1021-
role.permissions.append(perm)
1022-
session.commit()
1018+
if existing_perm is None:
1019+
perm = Permission(
1020+
name=table_name,
1021+
table_name=table_name,
1022+
can_view=perms.get("view", False),
1023+
can_create=perms.get("create", False),
1024+
can_edit=perms.get("edit", False),
1025+
can_delete=perms.get("delete", False),
1026+
)
1027+
session.add(perm)
1028+
session.flush()
1029+
else:
1030+
perm = existing_perm
1031+
role.permissions.append(perm)
1032+
session.commit()
1033+
finally:
1034+
session.close()
10231035
return None
10241036

10251037
@property

0 commit comments

Comments
 (0)