From f040c9fb38bb0e2327313fbc8f763b7280c2f466 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 6 Aug 2024 11:22:13 -0500 Subject: [PATCH] chore(server): remove get person asset limit (#11597) * chore(server): remover get person asset limit * sql * remove getPersonAsset endpoint * remove getPersonAsset endpoint * use search endpoint to get people * fix: server test * mobile linter * fix: server test * remove debuglog * deprecated endpoint * change page size on mobile * revert max size * fix test --- .../lib/providers/search/people.provider.dart | 3 - mobile/lib/services/person.service.dart | 36 ++++++++++-- mobile/openapi/README.md | 1 + mobile/openapi/lib/api/deprecated_api.dart | 56 +++++++++++++++++++ mobile/openapi/lib/api/people_api.dart | 7 ++- open-api/immich-openapi-specs.json | 10 +++- open-api/typescript-sdk/src/fetch-client.ts | 3 + server/src/controllers/person.controller.ts | 2 + 8 files changed, 107 insertions(+), 11 deletions(-) diff --git a/mobile/lib/providers/search/people.provider.dart b/mobile/lib/providers/search/people.provider.dart index 753b9f19bb..e2c243354b 100644 --- a/mobile/lib/providers/search/people.provider.dart +++ b/mobile/lib/providers/search/people.provider.dart @@ -22,9 +22,6 @@ Future> getAllPeople( Future personAssets(PersonAssetsRef ref, String personId) async { final PersonService personService = ref.read(personServiceProvider); final assets = await personService.getPersonAssets(personId); - if (assets == null) { - return RenderList.empty(); - } final settings = ref.read(appSettingsServiceProvider); final groupBy = diff --git a/mobile/lib/services/person.service.dart b/mobile/lib/services/person.service.dart index f35ae1a225..ddb61f5e48 100644 --- a/mobile/lib/services/person.service.dart +++ b/mobile/lib/services/person.service.dart @@ -30,15 +30,41 @@ class PersonService { } } - Future?> getPersonAssets(String id) async { + Future> getPersonAssets(String id) async { + List result = []; + var hasNext = true; + var currentPage = 1; + try { - final assets = await _apiService.peopleApi.getPersonAssets(id); - if (assets == null) return null; - return await _db.assets.getAllByRemoteId(assets.map((e) => e.id)); + while (hasNext) { + final response = await _apiService.searchApi.searchMetadata( + MetadataSearchDto( + personIds: [id], + page: currentPage, + size: 1000, + ), + ); + + if (response == null) { + break; + } + + if (response.assets.nextPage == null) { + hasNext = false; + } + + final assets = response.assets.items; + final mapAssets = + await _db.assets.getAllByRemoteId(assets.map((e) => e.id)); + result.addAll(mapAssets); + + currentPage++; + } } catch (error, stack) { _log.severe("Error while fetching person assets", error, stack); } - return null; + + return result; } Future updateName(String id, String name) async { diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 52e2e3cb40..89a4fb8e3b 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -117,6 +117,7 @@ Class | Method | HTTP request | Description *AuthenticationApi* | [**signUpAdmin**](doc//AuthenticationApi.md#signupadmin) | **POST** /auth/admin-sign-up | *AuthenticationApi* | [**validateAccessToken**](doc//AuthenticationApi.md#validateaccesstoken) | **POST** /auth/validateToken | *DeprecatedApi* | [**getAboutInfo**](doc//DeprecatedApi.md#getaboutinfo) | **GET** /server-info/about | +*DeprecatedApi* | [**getPersonAssets**](doc//DeprecatedApi.md#getpersonassets) | **GET** /people/{id}/assets | *DeprecatedApi* | [**getServerConfig**](doc//DeprecatedApi.md#getserverconfig) | **GET** /server-info/config | *DeprecatedApi* | [**getServerFeatures**](doc//DeprecatedApi.md#getserverfeatures) | **GET** /server-info/features | *DeprecatedApi* | [**getServerStatistics**](doc//DeprecatedApi.md#getserverstatistics) | **GET** /server-info/statistics | diff --git a/mobile/openapi/lib/api/deprecated_api.dart b/mobile/openapi/lib/api/deprecated_api.dart index 18518cca69..e1e09ae4b2 100644 --- a/mobile/openapi/lib/api/deprecated_api.dart +++ b/mobile/openapi/lib/api/deprecated_api.dart @@ -60,6 +60,62 @@ class DeprecatedApi { return null; } + /// This property was deprecated in v1.113.0 + /// + /// Note: This method returns the HTTP [Response]. + /// + /// Parameters: + /// + /// * [String] id (required): + Future getPersonAssetsWithHttpInfo(String id,) async { + // ignore: prefer_const_declarations + final path = r'/people/{id}/assets' + .replaceAll('{id}', id); + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + + return apiClient.invokeAPI( + path, + 'GET', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + /// This property was deprecated in v1.113.0 + /// + /// Parameters: + /// + /// * [String] id (required): + Future?> getPersonAssets(String id,) async { + final response = await getPersonAssetsWithHttpInfo(id,); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + final responseBody = await _decodeBodyBytes(response); + return (await apiClient.deserializeAsync(responseBody, 'List') as List) + .cast() + .toList(growable: false); + + } + return null; + } + /// This property was deprecated in v1.107.0 /// /// Note: This method returns the HTTP [Response]. diff --git a/mobile/openapi/lib/api/people_api.dart b/mobile/openapi/lib/api/people_api.dart index 9fe62f0841..95c4a2fd45 100644 --- a/mobile/openapi/lib/api/people_api.dart +++ b/mobile/openapi/lib/api/people_api.dart @@ -180,7 +180,10 @@ class PeopleApi { return null; } - /// Performs an HTTP 'GET /people/{id}/assets' operation and returns the [Response]. + /// This property was deprecated in v1.113.0 + /// + /// Note: This method returns the HTTP [Response]. + /// /// Parameters: /// /// * [String] id (required): @@ -210,6 +213,8 @@ class PeopleApi { ); } + /// This property was deprecated in v1.113.0 + /// /// Parameters: /// /// * [String] id (required): diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 6506a6293f..c30c43fabf 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -4115,6 +4115,8 @@ }, "/people/{id}/assets": { "get": { + "deprecated": true, + "description": "This property was deprecated in v1.113.0", "operationId": "getPersonAssets", "parameters": [ { @@ -4154,8 +4156,12 @@ } ], "tags": [ - "People" - ] + "People", + "Deprecated" + ], + "x-immich-lifecycle": { + "deprecatedAt": "v1.113.0" + } } }, "/people/{id}/merge": { diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index ec2a230f77..184052a4f6 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -2267,6 +2267,9 @@ export function updatePerson({ id, personUpdateDto }: { body: personUpdateDto }))); } +/** + * This property was deprecated in v1.113.0 + */ export function getPersonAssets({ id }: { id: string; }, opts?: Oazapfts.RequestOpts) { diff --git a/server/src/controllers/person.controller.ts b/server/src/controllers/person.controller.ts index 5f642dfa00..082d5ca46c 100644 --- a/server/src/controllers/person.controller.ts +++ b/server/src/controllers/person.controller.ts @@ -1,6 +1,7 @@ import { Body, Controller, Get, Inject, Next, Param, Post, Put, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; +import { EndpointLifecycle } from 'src/decorators'; import { BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; @@ -81,6 +82,7 @@ export class PersonController { await sendFile(res, next, () => this.service.getThumbnail(auth, id), this.logger); } + @EndpointLifecycle({ deprecatedAt: 'v1.113.0' }) @Get(':id/assets') @Authenticated() getPersonAssets(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise {