Skip to content

Commit

Permalink
feat: adding photo & video storage space to server stats (immich-app#…
Browse files Browse the repository at this point in the history
…14125)

* expose detailed user storage stats + display them in the storage per user table

* chore: openapi & sql

* fix: fix test stubs

* fix: formatting errors, e2e test and server test

* fix: upper lower case typo in spec file

---------

Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
  • Loading branch information
2 people authored and yosit committed Nov 21, 2024
1 parent ce9599d commit ea6ac57
Show file tree
Hide file tree
Showing 12 changed files with 138 additions and 7 deletions.
6 changes: 6 additions & 0 deletions e2e/src/api/specs/server.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,15 @@ describe('/server', () => {
expect(body).toEqual({
photos: 0,
usage: 0,
usagePhotos: 0,
usageVideos: 0,
usageByUser: [
{
quotaSizeInBytes: null,
photos: 0,
usage: 0,
usagePhotos: 0,
usageVideos: 0,
userName: 'Immich Admin',
userId: admin.userId,
videos: 0,
Expand All @@ -176,6 +180,8 @@ describe('/server', () => {
quotaSizeInBytes: null,
photos: 0,
usage: 0,
usagePhotos: 0,
usageVideos: 0,
userName: 'User 1',
userId: nonAdmin.userId,
videos: 0,
Expand Down
18 changes: 17 additions & 1 deletion mobile/openapi/lib/model/server_stats_response_dto.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 17 additions & 1 deletion mobile/openapi/lib/model/usage_by_user_dto.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 25 additions & 1 deletion open-api/immich-openapi-specs.json
Original file line number Diff line number Diff line change
Expand Up @@ -10966,7 +10966,9 @@
{
"photos": 1,
"videos": 1,
"diskUsageRaw": 1
"diskUsageRaw": 2,
"usagePhotos": 1,
"usageVideos": 1
}
],
"items": {
Expand All @@ -10975,6 +10977,16 @@
"title": "Array of usage for each user",
"type": "array"
},
"usagePhotos": {
"default": 0,
"format": "int64",
"type": "integer"
},
"usageVideos": {
"default": 0,
"format": "int64",
"type": "integer"
},
"videos": {
"default": 0,
"type": "integer"
Expand All @@ -10984,6 +10996,8 @@
"photos",
"usage",
"usageByUser",
"usagePhotos",
"usageVideos",
"videos"
],
"type": "object"
Expand Down Expand Up @@ -12503,6 +12517,14 @@
"format": "int64",
"type": "integer"
},
"usagePhotos": {
"format": "int64",
"type": "integer"
},
"usageVideos": {
"format": "int64",
"type": "integer"
},
"userId": {
"type": "string"
},
Expand All @@ -12517,6 +12539,8 @@
"photos",
"quotaSizeInBytes",
"usage",
"usagePhotos",
"usageVideos",
"userId",
"userName",
"videos"
Expand Down
4 changes: 4 additions & 0 deletions open-api/typescript-sdk/src/fetch-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,8 @@ export type UsageByUserDto = {
photos: number;
quotaSizeInBytes: number | null;
usage: number;
usagePhotos: number;
usageVideos: number;
userId: string;
userName: string;
videos: number;
Expand All @@ -977,6 +979,8 @@ export type ServerStatsResponseDto = {
photos: number;
usage: number;
usageByUser: UsageByUserDto[];
usagePhotos: number;
usageVideos: number;
videos: number;
};
export type ServerStorageResponseDto = {
Expand Down
14 changes: 13 additions & 1 deletion server/src/dtos/server.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ export class UsageByUserDto {
@ApiProperty({ type: 'integer', format: 'int64' })
usage!: number;
@ApiProperty({ type: 'integer', format: 'int64' })
usagePhotos!: number;
@ApiProperty({ type: 'integer', format: 'int64' })
usageVideos!: number;
@ApiProperty({ type: 'integer', format: 'int64' })
quotaSizeInBytes!: number | null;
}

Expand All @@ -99,6 +103,12 @@ export class ServerStatsResponseDto {
@ApiProperty({ type: 'integer', format: 'int64' })
usage = 0;

@ApiProperty({ type: 'integer', format: 'int64' })
usagePhotos = 0;

@ApiProperty({ type: 'integer', format: 'int64' })
usageVideos = 0;

@ApiProperty({
isArray: true,
type: UsageByUserDto,
Expand All @@ -107,7 +117,9 @@ export class ServerStatsResponseDto {
{
photos: 1,
videos: 1,
diskUsageRaw: 1,
diskUsageRaw: 2,
usagePhotos: 1,
usageVideos: 1,
},
],
})
Expand Down
2 changes: 2 additions & 0 deletions server/src/interfaces/user.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export interface UserStatsQueryResponse {
photos: number;
videos: number;
usage: number;
usagePhotos: number;
usageVideos: number;
quotaSizeInBytes: number | null;
}

Expand Down
18 changes: 17 additions & 1 deletion server/src/queries/user.repository.sql
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,23 @@ SELECT
"assets"."libraryId" IS NULL
),
0
) AS "usage"
) AS "usage",
COALESCE(
SUM("exif"."fileSizeInByte") FILTER (
WHERE
"assets"."libraryId" IS NULL
AND "assets"."type" = 'IMAGE'
),
0
) AS "usagePhotos",
COALESCE(
SUM("exif"."fileSizeInByte") FILTER (
WHERE
"assets"."libraryId" IS NULL
AND "assets"."type" = 'VIDEO'
),
0
) AS "usageVideos"
FROM
"users" "users"
LEFT JOIN "assets" "assets" ON "assets"."ownerId" = "users"."id"
Expand Down
10 changes: 10 additions & 0 deletions server/src/repositories/user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ export class UserRepository implements IUserRepository {
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'IMAGE' AND assets.isVisible)`, 'photos')
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'VIDEO' AND assets.isVisible)`, 'videos')
.addSelect('COALESCE(SUM(exif.fileSizeInByte) FILTER (WHERE assets.libraryId IS NULL), 0)', 'usage')
.addSelect(
`COALESCE(SUM(exif.fileSizeInByte) FILTER (WHERE assets.libraryId IS NULL AND assets.type = 'IMAGE'), 0)`,
'usagePhotos',
)
.addSelect(
`COALESCE(SUM(exif.fileSizeInByte) FILTER (WHERE assets.libraryId IS NULL AND assets.type = 'VIDEO'), 0)`,
'usageVideos',
)
.addSelect('users.quotaSizeInBytes', 'quotaSizeInBytes')
.leftJoin('users.assets', 'assets')
.leftJoin('assets.exifInfo', 'exif')
Expand All @@ -119,6 +127,8 @@ export class UserRepository implements IUserRepository {
stat.photos = Number(stat.photos);
stat.videos = Number(stat.videos);
stat.usage = Number(stat.usage);
stat.usagePhotos = Number(stat.usagePhotos);
stat.usageVideos = Number(stat.usageVideos);
stat.quotaSizeInBytes = stat.quotaSizeInBytes;
}

Expand Down
14 changes: 14 additions & 0 deletions server/src/services/server.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ describe(ServerService.name, () => {
photos: 10,
videos: 11,
usage: 12_345,
usagePhotos: 1,
usageVideos: 11_345,
quotaSizeInBytes: 0,
},
{
Expand All @@ -193,6 +195,8 @@ describe(ServerService.name, () => {
photos: 10,
videos: 20,
usage: 123_456,
usagePhotos: 100,
usageVideos: 23_456,
quotaSizeInBytes: 0,
},
{
Expand All @@ -201,6 +205,8 @@ describe(ServerService.name, () => {
photos: 100,
videos: 0,
usage: 987_654,
usagePhotos: 900,
usageVideos: 87_654,
quotaSizeInBytes: 0,
},
]);
Expand All @@ -209,11 +215,15 @@ describe(ServerService.name, () => {
photos: 120,
videos: 31,
usage: 1_123_455,
usagePhotos: 1001,
usageVideos: 122_455,
usageByUser: [
{
photos: 10,
quotaSizeInBytes: 0,
usage: 12_345,
usagePhotos: 1,
usageVideos: 11_345,
userName: '1 User',
userId: 'user1',
videos: 11,
Expand All @@ -222,6 +232,8 @@ describe(ServerService.name, () => {
photos: 10,
quotaSizeInBytes: 0,
usage: 123_456,
usagePhotos: 100,
usageVideos: 23_456,
userName: '2 User',
userId: 'user2',
videos: 20,
Expand All @@ -230,6 +242,8 @@ describe(ServerService.name, () => {
photos: 100,
quotaSizeInBytes: 0,
usage: 987_654,
usagePhotos: 900,
usageVideos: 87_654,
userName: '3 User',
userId: 'user3',
videos: 0,
Expand Down
Loading

0 comments on commit ea6ac57

Please sign in to comment.