Implementation:OpenHands OpenHands UserStore Get User By Id Async
| Knowledge Sources | |
|---|---|
| Domains | Organization_Management, Multi_Tenancy |
| Last Updated | 2026-02-11 21:00 GMT |
Overview
Concrete tool for loading a user record with distributed locking and eager-loaded relationships to verify post-migration integrity provided by the OpenHands enterprise storage layer.
Description
UserStore.get_user_by_id_async loads a User record by its Keycloak user ID while ensuring thread-safe access during the migration transition period. The method implements two key mechanisms:
- Distributed lock acquisition: Before querying the database, the method acquires a distributed lock via
_acquire_user_creation_lock(user_id). This lock prevents concurrent requests for the same un-migrated user from triggering duplicate migration attempts. The lock is keyed to the specific user ID, so it does not block access to other users. - Eager loading via joinedload: The database query uses SQLAlchemy's
joinedloadto fetch the User entity along with its related entities (personal organization, organization memberships, roles, and member settings) in a single SQL statement. This ensures that:- All expected relationships are present and accessible without additional queries.
- The N+1 query problem is avoided when the caller accesses related data.
- The returned User object provides a complete picture of the user's organizational state.
If the user is not found in the database (returns None), the caller can then decide whether to trigger migration via migrate_user.
Usage
Call this method whenever you need to load a user record and verify that their organizational relationships are intact. It is the primary entry point for user resolution in the authentication middleware and is designed to be called on every authenticated request.
Code Reference
Source Location
- Repository: OpenHands
- File:
enterprise/storage/user_store.py - Lines: L706-769
Signature
async def get_user_by_id_async(
self,
user_id: str,
) -> User | None:
"""Load a user by ID with distributed locking and eager-loaded relationships.
Acquires a distributed lock to prevent concurrent migration races,
then queries the User table with joinedload for organization and
membership relationships.
Args:
user_id: The Keycloak user ID to look up.
Returns:
The User entity with all related entities eagerly loaded,
or None if the user does not exist in the database.
"""
Import
from enterprise.storage.user_store import UserStore
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| user_id | str | Yes | The Keycloak user ID to look up in the User table |
Outputs
| Name | Type | Description |
|---|---|---|
| user | User or None | The User entity with eagerly loaded personal_org, org_memberships, and associated roles; or None if the user record does not exist |
Usage Examples
Basic Usage
from enterprise.storage.user_store import UserStore
user_store = UserStore(session=db_session)
# Load user with distributed lock and eager-loaded relationships
user = await user_store.get_user_by_id_async(user_id="keycloak-user-abc123")
if user is None:
# User not yet migrated — trigger migration
user = await user_store.migrate_user(
user_id="keycloak-user-abc123",
user_settings=default_settings,
user_info=keycloak_user_info,
)
# Access eagerly loaded relationships without additional queries
print(user.personal_org.name)
for membership in user.org_memberships:
print(f"Org: {membership.org_id}, Role: {membership.role.name}")