Refresh the ``user_name`` snapshot on existing usage rows. The denorm exists so usage stays attributable after the user row is deleted, but a live rename should still flow through — dashboards group by ``user_name`` and would otherwise show the stale value until the user is hard-del
(
session: AsyncSession,
user_id: int,
new_name: Optional[str],
)
| 17 | |
| 18 | |
| 19 | async def propagate_user_rename( |
| 20 | session: AsyncSession, |
| 21 | user_id: int, |
| 22 | new_name: Optional[str], |
| 23 | ) -> None: |
| 24 | """Refresh the ``user_name`` snapshot on existing usage rows. |
| 25 | |
| 26 | The denorm exists so usage stays attributable after the user row is |
| 27 | deleted, but a live rename should still flow through — dashboards |
| 28 | group by ``user_name`` and would otherwise show the stale value |
| 29 | until the user is hard-deleted. Runs on the caller's session and |
| 30 | leaves committing to them so the user-row write and the snapshot |
| 31 | refresh land in the same transaction. |
| 32 | |
| 33 | Counterpart denorms (``cluster_name``, ``model_name``, |
| 34 | ``api_key_name``, ``provider_name``) have the same drift property |
| 35 | but are out of scope for this helper; add sibling helpers when |
| 36 | those rename paths grow. |
| 37 | """ |
| 38 | for table in (ModelUsage, ModelUsageDetails, ModelUsageDetailsArchive): |
| 39 | await session.exec( |
| 40 | update(table).where(table.user_id == user_id).values(user_name=new_name) |
| 41 | ) |
| 42 | |
| 43 | |
| 44 | def format_usage_user_label(user_name: Optional[str]) -> str: |