formatting
This commit is contained in:
parent
436f99c747
commit
1338c5fd59
19 changed files with 75 additions and 217 deletions
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
|
@ -213,7 +213,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: tensorchord/pgvecto-rs:pg14-v0.1.10
|
||||
image: tensorchord/pgvecto-rs:pg14-v0.1.11
|
||||
env:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_USER: postgres
|
||||
|
|
24
mobile/openapi/doc/SearchApi.md
generated
24
mobile/openapi/doc/SearchApi.md
generated
|
@ -66,7 +66,7 @@ This endpoint does not need any parameter.
|
|||
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
|
||||
|
||||
# **search**
|
||||
> SearchResponseDto search(q, query, clip, type, isFavorite, isArchived, exifInfoPeriodCity, exifInfoPeriodState, exifInfoPeriodCountry, exifInfoPeriodMake, exifInfoPeriodModel, exifInfoPeriodProjectionType, smartInfoPeriodObjects, smartInfoPeriodTags, recent, motion)
|
||||
> SearchResponseDto search(q, query, clip, type, recent, motion)
|
||||
|
||||
|
||||
|
||||
|
@ -93,21 +93,11 @@ final q = q_example; // String |
|
|||
final query = query_example; // String |
|
||||
final clip = true; // bool |
|
||||
final type = type_example; // String |
|
||||
final isFavorite = true; // bool |
|
||||
final isArchived = true; // bool |
|
||||
final exifInfoPeriodCity = exifInfoPeriodCity_example; // String |
|
||||
final exifInfoPeriodState = exifInfoPeriodState_example; // String |
|
||||
final exifInfoPeriodCountry = exifInfoPeriodCountry_example; // String |
|
||||
final exifInfoPeriodMake = exifInfoPeriodMake_example; // String |
|
||||
final exifInfoPeriodModel = exifInfoPeriodModel_example; // String |
|
||||
final exifInfoPeriodProjectionType = exifInfoPeriodProjectionType_example; // String |
|
||||
final smartInfoPeriodObjects = []; // List<String> |
|
||||
final smartInfoPeriodTags = []; // List<String> |
|
||||
final recent = true; // bool |
|
||||
final motion = true; // bool |
|
||||
|
||||
try {
|
||||
final result = api_instance.search(q, query, clip, type, isFavorite, isArchived, exifInfoPeriodCity, exifInfoPeriodState, exifInfoPeriodCountry, exifInfoPeriodMake, exifInfoPeriodModel, exifInfoPeriodProjectionType, smartInfoPeriodObjects, smartInfoPeriodTags, recent, motion);
|
||||
final result = api_instance.search(q, query, clip, type, recent, motion);
|
||||
print(result);
|
||||
} catch (e) {
|
||||
print('Exception when calling SearchApi->search: $e\n');
|
||||
|
@ -122,16 +112,6 @@ Name | Type | Description | Notes
|
|||
**query** | **String**| | [optional]
|
||||
**clip** | **bool**| | [optional]
|
||||
**type** | **String**| | [optional]
|
||||
**isFavorite** | **bool**| | [optional]
|
||||
**isArchived** | **bool**| | [optional]
|
||||
**exifInfoPeriodCity** | **String**| | [optional]
|
||||
**exifInfoPeriodState** | **String**| | [optional]
|
||||
**exifInfoPeriodCountry** | **String**| | [optional]
|
||||
**exifInfoPeriodMake** | **String**| | [optional]
|
||||
**exifInfoPeriodModel** | **String**| | [optional]
|
||||
**exifInfoPeriodProjectionType** | **String**| | [optional]
|
||||
**smartInfoPeriodObjects** | [**List<String>**](String.md)| | [optional] [default to const []]
|
||||
**smartInfoPeriodTags** | [**List<String>**](String.md)| | [optional] [default to const []]
|
||||
**recent** | **bool**| | [optional]
|
||||
**motion** | **bool**| | [optional]
|
||||
|
||||
|
|
76
mobile/openapi/lib/api/search_api.dart
generated
76
mobile/openapi/lib/api/search_api.dart
generated
|
@ -71,30 +71,10 @@ class SearchApi {
|
|||
///
|
||||
/// * [String] type:
|
||||
///
|
||||
/// * [bool] isFavorite:
|
||||
///
|
||||
/// * [bool] isArchived:
|
||||
///
|
||||
/// * [String] exifInfoPeriodCity:
|
||||
///
|
||||
/// * [String] exifInfoPeriodState:
|
||||
///
|
||||
/// * [String] exifInfoPeriodCountry:
|
||||
///
|
||||
/// * [String] exifInfoPeriodMake:
|
||||
///
|
||||
/// * [String] exifInfoPeriodModel:
|
||||
///
|
||||
/// * [String] exifInfoPeriodProjectionType:
|
||||
///
|
||||
/// * [List<String>] smartInfoPeriodObjects:
|
||||
///
|
||||
/// * [List<String>] smartInfoPeriodTags:
|
||||
///
|
||||
/// * [bool] recent:
|
||||
///
|
||||
/// * [bool] motion:
|
||||
Future<Response> searchWithHttpInfo({ String? q, String? query, bool? clip, String? type, bool? isFavorite, bool? isArchived, String? exifInfoPeriodCity, String? exifInfoPeriodState, String? exifInfoPeriodCountry, String? exifInfoPeriodMake, String? exifInfoPeriodModel, String? exifInfoPeriodProjectionType, List<String>? smartInfoPeriodObjects, List<String>? smartInfoPeriodTags, bool? recent, bool? motion, }) async {
|
||||
Future<Response> searchWithHttpInfo({ String? q, String? query, bool? clip, String? type, bool? recent, bool? motion, }) async {
|
||||
// ignore: prefer_const_declarations
|
||||
final path = r'/search';
|
||||
|
||||
|
@ -117,36 +97,6 @@ class SearchApi {
|
|||
if (type != null) {
|
||||
queryParams.addAll(_queryParams('', 'type', type));
|
||||
}
|
||||
if (isFavorite != null) {
|
||||
queryParams.addAll(_queryParams('', 'isFavorite', isFavorite));
|
||||
}
|
||||
if (isArchived != null) {
|
||||
queryParams.addAll(_queryParams('', 'isArchived', isArchived));
|
||||
}
|
||||
if (exifInfoPeriodCity != null) {
|
||||
queryParams.addAll(_queryParams('', 'exifInfo.city', exifInfoPeriodCity));
|
||||
}
|
||||
if (exifInfoPeriodState != null) {
|
||||
queryParams.addAll(_queryParams('', 'exifInfo.state', exifInfoPeriodState));
|
||||
}
|
||||
if (exifInfoPeriodCountry != null) {
|
||||
queryParams.addAll(_queryParams('', 'exifInfo.country', exifInfoPeriodCountry));
|
||||
}
|
||||
if (exifInfoPeriodMake != null) {
|
||||
queryParams.addAll(_queryParams('', 'exifInfo.make', exifInfoPeriodMake));
|
||||
}
|
||||
if (exifInfoPeriodModel != null) {
|
||||
queryParams.addAll(_queryParams('', 'exifInfo.model', exifInfoPeriodModel));
|
||||
}
|
||||
if (exifInfoPeriodProjectionType != null) {
|
||||
queryParams.addAll(_queryParams('', 'exifInfo.projectionType', exifInfoPeriodProjectionType));
|
||||
}
|
||||
if (smartInfoPeriodObjects != null) {
|
||||
queryParams.addAll(_queryParams('multi', 'smartInfo.objects', smartInfoPeriodObjects));
|
||||
}
|
||||
if (smartInfoPeriodTags != null) {
|
||||
queryParams.addAll(_queryParams('multi', 'smartInfo.tags', smartInfoPeriodTags));
|
||||
}
|
||||
if (recent != null) {
|
||||
queryParams.addAll(_queryParams('', 'recent', recent));
|
||||
}
|
||||
|
@ -178,31 +128,11 @@ class SearchApi {
|
|||
///
|
||||
/// * [String] type:
|
||||
///
|
||||
/// * [bool] isFavorite:
|
||||
///
|
||||
/// * [bool] isArchived:
|
||||
///
|
||||
/// * [String] exifInfoPeriodCity:
|
||||
///
|
||||
/// * [String] exifInfoPeriodState:
|
||||
///
|
||||
/// * [String] exifInfoPeriodCountry:
|
||||
///
|
||||
/// * [String] exifInfoPeriodMake:
|
||||
///
|
||||
/// * [String] exifInfoPeriodModel:
|
||||
///
|
||||
/// * [String] exifInfoPeriodProjectionType:
|
||||
///
|
||||
/// * [List<String>] smartInfoPeriodObjects:
|
||||
///
|
||||
/// * [List<String>] smartInfoPeriodTags:
|
||||
///
|
||||
/// * [bool] recent:
|
||||
///
|
||||
/// * [bool] motion:
|
||||
Future<SearchResponseDto?> search({ String? q, String? query, bool? clip, String? type, bool? isFavorite, bool? isArchived, String? exifInfoPeriodCity, String? exifInfoPeriodState, String? exifInfoPeriodCountry, String? exifInfoPeriodMake, String? exifInfoPeriodModel, String? exifInfoPeriodProjectionType, List<String>? smartInfoPeriodObjects, List<String>? smartInfoPeriodTags, bool? recent, bool? motion, }) async {
|
||||
final response = await searchWithHttpInfo( q: q, query: query, clip: clip, type: type, isFavorite: isFavorite, isArchived: isArchived, exifInfoPeriodCity: exifInfoPeriodCity, exifInfoPeriodState: exifInfoPeriodState, exifInfoPeriodCountry: exifInfoPeriodCountry, exifInfoPeriodMake: exifInfoPeriodMake, exifInfoPeriodModel: exifInfoPeriodModel, exifInfoPeriodProjectionType: exifInfoPeriodProjectionType, smartInfoPeriodObjects: smartInfoPeriodObjects, smartInfoPeriodTags: smartInfoPeriodTags, recent: recent, motion: motion, );
|
||||
Future<SearchResponseDto?> search({ String? q, String? query, bool? clip, String? type, bool? recent, bool? motion, }) async {
|
||||
final response = await searchWithHttpInfo( q: q, query: query, clip: clip, type: type, recent: recent, motion: motion, );
|
||||
if (response.statusCode >= HttpStatus.badRequest) {
|
||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||
}
|
||||
|
|
2
mobile/openapi/test/search_api_test.dart
generated
2
mobile/openapi/test/search_api_test.dart
generated
|
@ -22,7 +22,7 @@ void main() {
|
|||
// TODO
|
||||
});
|
||||
|
||||
//Future<SearchResponseDto> search({ String q, String query, bool clip, String type, bool isFavorite, bool isArchived, String exifInfoPeriodCity, String exifInfoPeriodState, String exifInfoPeriodCountry, String exifInfoPeriodMake, String exifInfoPeriodModel, String exifInfoPeriodProjectionType, List<String> smartInfoPeriodObjects, List<String> smartInfoPeriodTags, bool recent, bool motion }) async
|
||||
//Future<SearchResponseDto> search({ String q, String query, bool clip, String type, bool recent, bool motion }) async
|
||||
test('test search', () async {
|
||||
// TODO
|
||||
});
|
||||
|
|
|
@ -4567,92 +4567,6 @@
|
|||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "isFavorite",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "isArchived",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "exifInfo.city",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "exifInfo.state",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "exifInfo.country",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "exifInfo.make",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "exifInfo.model",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "exifInfo.projectionType",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "smartInfo.objects",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "smartInfo.tags",
|
||||
"required": false,
|
||||
"in": "query",
|
||||
"schema": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "recent",
|
||||
"required": false,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { AssetEntity, AssetFaceEntity, AssetType } from '@app/infra/entities';
|
||||
import { AssetEntity, AssetType } from '@app/infra/entities';
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { PersonWithFacesResponseDto } from '../../person/person.dto';
|
||||
import { TagResponseDto, mapTag } from '../../tag';
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { SystemConfig, SystemConfigEntity, SystemConfigKey } from '@app/infra/entities';
|
||||
import { SystemConfig, SystemConfigKey } from '@app/infra/entities';
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import {
|
||||
assetStub,
|
||||
|
@ -362,7 +362,7 @@ describe(JobService.name, () => {
|
|||
});
|
||||
}
|
||||
|
||||
const featureTests: Array<{ queue: QueueName, feature: FeatureFlag, configKey: SystemConfigKey}> = [
|
||||
const featureTests: Array<{ queue: QueueName; feature: FeatureFlag; configKey: SystemConfigKey }> = [
|
||||
{
|
||||
queue: QueueName.CLIP_ENCODING,
|
||||
feature: FeatureFlag.CLIP_ENCODE,
|
||||
|
@ -385,7 +385,7 @@ describe(JobService.name, () => {
|
|||
configMock.load.mockResolvedValue([{ key: configKey, value: false }]);
|
||||
jobMock.getQueueStatus.mockResolvedValue({ isActive: false, isPaused: false });
|
||||
|
||||
expect(sut.handleCommand(queue, { command: JobCommand.START, force: false })).rejects.toThrow();
|
||||
await expect(sut.handleCommand(queue, { command: JobCommand.START, force: false })).rejects.toThrow();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { SearchExploreItem } from '@app/domain';
|
||||
import { AssetEntity, AssetJobStatusEntity, AssetType, ExifEntity, SmartInfoEntity } from '@app/infra/entities';
|
||||
import { AssetEntity, AssetJobStatusEntity, AssetType, ExifEntity } from '@app/infra/entities';
|
||||
import { FindOptionsRelations } from 'typeorm';
|
||||
import { Paginated, PaginationOptions } from '../domain.util';
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { AssetEntity, AssetFaceEntity, SmartInfoEntity } from '@app/infra/entiti
|
|||
|
||||
export const ISmartInfoRepository = 'ISmartInfoRepository';
|
||||
|
||||
export type Embedding = number[];
|
||||
export type Embedding = number[];
|
||||
|
||||
export interface EmbeddingSearch {
|
||||
ownerId: string;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { AssetType } from '@app/infra/entities';
|
||||
import { Transform } from 'class-transformer';
|
||||
import { IsBoolean, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { IsBoolean, IsEnum, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { Optional, toBoolean } from '../../domain.util';
|
||||
|
||||
export class SearchDto {
|
||||
|
@ -17,6 +18,20 @@ export class SearchDto {
|
|||
@Optional()
|
||||
@Transform(toBoolean)
|
||||
clip?: boolean;
|
||||
|
||||
@IsEnum(AssetType)
|
||||
@Optional()
|
||||
type?: AssetType;
|
||||
|
||||
@IsBoolean()
|
||||
@Optional()
|
||||
@Transform(toBoolean)
|
||||
recent?: boolean;
|
||||
|
||||
@IsBoolean()
|
||||
@Optional()
|
||||
@Transform(toBoolean)
|
||||
motion?: boolean;
|
||||
}
|
||||
|
||||
export class SearchPeopleDto {
|
||||
|
|
|
@ -80,7 +80,7 @@ export class SearchService {
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
albums: {
|
||||
total: 0,
|
||||
|
|
|
@ -2,7 +2,7 @@ import { dataSource } from '@app/infra';
|
|||
import AsyncLock from 'async-lock';
|
||||
export enum DatabaseLock {
|
||||
GeodataImport = 100,
|
||||
CLIPDimSize = 512
|
||||
CLIPDimSize = 512,
|
||||
}
|
||||
|
||||
export async function acquireLock(lock: DatabaseLock): Promise<void> {
|
||||
|
@ -15,10 +15,12 @@ export async function releaseLock(lock: DatabaseLock): Promise<void> {
|
|||
|
||||
export const asyncLock = new AsyncLock();
|
||||
|
||||
export function RequireLock<T>(lock: DatabaseLock): Function {
|
||||
export function RequireLock<T>(
|
||||
lock: DatabaseLock,
|
||||
): (target: any, propertyKey: string, descriptor: PropertyDescriptor) => void {
|
||||
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor): void {
|
||||
const originalMethod = descriptor.value;
|
||||
descriptor.value = async function(...args: any[]): Promise<T> {
|
||||
descriptor.value = async function (...args: any[]): Promise<T> {
|
||||
if (!dataSource.isInitialized) {
|
||||
await dataSource.initialize();
|
||||
}
|
||||
|
@ -35,5 +37,5 @@ export function RequireLock<T>(lock: DatabaseLock): Function {
|
|||
|
||||
return res as any;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
export * from './database.config';
|
||||
export * from './database-locks';
|
||||
export * from './database.config';
|
||||
export * from './infra.config';
|
||||
export * from './infra.module';
|
||||
export * from './redis-io.adapter';
|
||||
|
|
|
@ -53,8 +53,8 @@ import {
|
|||
MoveRepository,
|
||||
PartnerRepository,
|
||||
PersonRepository,
|
||||
ServerInfoRepository,
|
||||
SearchRepository,
|
||||
ServerInfoRepository,
|
||||
SharedLinkRepository,
|
||||
SmartInfoRepository,
|
||||
SystemConfigRepository,
|
||||
|
|
|
@ -36,7 +36,7 @@ export async function paginate<Entity extends ObjectLiteral>(
|
|||
export const asVector = (embedding: number[], quote = false) =>
|
||||
quote ? `'[${embedding.join(',')}]'` : `[${embedding.join(',')}]`;
|
||||
|
||||
export const isValidInteger = (value: number, options: {min?: number, max?: number}): value is number => {
|
||||
export const isValidInteger = (value: number, options: { min?: number; max?: number }): value is number => {
|
||||
const { min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER } = options;
|
||||
return Number.isInteger(value) && value >= min && value <= max;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -5,8 +5,8 @@ import {
|
|||
ISystemMetadataRepository,
|
||||
ReverseGeocodeResult,
|
||||
} from '@app/domain';
|
||||
import { GeodataAdmin1Entity, GeodataAdmin2Entity, GeodataPlacesEntity, SystemMetadataKey } from '@app/infra/entities';
|
||||
import { DatabaseLock, RequireLock } from '@app/infra';
|
||||
import { GeodataAdmin1Entity, GeodataAdmin2Entity, GeodataPlacesEntity, SystemMetadataKey } from '@app/infra/entities';
|
||||
import { Inject, Logger } from '@nestjs/common';
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
import { DefaultReadTaskOptions, exiftool, Tags } from 'exiftool-vendored';
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { Embedding, EmbeddingSearch, ISmartInfoRepository } from '@app/domain';
|
||||
import { DatabaseLock, RequireLock, asyncLock } from '@app/infra';
|
||||
import { AssetEntity, AssetFaceEntity, SmartInfoEntity, SmartSearchEntity } from '@app/infra/entities';
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { AssetEntity, AssetFaceEntity, SmartInfoEntity, SmartSearchEntity } from '@app/infra/entities';
|
||||
import { asVector, isValidInteger } from '../infra.utils';
|
||||
import { DatabaseLock, RequireLock, asyncLock } from '@app/infra';
|
||||
|
||||
@Injectable()
|
||||
export class SmartInfoRepository implements ISmartInfoRepository {
|
||||
|
@ -46,12 +46,7 @@ export class SmartInfoRepository implements ISmartInfoRepository {
|
|||
return results;
|
||||
}
|
||||
|
||||
async searchFaces({
|
||||
ownerId,
|
||||
embedding,
|
||||
numResults,
|
||||
maxDistance,
|
||||
}: EmbeddingSearch): Promise<AssetFaceEntity[]> {
|
||||
async searchFaces({ ownerId, embedding, numResults, maxDistance }: EmbeddingSearch): Promise<AssetFaceEntity[]> {
|
||||
if (!isValidInteger(numResults, { min: 1 })) {
|
||||
throw new Error(`Invalid value for 'numResults': ${numResults}`);
|
||||
}
|
||||
|
@ -84,7 +79,9 @@ export class SmartInfoRepository implements ISmartInfoRepository {
|
|||
|
||||
async upsert(smartInfo: Partial<SmartInfoEntity>, embedding?: Embedding): Promise<void> {
|
||||
await this.repository.upsert(smartInfo, { conflictPaths: ['assetId'] });
|
||||
if (!smartInfo.assetId || !embedding) return;
|
||||
if (!smartInfo.assetId || !embedding) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.upsertEmbedding(smartInfo.assetId, embedding);
|
||||
}
|
||||
|
@ -115,8 +112,10 @@ export class SmartInfoRepository implements ISmartInfoRepository {
|
|||
throw new Error(`Invalid CLIP dimension size: ${dimSize}`);
|
||||
}
|
||||
|
||||
if (this.curDimSize === dimSize) return;
|
||||
|
||||
if (this.curDimSize === dimSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.log(`Current dimension size is ${this.curDimSize}. Updating CLIP dimension size to ${dimSize}.`);
|
||||
|
||||
await this.smartSearchRepository.manager.transaction(async (manager) => {
|
||||
|
@ -142,7 +141,9 @@ export class SmartInfoRepository implements ISmartInfoRepository {
|
|||
|
||||
@RequireLock(DatabaseLock.CLIPDimSize)
|
||||
private async getDimSize(): Promise<void> {
|
||||
if (this.curDimSize != null) return;
|
||||
if (this.curDimSize != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const res = await this.smartSearchRepository.manager.query(`
|
||||
SELECT atttypmod as dimsize
|
||||
|
|
|
@ -37,7 +37,11 @@ describe(`${PersonController.name}`, () => {
|
|||
name: 'visible_person',
|
||||
thumbnailPath: '/thumbnail/face_asset',
|
||||
});
|
||||
await personRepository.createFace({ assetId: faceAsset.id, personId: visiblePerson.id, embedding: Array.from({length: 512}, Math.random) });
|
||||
await personRepository.createFace({
|
||||
assetId: faceAsset.id,
|
||||
personId: visiblePerson.id,
|
||||
embedding: Array.from({ length: 512 }, Math.random),
|
||||
});
|
||||
|
||||
hiddenPerson = await personRepository.create({
|
||||
ownerId: loginResponse.userId,
|
||||
|
@ -45,7 +49,11 @@ describe(`${PersonController.name}`, () => {
|
|||
isHidden: true,
|
||||
thumbnailPath: '/thumbnail/face_asset',
|
||||
});
|
||||
await personRepository.createFace({ assetId: faceAsset.id, personId: hiddenPerson.id, embedding: Array.from({length: 512}, Math.random) });
|
||||
await personRepository.createFace({
|
||||
assetId: faceAsset.id,
|
||||
personId: hiddenPerson.id,
|
||||
embedding: Array.from({ length: 512 }, Math.random),
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /person', () => {
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
import { AssetResponseDto, IAssetRepository, ISmartInfoRepository, LibraryResponseDto, LoginResponseDto, mapAsset } from '@app/domain';
|
||||
import {
|
||||
AssetResponseDto,
|
||||
IAssetRepository,
|
||||
ISmartInfoRepository,
|
||||
LibraryResponseDto,
|
||||
LoginResponseDto,
|
||||
mapAsset,
|
||||
} from '@app/domain';
|
||||
import { SearchController } from '@app/immich';
|
||||
import { INestApplication } from '@nestjs/common';
|
||||
import { api } from '@test/api';
|
||||
|
@ -47,7 +54,8 @@ describe(`${SearchController.name}`, () => {
|
|||
});
|
||||
await smartInfoRepository.upsert(
|
||||
{ assetId, objects: ['car', 'tree'], tags: ['accident'] },
|
||||
Array.from({ length: 512 }, Math.random));
|
||||
Array.from({ length: 512 }, Math.random),
|
||||
);
|
||||
const assetWithMetadata = await assetRepository.getById(assetId, { exifInfo: true, smartInfo: true });
|
||||
if (!assetWithMetadata) {
|
||||
throw new Error('Asset not found');
|
||||
|
|
Loading…
Reference in a new issue