Skip to content

Commit 315e315

Browse files
committed
fix(models): add lazy='selectin' to User.identity to prevent MissingGreenlet
association_proxy fields (email, username, password_hash, email_verified, primary_mobile) access User.identity at attribute-read time. In async SQLAlchemy contexts this triggered a synchronous greenlet IO call, causing: sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called Observed 63 occurrences in 10 minutes on production. Adding lazy='selectin' makes SQLAlchemy eagerly load identity alongside every User query, eliminating the lazy-load IO entirely and fixing the crash. Ref: PR #258 (nap-liu)
1 parent 212ccea commit 315e315

1 file changed

Lines changed: 5 additions & 1 deletion

File tree

backend/app/models/user.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,11 @@ class User(Base):
9797
quota_agent_ttl_hours: Mapped[int] = mapped_column(Integer, default=48)
9898

9999
# Relationships
100-
identity: Mapped["Identity"] = relationship(back_populates="tenant_users")
100+
# lazy="selectin" is required because association_proxy fields (email, username,
101+
# password_hash, email_verified, primary_mobile) delegate to this relationship.
102+
# Without eager loading, any proxy access in an async context triggers a synchronous
103+
# IO call inside a greenlet, raising sqlalchemy.exc.MissingGreenlet.
104+
identity: Mapped["Identity"] = relationship(back_populates="tenant_users", lazy="selectin")
101105

102106
# Association proxies for backward compatibility
103107
email = association_proxy("identity", "email")

0 commit comments

Comments
 (0)