|
3 | 3 |
|
4 | 4 | from sqlalchemy import select, update |
5 | 5 | from sqlalchemy.ext.asyncio import AsyncSession |
6 | | -from sqlalchemy.orm import selectinload |
| 6 | +from sqlalchemy.orm import joinedload |
7 | 7 |
|
8 | 8 | from dstack._internal.core.backends.base.compute import ComputeWithVolumeSupport |
9 | 9 | from dstack._internal.core.errors import BackendNotAvailable |
10 | 10 | from dstack._internal.core.models.profiles import parse_duration |
11 | 11 | from dstack._internal.core.models.volumes import VolumeStatus |
12 | 12 | from dstack._internal.server.db import get_db, get_session_ctx |
13 | | -from dstack._internal.server.models import VolumeModel |
| 13 | +from dstack._internal.server.models import ProjectModel, VolumeModel |
14 | 14 | from dstack._internal.server.services import backends as backends_services |
15 | 15 | from dstack._internal.server.services.locking import get_locker |
16 | 16 | from dstack._internal.server.services.volumes import ( |
@@ -45,12 +45,13 @@ async def process_idle_volumes(): |
45 | 45 | for volume_id in volume_ids: |
46 | 46 | lockset.add(volume_id) |
47 | 47 |
|
| 48 | + # Refetch volumes with proper relationship loading to avoid MissingGreenlet |
48 | 49 | res = await session.execute( |
49 | 50 | select(VolumeModel) |
50 | 51 | .where(VolumeModel.id.in_(volume_ids)) |
51 | | - .options(selectinload(VolumeModel.project)) |
52 | | - .options(selectinload(VolumeModel.user)) |
53 | | - .options(selectinload(VolumeModel.attachments)) |
| 52 | + .options(joinedload(VolumeModel.project).joinedload(ProjectModel.backends)) |
| 53 | + .options(joinedload(VolumeModel.user)) |
| 54 | + .options(joinedload(VolumeModel.attachments)) |
54 | 55 | .execution_options(populate_existing=True) |
55 | 56 | ) |
56 | 57 | volumes = list(res.unique().scalars().all()) |
|
0 commit comments