mirror of
https://github.com/immich-app/immich.git
synced 2025-07-31 15:08:44 -04:00
refactor: event names (#19945)
This commit is contained in:
parent
351701c4d6
commit
920d7de349
@ -73,11 +73,11 @@ class BaseModule implements OnModuleInit, OnModuleDestroy {
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.eventRepository.setup({ services });
|
this.eventRepository.setup({ services });
|
||||||
await this.eventRepository.emit('app.bootstrap');
|
await this.eventRepository.emit('AppBootstrap');
|
||||||
}
|
}
|
||||||
|
|
||||||
async onModuleDestroy() {
|
async onModuleDestroy() {
|
||||||
await this.eventRepository.emit('app.shutdown');
|
await this.eventRepository.emit('AppShutdown');
|
||||||
await teardownTelemetry();
|
await teardownTelemetry();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -35,59 +35,59 @@ type Item<T extends EmitEvent> = {
|
|||||||
|
|
||||||
type EventMap = {
|
type EventMap = {
|
||||||
// app events
|
// app events
|
||||||
'app.bootstrap': [];
|
AppBootstrap: [];
|
||||||
'app.shutdown': [];
|
AppShutdown: [];
|
||||||
|
|
||||||
'config.init': [{ newConfig: SystemConfig }];
|
ConfigInit: [{ newConfig: SystemConfig }];
|
||||||
// config events
|
// config events
|
||||||
'config.update': [
|
ConfigUpdate: [
|
||||||
{
|
{
|
||||||
newConfig: SystemConfig;
|
newConfig: SystemConfig;
|
||||||
oldConfig: SystemConfig;
|
oldConfig: SystemConfig;
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
'config.validate': [{ newConfig: SystemConfig; oldConfig: SystemConfig }];
|
ConfigValidate: [{ newConfig: SystemConfig; oldConfig: SystemConfig }];
|
||||||
|
|
||||||
// album events
|
// album events
|
||||||
'album.update': [{ id: string; recipientId: string }];
|
AlbumUpdate: [{ id: string; recipientId: string }];
|
||||||
'album.invite': [{ id: string; userId: string }];
|
AlbumInvite: [{ id: string; userId: string }];
|
||||||
|
|
||||||
// asset events
|
// asset events
|
||||||
'asset.tag': [{ assetId: string }];
|
AssetTag: [{ assetId: string }];
|
||||||
'asset.untag': [{ assetId: string }];
|
AssetUntag: [{ assetId: string }];
|
||||||
'asset.hide': [{ assetId: string; userId: string }];
|
AssetHide: [{ assetId: string; userId: string }];
|
||||||
'asset.show': [{ assetId: string; userId: string }];
|
AssetShow: [{ assetId: string; userId: string }];
|
||||||
'asset.trash': [{ assetId: string; userId: string }];
|
AssetTrash: [{ assetId: string; userId: string }];
|
||||||
'asset.delete': [{ assetId: string; userId: string }];
|
AssetDelete: [{ assetId: string; userId: string }];
|
||||||
'asset.metadataExtracted': [{ assetId: string; userId: string; source?: JobSource }];
|
AssetMetadataExtracted: [{ assetId: string; userId: string; source?: JobSource }];
|
||||||
|
|
||||||
// asset bulk events
|
// asset bulk events
|
||||||
'assets.trash': [{ assetIds: string[]; userId: string }];
|
AssetTrashAll: [{ assetIds: string[]; userId: string }];
|
||||||
'assets.delete': [{ assetIds: string[]; userId: string }];
|
AssetDeleteAll: [{ assetIds: string[]; userId: string }];
|
||||||
'assets.restore': [{ assetIds: string[]; userId: string }];
|
AssetRestoreAll: [{ assetIds: string[]; userId: string }];
|
||||||
|
|
||||||
'job.start': [QueueName, JobItem];
|
JobStart: [QueueName, JobItem];
|
||||||
'job.failed': [{ job: JobItem; error: Error | any }];
|
JobFailed: [{ job: JobItem; error: Error | any }];
|
||||||
|
|
||||||
// session events
|
// session events
|
||||||
'session.delete': [{ sessionId: string }];
|
SessionDelete: [{ sessionId: string }];
|
||||||
|
|
||||||
// stack events
|
// stack events
|
||||||
'stack.create': [{ stackId: string; userId: string }];
|
StackCreate: [{ stackId: string; userId: string }];
|
||||||
'stack.update': [{ stackId: string; userId: string }];
|
StackUpdate: [{ stackId: string; userId: string }];
|
||||||
'stack.delete': [{ stackId: string; userId: string }];
|
StackDelete: [{ stackId: string; userId: string }];
|
||||||
|
|
||||||
// stack bulk events
|
// stack bulk events
|
||||||
'stacks.delete': [{ stackIds: string[]; userId: string }];
|
StackDeleteAll: [{ stackIds: string[]; userId: string }];
|
||||||
|
|
||||||
// user events
|
// user events
|
||||||
'user.signup': [{ notify: boolean; id: string; tempPassword?: string }];
|
UserSignup: [{ notify: boolean; id: string; tempPassword?: string }];
|
||||||
|
|
||||||
// websocket events
|
// websocket events
|
||||||
'websocket.connect': [{ userId: string }];
|
WebsocketConnect: [{ userId: string }];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const serverEvents = ['config.update'] as const;
|
export const serverEvents = ['ConfigUpdate'] as const;
|
||||||
export type ServerEvents = (typeof serverEvents)[number];
|
export type ServerEvents = (typeof serverEvents)[number];
|
||||||
|
|
||||||
export type EmitEvent = keyof EventMap;
|
export type EmitEvent = keyof EventMap;
|
||||||
@ -213,7 +213,7 @@ export class EventRepository implements OnGatewayConnection, OnGatewayDisconnect
|
|||||||
if (auth.session) {
|
if (auth.session) {
|
||||||
await client.join(auth.session.id);
|
await client.join(auth.session.id);
|
||||||
}
|
}
|
||||||
await this.onEvent({ name: 'websocket.connect', args: [{ userId: auth.user.id }], server: false });
|
await this.onEvent({ name: 'WebsocketConnect', args: [{ userId: auth.user.id }], server: false });
|
||||||
} catch (error: Error | any) {
|
} catch (error: Error | any) {
|
||||||
this.logger.error(`Websocket connection error: ${error}`, error?.stack);
|
this.logger.error(`Websocket connection error: ${error}`, error?.stack);
|
||||||
client.emit('error', 'unauthorized');
|
client.emit('error', 'unauthorized');
|
||||||
|
@ -89,7 +89,7 @@ export class JobRepository {
|
|||||||
this.logger.debug(`Starting worker for queue: ${queueName}`);
|
this.logger.debug(`Starting worker for queue: ${queueName}`);
|
||||||
this.workers[queueName] = new Worker(
|
this.workers[queueName] = new Worker(
|
||||||
queueName,
|
queueName,
|
||||||
(job) => this.eventRepository.emit('job.start', queueName, job as JobItem),
|
(job) => this.eventRepository.emit('JobStart', queueName, job as JobItem),
|
||||||
{ ...bull.config, concurrency: 1 },
|
{ ...bull.config, concurrency: 1 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ describe(AlbumService.name, () => {
|
|||||||
expect(mocks.user.get).toHaveBeenCalledWith('user-id', {});
|
expect(mocks.user.get).toHaveBeenCalledWith('user-id', {});
|
||||||
expect(mocks.user.getMetadata).toHaveBeenCalledWith(authStub.admin.user.id);
|
expect(mocks.user.getMetadata).toHaveBeenCalledWith(authStub.admin.user.id);
|
||||||
expect(mocks.access.asset.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['123']), false);
|
expect(mocks.access.asset.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['123']), false);
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('album.invite', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AlbumInvite', {
|
||||||
id: albumStub.empty.id,
|
id: albumStub.empty.id,
|
||||||
userId: 'user-id',
|
userId: 'user-id',
|
||||||
});
|
});
|
||||||
@ -209,7 +209,7 @@ describe(AlbumService.name, () => {
|
|||||||
expect(mocks.user.get).toHaveBeenCalledWith('user-id', {});
|
expect(mocks.user.get).toHaveBeenCalledWith('user-id', {});
|
||||||
expect(mocks.user.getMetadata).toHaveBeenCalledWith(authStub.admin.user.id);
|
expect(mocks.user.getMetadata).toHaveBeenCalledWith(authStub.admin.user.id);
|
||||||
expect(mocks.access.asset.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['123']), false);
|
expect(mocks.access.asset.checkOwnerAccess).toHaveBeenCalledWith(authStub.admin.user.id, new Set(['123']), false);
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('album.invite', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AlbumInvite', {
|
||||||
id: albumStub.empty.id,
|
id: albumStub.empty.id,
|
||||||
userId: 'user-id',
|
userId: 'user-id',
|
||||||
});
|
});
|
||||||
@ -413,7 +413,7 @@ describe(AlbumService.name, () => {
|
|||||||
usersId: authStub.user2.user.id,
|
usersId: authStub.user2.user.id,
|
||||||
albumsId: albumStub.sharedWithAdmin.id,
|
albumsId: albumStub.sharedWithAdmin.id,
|
||||||
});
|
});
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('album.invite', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AlbumInvite', {
|
||||||
id: albumStub.sharedWithAdmin.id,
|
id: albumStub.sharedWithAdmin.id,
|
||||||
userId: userStub.user2.id,
|
userId: userStub.user2.id,
|
||||||
});
|
});
|
||||||
@ -662,7 +662,7 @@ describe(AlbumService.name, () => {
|
|||||||
albumThumbnailAssetId: 'asset-1',
|
albumThumbnailAssetId: 'asset-1',
|
||||||
});
|
});
|
||||||
expect(mocks.album.addAssetIds).toHaveBeenCalledWith('album-123', ['asset-1', 'asset-2', 'asset-3']);
|
expect(mocks.album.addAssetIds).toHaveBeenCalledWith('album-123', ['asset-1', 'asset-2', 'asset-3']);
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('album.update', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AlbumUpdate', {
|
||||||
id: 'album-123',
|
id: 'album-123',
|
||||||
recipientId: 'admin_id',
|
recipientId: 'admin_id',
|
||||||
});
|
});
|
||||||
|
@ -122,7 +122,7 @@ export class AlbumService extends BaseService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (const { userId } of albumUsers) {
|
for (const { userId } of albumUsers) {
|
||||||
await this.eventRepository.emit('album.invite', { id: album.id, userId });
|
await this.eventRepository.emit('AlbumInvite', { id: album.id, userId });
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapAlbumWithAssets(album);
|
return mapAlbumWithAssets(album);
|
||||||
@ -179,7 +179,7 @@ export class AlbumService extends BaseService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (const recipientId of allUsersExceptUs) {
|
for (const recipientId of allUsersExceptUs) {
|
||||||
await this.eventRepository.emit('album.update', { id, recipientId });
|
await this.eventRepository.emit('AlbumUpdate', { id, recipientId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +225,7 @@ export class AlbumService extends BaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await this.albumUserRepository.create({ usersId: userId, albumsId: id, role });
|
await this.albumUserRepository.create({ usersId: userId, albumsId: id, role });
|
||||||
await this.eventRepository.emit('album.invite', { id, userId });
|
await this.eventRepository.emit('AlbumInvite', { id, userId });
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.findOrFail(id, { withAssets: true }).then(mapAlbumWithoutAssets);
|
return this.findOrFail(id, { withAssets: true }).then(mapAlbumWithoutAssets);
|
||||||
|
@ -180,7 +180,7 @@ export class AssetMediaService extends BaseService {
|
|||||||
const copiedPhoto = await this.createCopy(asset);
|
const copiedPhoto = await this.createCopy(asset);
|
||||||
// and immediate trash it
|
// and immediate trash it
|
||||||
await this.assetRepository.updateAll([copiedPhoto.id], { deletedAt: new Date(), status: AssetStatus.TRASHED });
|
await this.assetRepository.updateAll([copiedPhoto.id], { deletedAt: new Date(), status: AssetStatus.TRASHED });
|
||||||
await this.eventRepository.emit('asset.trash', { assetId: copiedPhoto.id, userId: auth.user.id });
|
await this.eventRepository.emit('AssetTrash', { assetId: copiedPhoto.id, userId: auth.user.id });
|
||||||
|
|
||||||
await this.userRepository.updateUsage(auth.user.id, file.size);
|
await this.userRepository.updateUsage(auth.user.id, file.size);
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ describe(AssetService.name, () => {
|
|||||||
id: assetStub.livePhotoMotionAsset.id,
|
id: assetStub.livePhotoMotionAsset.id,
|
||||||
visibility: AssetVisibility.TIMELINE,
|
visibility: AssetVisibility.TIMELINE,
|
||||||
});
|
});
|
||||||
expect(mocks.event.emit).not.toHaveBeenCalledWith('asset.show', {
|
expect(mocks.event.emit).not.toHaveBeenCalledWith('AssetShow', {
|
||||||
assetId: assetStub.livePhotoMotionAsset.id,
|
assetId: assetStub.livePhotoMotionAsset.id,
|
||||||
userId: userStub.admin.id,
|
userId: userStub.admin.id,
|
||||||
});
|
});
|
||||||
@ -279,7 +279,7 @@ describe(AssetService.name, () => {
|
|||||||
id: assetStub.livePhotoMotionAsset.id,
|
id: assetStub.livePhotoMotionAsset.id,
|
||||||
visibility: AssetVisibility.TIMELINE,
|
visibility: AssetVisibility.TIMELINE,
|
||||||
});
|
});
|
||||||
expect(mocks.event.emit).not.toHaveBeenCalledWith('asset.show', {
|
expect(mocks.event.emit).not.toHaveBeenCalledWith('AssetShow', {
|
||||||
assetId: assetStub.livePhotoMotionAsset.id,
|
assetId: assetStub.livePhotoMotionAsset.id,
|
||||||
userId: userStub.admin.id,
|
userId: userStub.admin.id,
|
||||||
});
|
});
|
||||||
@ -303,7 +303,7 @@ describe(AssetService.name, () => {
|
|||||||
id: assetStub.livePhotoMotionAsset.id,
|
id: assetStub.livePhotoMotionAsset.id,
|
||||||
visibility: AssetVisibility.TIMELINE,
|
visibility: AssetVisibility.TIMELINE,
|
||||||
});
|
});
|
||||||
expect(mocks.event.emit).not.toHaveBeenCalledWith('asset.show', {
|
expect(mocks.event.emit).not.toHaveBeenCalledWith('AssetShow', {
|
||||||
assetId: assetStub.livePhotoMotionAsset.id,
|
assetId: assetStub.livePhotoMotionAsset.id,
|
||||||
userId: userStub.admin.id,
|
userId: userStub.admin.id,
|
||||||
});
|
});
|
||||||
@ -327,7 +327,7 @@ describe(AssetService.name, () => {
|
|||||||
id: assetStub.livePhotoMotionAsset.id,
|
id: assetStub.livePhotoMotionAsset.id,
|
||||||
visibility: AssetVisibility.HIDDEN,
|
visibility: AssetVisibility.HIDDEN,
|
||||||
});
|
});
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('asset.hide', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AssetHide', {
|
||||||
assetId: assetStub.livePhotoMotionAsset.id,
|
assetId: assetStub.livePhotoMotionAsset.id,
|
||||||
userId: userStub.admin.id,
|
userId: userStub.admin.id,
|
||||||
});
|
});
|
||||||
@ -360,7 +360,7 @@ describe(AssetService.name, () => {
|
|||||||
id: assetStub.livePhotoMotionAsset.id,
|
id: assetStub.livePhotoMotionAsset.id,
|
||||||
visibility: assetStub.livePhotoStillAsset.visibility,
|
visibility: assetStub.livePhotoStillAsset.visibility,
|
||||||
});
|
});
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('asset.show', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AssetShow', {
|
||||||
assetId: assetStub.livePhotoMotionAsset.id,
|
assetId: assetStub.livePhotoMotionAsset.id,
|
||||||
userId: userStub.admin.id,
|
userId: userStub.admin.id,
|
||||||
});
|
});
|
||||||
@ -484,7 +484,7 @@ describe(AssetService.name, () => {
|
|||||||
|
|
||||||
await sut.deleteAll(authStub.user1, { ids: ['asset1', 'asset2'], force: true });
|
await sut.deleteAll(authStub.user1, { ids: ['asset1', 'asset2'], force: true });
|
||||||
|
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('assets.delete', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AssetDeleteAll', {
|
||||||
assetIds: ['asset1', 'asset2'],
|
assetIds: ['asset1', 'asset2'],
|
||||||
userId: 'user-id',
|
userId: 'user-id',
|
||||||
});
|
});
|
||||||
|
@ -208,7 +208,7 @@ export class AssetService extends BaseService {
|
|||||||
await this.userRepository.updateUsage(asset.ownerId, -(asset.exifInfo?.fileSizeInByte || 0));
|
await this.userRepository.updateUsage(asset.ownerId, -(asset.exifInfo?.fileSizeInByte || 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.eventRepository.emit('asset.delete', { assetId: id, userId: asset.ownerId });
|
await this.eventRepository.emit('AssetDelete', { assetId: id, userId: asset.ownerId });
|
||||||
|
|
||||||
// delete the motion if it is not used by another asset
|
// delete the motion if it is not used by another asset
|
||||||
if (asset.livePhotoVideoId) {
|
if (asset.livePhotoVideoId) {
|
||||||
@ -241,7 +241,10 @@ export class AssetService extends BaseService {
|
|||||||
deletedAt: new Date(),
|
deletedAt: new Date(),
|
||||||
status: force ? AssetStatus.DELETED : AssetStatus.TRASHED,
|
status: force ? AssetStatus.DELETED : AssetStatus.TRASHED,
|
||||||
});
|
});
|
||||||
await this.eventRepository.emit(force ? 'assets.delete' : 'assets.trash', { assetIds: ids, userId: auth.user.id });
|
await this.eventRepository.emit(force ? 'AssetDeleteAll' : 'AssetTrashAll', {
|
||||||
|
assetIds: ids,
|
||||||
|
userId: auth.user.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(auth: AuthDto, dto: AssetJobsDto) {
|
async run(auth: AuthDto, dto: AssetJobsDto) {
|
||||||
|
@ -179,7 +179,7 @@ describe(AuthService.name, () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(mocks.session.delete).toHaveBeenCalledWith('token123');
|
expect(mocks.session.delete).toHaveBeenCalledWith('token123');
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('session.delete', { sessionId: 'token123' });
|
expect(mocks.event.emit).toHaveBeenCalledWith('SessionDelete', { sessionId: 'token123' });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return the default redirect if auth type is OAUTH but oauth is not enabled', async () => {
|
it('should return the default redirect if auth type is OAUTH but oauth is not enabled', async () => {
|
||||||
|
@ -80,7 +80,7 @@ export class AuthService extends BaseService {
|
|||||||
async logout(auth: AuthDto, authType: AuthType): Promise<LogoutResponseDto> {
|
async logout(auth: AuthDto, authType: AuthType): Promise<LogoutResponseDto> {
|
||||||
if (auth.session) {
|
if (auth.session) {
|
||||||
await this.sessionRepository.delete(auth.session.id);
|
await this.sessionRepository.delete(auth.session.id);
|
||||||
await this.eventRepository.emit('session.delete', { sessionId: auth.session.id });
|
await this.eventRepository.emit('SessionDelete', { sessionId: auth.session.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -14,12 +14,12 @@ import { handlePromiseError } from 'src/utils/misc';
|
|||||||
export class BackupService extends BaseService {
|
export class BackupService extends BaseService {
|
||||||
private backupLock = false;
|
private backupLock = false;
|
||||||
|
|
||||||
@OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] })
|
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.MICROSERVICES] })
|
||||||
async onConfigInit({
|
async onConfigInit({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
backup: { database },
|
backup: { database },
|
||||||
},
|
},
|
||||||
}: ArgOf<'config.init'>) {
|
}: ArgOf<'ConfigInit'>) {
|
||||||
this.backupLock = await this.databaseRepository.tryLock(DatabaseLock.BackupDatabase);
|
this.backupLock = await this.databaseRepository.tryLock(DatabaseLock.BackupDatabase);
|
||||||
|
|
||||||
if (this.backupLock) {
|
if (this.backupLock) {
|
||||||
@ -32,8 +32,8 @@ export class BackupService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.update', server: true })
|
@OnEvent({ name: 'ConfigUpdate', server: true })
|
||||||
onConfigUpdate({ newConfig: { backup } }: ArgOf<'config.update'>) {
|
onConfigUpdate({ newConfig: { backup } }: ArgOf<'ConfigUpdate'>) {
|
||||||
if (!this.backupLock) {
|
if (!this.backupLock) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ const messages = {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DatabaseService extends BaseService {
|
export class DatabaseService extends BaseService {
|
||||||
@OnEvent({ name: 'app.bootstrap', priority: BootstrapEventPriority.DatabaseService })
|
@OnEvent({ name: 'AppBootstrap', priority: BootstrapEventPriority.DatabaseService })
|
||||||
async onBootstrap() {
|
async onBootstrap() {
|
||||||
const version = await this.databaseRepository.getPostgresVersion();
|
const version = await this.databaseRepository.getPostgresVersion();
|
||||||
const current = semver.coerce(version);
|
const current = semver.coerce(version);
|
||||||
|
@ -67,8 +67,8 @@ export class JobService extends BaseService {
|
|||||||
private services: ClassConstructor<unknown>[] = [];
|
private services: ClassConstructor<unknown>[] = [];
|
||||||
private nightlyJobsLock = false;
|
private nightlyJobsLock = false;
|
||||||
|
|
||||||
@OnEvent({ name: 'config.init' })
|
@OnEvent({ name: 'ConfigInit' })
|
||||||
async onConfigInit({ newConfig: config }: ArgOf<'config.init'>) {
|
async onConfigInit({ newConfig: config }: ArgOf<'ConfigInit'>) {
|
||||||
if (this.worker === ImmichWorker.MICROSERVICES) {
|
if (this.worker === ImmichWorker.MICROSERVICES) {
|
||||||
this.updateQueueConcurrency(config);
|
this.updateQueueConcurrency(config);
|
||||||
return;
|
return;
|
||||||
@ -87,8 +87,8 @@ export class JobService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.update', server: true })
|
@OnEvent({ name: 'ConfigUpdate', server: true })
|
||||||
onConfigUpdate({ newConfig: config }: ArgOf<'config.update'>) {
|
onConfigUpdate({ newConfig: config }: ArgOf<'ConfigUpdate'>) {
|
||||||
if (this.worker === ImmichWorker.MICROSERVICES) {
|
if (this.worker === ImmichWorker.MICROSERVICES) {
|
||||||
this.updateQueueConcurrency(config);
|
this.updateQueueConcurrency(config);
|
||||||
return;
|
return;
|
||||||
@ -101,7 +101,7 @@ export class JobService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'app.bootstrap', priority: BootstrapEventPriority.JobService })
|
@OnEvent({ name: 'AppBootstrap', priority: BootstrapEventPriority.JobService })
|
||||||
onBootstrap() {
|
onBootstrap() {
|
||||||
this.jobRepository.setup(this.services);
|
this.jobRepository.setup(this.services);
|
||||||
if (this.worker === ImmichWorker.MICROSERVICES) {
|
if (this.worker === ImmichWorker.MICROSERVICES) {
|
||||||
@ -243,8 +243,8 @@ export class JobService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'job.start' })
|
@OnEvent({ name: 'JobStart' })
|
||||||
async onJobStart(...[queueName, job]: ArgsOf<'job.start'>) {
|
async onJobStart(...[queueName, job]: ArgsOf<'JobStart'>) {
|
||||||
const queueMetric = `immich.queues.${snakeCase(queueName)}.active`;
|
const queueMetric = `immich.queues.${snakeCase(queueName)}.active`;
|
||||||
this.telemetryRepository.jobs.addToGauge(queueMetric, 1);
|
this.telemetryRepository.jobs.addToGauge(queueMetric, 1);
|
||||||
try {
|
try {
|
||||||
@ -255,7 +255,7 @@ export class JobService extends BaseService {
|
|||||||
await this.onDone(job);
|
await this.onDone(job);
|
||||||
}
|
}
|
||||||
} catch (error: Error | any) {
|
} catch (error: Error | any) {
|
||||||
await this.eventRepository.emit('job.failed', { job, error });
|
await this.eventRepository.emit('JobFailed', { job, error });
|
||||||
} finally {
|
} finally {
|
||||||
this.telemetryRepository.jobs.addToGauge(queueMetric, -1);
|
this.telemetryRepository.jobs.addToGauge(queueMetric, -1);
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,12 @@ export class LibraryService extends BaseService {
|
|||||||
private lock = false;
|
private lock = false;
|
||||||
private watchers: Record<string, () => Promise<void>> = {};
|
private watchers: Record<string, () => Promise<void>> = {};
|
||||||
|
|
||||||
@OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] })
|
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.MICROSERVICES] })
|
||||||
async onConfigInit({
|
async onConfigInit({
|
||||||
newConfig: {
|
newConfig: {
|
||||||
library: { watch, scan },
|
library: { watch, scan },
|
||||||
},
|
},
|
||||||
}: ArgOf<'config.init'>) {
|
}: ArgOf<'ConfigInit'>) {
|
||||||
// This ensures that library watching only occurs in one microservice
|
// This ensures that library watching only occurs in one microservice
|
||||||
this.lock = await this.databaseRepository.tryLock(DatabaseLock.Library);
|
this.lock = await this.databaseRepository.tryLock(DatabaseLock.Library);
|
||||||
|
|
||||||
@ -58,8 +58,8 @@ export class LibraryService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.update', server: true })
|
@OnEvent({ name: 'ConfigUpdate', server: true })
|
||||||
async onConfigUpdate({ newConfig: { library } }: ArgOf<'config.update'>) {
|
async onConfigUpdate({ newConfig: { library } }: ArgOf<'ConfigUpdate'>) {
|
||||||
if (!this.lock) {
|
if (!this.lock) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -155,7 +155,7 @@ export class LibraryService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'app.shutdown' })
|
@OnEvent({ name: 'AppShutdown' })
|
||||||
async onShutdown() {
|
async onShutdown() {
|
||||||
await this.unwatchAll();
|
await this.unwatchAll();
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ interface UpsertFileOptions {
|
|||||||
export class MediaService extends BaseService {
|
export class MediaService extends BaseService {
|
||||||
videoInterfaces: VideoInterfaces = { dri: [], mali: false };
|
videoInterfaces: VideoInterfaces = { dri: [], mali: false };
|
||||||
|
|
||||||
@OnEvent({ name: 'app.bootstrap' })
|
@OnEvent({ name: 'AppBootstrap' })
|
||||||
async onBootstrap() {
|
async onBootstrap() {
|
||||||
const [dri, mali] = await Promise.all([this.getDevices(), this.hasMaliOpenCL()]);
|
const [dri, mali] = await Promise.all([this.getDevices(), this.hasMaliOpenCL()]);
|
||||||
this.videoInterfaces = { dri, mali };
|
this.videoInterfaces = { dri, mali };
|
||||||
|
@ -1368,7 +1368,7 @@ describe(MetadataService.name, () => {
|
|||||||
|
|
||||||
await sut.handleMetadataExtraction({ id: assetStub.livePhotoStillAsset.id });
|
await sut.handleMetadataExtraction({ id: assetStub.livePhotoStillAsset.id });
|
||||||
|
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('asset.hide', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AssetHide', {
|
||||||
userId: assetStub.livePhotoMotionAsset.ownerId,
|
userId: assetStub.livePhotoMotionAsset.ownerId,
|
||||||
assetId: assetStub.livePhotoMotionAsset.id,
|
assetId: assetStub.livePhotoMotionAsset.id,
|
||||||
});
|
});
|
||||||
@ -1384,7 +1384,7 @@ describe(MetadataService.name, () => {
|
|||||||
|
|
||||||
await sut.handleMetadataExtraction({ id: assetStub.livePhotoStillAsset.id });
|
await sut.handleMetadataExtraction({ id: assetStub.livePhotoStillAsset.id });
|
||||||
|
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('asset.metadataExtracted', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('AssetMetadataExtracted', {
|
||||||
assetId: assetStub.livePhotoStillAsset.id,
|
assetId: assetStub.livePhotoStillAsset.id,
|
||||||
userId: assetStub.livePhotoStillAsset.ownerId,
|
userId: assetStub.livePhotoStillAsset.ownerId,
|
||||||
});
|
});
|
||||||
|
@ -126,24 +126,24 @@ type Dates = {
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MetadataService extends BaseService {
|
export class MetadataService extends BaseService {
|
||||||
@OnEvent({ name: 'app.bootstrap', workers: [ImmichWorker.MICROSERVICES] })
|
@OnEvent({ name: 'AppBootstrap', workers: [ImmichWorker.MICROSERVICES] })
|
||||||
async onBootstrap() {
|
async onBootstrap() {
|
||||||
this.logger.log('Bootstrapping metadata service');
|
this.logger.log('Bootstrapping metadata service');
|
||||||
await this.init();
|
await this.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'app.shutdown' })
|
@OnEvent({ name: 'AppShutdown' })
|
||||||
async onShutdown() {
|
async onShutdown() {
|
||||||
await this.metadataRepository.teardown();
|
await this.metadataRepository.teardown();
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] })
|
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.MICROSERVICES] })
|
||||||
onConfigInit({ newConfig }: ArgOf<'config.init'>) {
|
onConfigInit({ newConfig }: ArgOf<'ConfigInit'>) {
|
||||||
this.metadataRepository.setMaxConcurrency(newConfig.job.metadataExtraction.concurrency);
|
this.metadataRepository.setMaxConcurrency(newConfig.job.metadataExtraction.concurrency);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.update', workers: [ImmichWorker.MICROSERVICES], server: true })
|
@OnEvent({ name: 'ConfigUpdate', workers: [ImmichWorker.MICROSERVICES], server: true })
|
||||||
onConfigUpdate({ newConfig }: ArgOf<'config.update'>) {
|
onConfigUpdate({ newConfig }: ArgOf<'ConfigUpdate'>) {
|
||||||
this.metadataRepository.setMaxConcurrency(newConfig.job.metadataExtraction.concurrency);
|
this.metadataRepository.setMaxConcurrency(newConfig.job.metadataExtraction.concurrency);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +190,7 @@ export class MetadataService extends BaseService {
|
|||||||
this.albumRepository.removeAssetsFromAll([motionAsset.id]),
|
this.albumRepository.removeAssetsFromAll([motionAsset.id]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await this.eventRepository.emit('asset.hide', { assetId: motionAsset.id, userId: motionAsset.ownerId });
|
await this.eventRepository.emit('AssetHide', { assetId: motionAsset.id, userId: motionAsset.ownerId });
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnJob({ name: JobName.QUEUE_METADATA_EXTRACTION, queue: QueueName.METADATA_EXTRACTION })
|
@OnJob({ name: JobName.QUEUE_METADATA_EXTRACTION, queue: QueueName.METADATA_EXTRACTION })
|
||||||
@ -313,7 +313,7 @@ export class MetadataService extends BaseService {
|
|||||||
|
|
||||||
await this.assetRepository.upsertJobStatus({ assetId: asset.id, metadataExtractedAt: new Date() });
|
await this.assetRepository.upsertJobStatus({ assetId: asset.id, metadataExtractedAt: new Date() });
|
||||||
|
|
||||||
await this.eventRepository.emit('asset.metadataExtracted', {
|
await this.eventRepository.emit('AssetMetadataExtracted', {
|
||||||
assetId: asset.id,
|
assetId: asset.id,
|
||||||
userId: asset.ownerId,
|
userId: asset.ownerId,
|
||||||
source: data.source,
|
source: data.source,
|
||||||
@ -351,13 +351,13 @@ export class MetadataService extends BaseService {
|
|||||||
return this.processSidecar(id, false);
|
return this.processSidecar(id, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.tag' })
|
@OnEvent({ name: 'AssetTag' })
|
||||||
async handleTagAsset({ assetId }: ArgOf<'asset.tag'>) {
|
async handleTagAsset({ assetId }: ArgOf<'AssetTag'>) {
|
||||||
await this.jobRepository.queue({ name: JobName.SIDECAR_WRITE, data: { id: assetId, tags: true } });
|
await this.jobRepository.queue({ name: JobName.SIDECAR_WRITE, data: { id: assetId, tags: true } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.untag' })
|
@OnEvent({ name: 'AssetUntag' })
|
||||||
async handleUntagAsset({ assetId }: ArgOf<'asset.untag'>) {
|
async handleUntagAsset({ assetId }: ArgOf<'AssetUntag'>) {
|
||||||
await this.jobRepository.queue({ name: JobName.SIDECAR_WRITE, data: { id: assetId, tags: true } });
|
await this.jobRepository.queue({ name: JobName.SIDECAR_WRITE, data: { id: assetId, tags: true } });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ describe(NotificationService.name, () => {
|
|||||||
const update = { oldConfig: defaults, newConfig: defaults };
|
const update = { oldConfig: defaults, newConfig: defaults };
|
||||||
expect(sut.onConfigUpdate(update)).toBeUndefined();
|
expect(sut.onConfigUpdate(update)).toBeUndefined();
|
||||||
expect(mocks.event.clientBroadcast).toHaveBeenCalledWith('on_config_update');
|
expect(mocks.event.clientBroadcast).toHaveBeenCalledWith('on_config_update');
|
||||||
expect(mocks.event.serverSend).toHaveBeenCalledWith('config.update', update);
|
expect(mocks.event.serverSend).toHaveBeenCalledWith('ConfigUpdate', update);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -77,8 +77,8 @@ export class NotificationService extends BaseService {
|
|||||||
await this.notificationRepository.cleanup();
|
await this.notificationRepository.cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'job.failed' })
|
@OnEvent({ name: 'JobFailed' })
|
||||||
async onJobFailed({ job, error }: ArgOf<'job.failed'>) {
|
async onJobFailed({ job, error }: ArgOf<'JobFailed'>) {
|
||||||
const admin = await this.userRepository.getAdmin();
|
const admin = await this.userRepository.getAdmin();
|
||||||
if (!admin) {
|
if (!admin) {
|
||||||
return;
|
return;
|
||||||
@ -107,14 +107,14 @@ export class NotificationService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.update' })
|
@OnEvent({ name: 'ConfigUpdate' })
|
||||||
onConfigUpdate({ oldConfig, newConfig }: ArgOf<'config.update'>) {
|
onConfigUpdate({ oldConfig, newConfig }: ArgOf<'ConfigUpdate'>) {
|
||||||
this.eventRepository.clientBroadcast('on_config_update');
|
this.eventRepository.clientBroadcast('on_config_update');
|
||||||
this.eventRepository.serverSend('config.update', { oldConfig, newConfig });
|
this.eventRepository.serverSend('ConfigUpdate', { oldConfig, newConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.validate', priority: -100 })
|
@OnEvent({ name: 'ConfigValidate', priority: -100 })
|
||||||
async onConfigValidate({ oldConfig, newConfig }: ArgOf<'config.validate'>) {
|
async onConfigValidate({ oldConfig, newConfig }: ArgOf<'ConfigValidate'>) {
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
newConfig.notifications.smtp.enabled &&
|
newConfig.notifications.smtp.enabled &&
|
||||||
@ -128,33 +128,33 @@ export class NotificationService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.hide' })
|
@OnEvent({ name: 'AssetHide' })
|
||||||
onAssetHide({ assetId, userId }: ArgOf<'asset.hide'>) {
|
onAssetHide({ assetId, userId }: ArgOf<'AssetHide'>) {
|
||||||
this.eventRepository.clientSend('on_asset_hidden', userId, assetId);
|
this.eventRepository.clientSend('on_asset_hidden', userId, assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.show' })
|
@OnEvent({ name: 'AssetShow' })
|
||||||
async onAssetShow({ assetId }: ArgOf<'asset.show'>) {
|
async onAssetShow({ assetId }: ArgOf<'AssetShow'>) {
|
||||||
await this.jobRepository.queue({ name: JobName.GENERATE_THUMBNAILS, data: { id: assetId, notify: true } });
|
await this.jobRepository.queue({ name: JobName.GENERATE_THUMBNAILS, data: { id: assetId, notify: true } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.trash' })
|
@OnEvent({ name: 'AssetTrash' })
|
||||||
onAssetTrash({ assetId, userId }: ArgOf<'asset.trash'>) {
|
onAssetTrash({ assetId, userId }: ArgOf<'AssetTrash'>) {
|
||||||
this.eventRepository.clientSend('on_asset_trash', userId, [assetId]);
|
this.eventRepository.clientSend('on_asset_trash', userId, [assetId]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.delete' })
|
@OnEvent({ name: 'AssetDelete' })
|
||||||
onAssetDelete({ assetId, userId }: ArgOf<'asset.delete'>) {
|
onAssetDelete({ assetId, userId }: ArgOf<'AssetDelete'>) {
|
||||||
this.eventRepository.clientSend('on_asset_delete', userId, assetId);
|
this.eventRepository.clientSend('on_asset_delete', userId, assetId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'assets.trash' })
|
@OnEvent({ name: 'AssetTrashAll' })
|
||||||
onAssetsTrash({ assetIds, userId }: ArgOf<'assets.trash'>) {
|
onAssetsTrash({ assetIds, userId }: ArgOf<'AssetTrashAll'>) {
|
||||||
this.eventRepository.clientSend('on_asset_trash', userId, assetIds);
|
this.eventRepository.clientSend('on_asset_trash', userId, assetIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.metadataExtracted' })
|
@OnEvent({ name: 'AssetMetadataExtracted' })
|
||||||
async onAssetMetadataExtracted({ assetId, userId, source }: ArgOf<'asset.metadataExtracted'>) {
|
async onAssetMetadataExtracted({ assetId, userId, source }: ArgOf<'AssetMetadataExtracted'>) {
|
||||||
if (source !== 'sidecar-write') {
|
if (source !== 'sidecar-write') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -165,40 +165,40 @@ export class NotificationService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'assets.restore' })
|
@OnEvent({ name: 'AssetRestoreAll' })
|
||||||
onAssetsRestore({ assetIds, userId }: ArgOf<'assets.restore'>) {
|
onAssetsRestore({ assetIds, userId }: ArgOf<'AssetRestoreAll'>) {
|
||||||
this.eventRepository.clientSend('on_asset_restore', userId, assetIds);
|
this.eventRepository.clientSend('on_asset_restore', userId, assetIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'stack.create' })
|
@OnEvent({ name: 'StackCreate' })
|
||||||
onStackCreate({ userId }: ArgOf<'stack.create'>) {
|
onStackCreate({ userId }: ArgOf<'StackCreate'>) {
|
||||||
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'stack.update' })
|
@OnEvent({ name: 'StackUpdate' })
|
||||||
onStackUpdate({ userId }: ArgOf<'stack.update'>) {
|
onStackUpdate({ userId }: ArgOf<'StackUpdate'>) {
|
||||||
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'stack.delete' })
|
@OnEvent({ name: 'StackDelete' })
|
||||||
onStackDelete({ userId }: ArgOf<'stack.delete'>) {
|
onStackDelete({ userId }: ArgOf<'StackDelete'>) {
|
||||||
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'stacks.delete' })
|
@OnEvent({ name: 'StackDeleteAll' })
|
||||||
onStacksDelete({ userId }: ArgOf<'stacks.delete'>) {
|
onStacksDelete({ userId }: ArgOf<'StackDeleteAll'>) {
|
||||||
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
this.eventRepository.clientSend('on_asset_stack_update', userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'user.signup' })
|
@OnEvent({ name: 'UserSignup' })
|
||||||
async onUserSignup({ notify, id, tempPassword }: ArgOf<'user.signup'>) {
|
async onUserSignup({ notify, id, tempPassword }: ArgOf<'UserSignup'>) {
|
||||||
if (notify) {
|
if (notify) {
|
||||||
await this.jobRepository.queue({ name: JobName.NOTIFY_SIGNUP, data: { id, tempPassword } });
|
await this.jobRepository.queue({ name: JobName.NOTIFY_SIGNUP, data: { id, tempPassword } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'album.update' })
|
@OnEvent({ name: 'AlbumUpdate' })
|
||||||
async onAlbumUpdate({ id, recipientId }: ArgOf<'album.update'>) {
|
async onAlbumUpdate({ id, recipientId }: ArgOf<'AlbumUpdate'>) {
|
||||||
await this.jobRepository.removeJob(JobName.NOTIFY_ALBUM_UPDATE, `${id}/${recipientId}`);
|
await this.jobRepository.removeJob(JobName.NOTIFY_ALBUM_UPDATE, `${id}/${recipientId}`);
|
||||||
await this.jobRepository.queue({
|
await this.jobRepository.queue({
|
||||||
name: JobName.NOTIFY_ALBUM_UPDATE,
|
name: JobName.NOTIFY_ALBUM_UPDATE,
|
||||||
@ -206,13 +206,13 @@ export class NotificationService extends BaseService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'album.invite' })
|
@OnEvent({ name: 'AlbumInvite' })
|
||||||
async onAlbumInvite({ id, userId }: ArgOf<'album.invite'>) {
|
async onAlbumInvite({ id, userId }: ArgOf<'AlbumInvite'>) {
|
||||||
await this.jobRepository.queue({ name: JobName.NOTIFY_ALBUM_INVITE, data: { id, recipientId: userId } });
|
await this.jobRepository.queue({ name: JobName.NOTIFY_ALBUM_INVITE, data: { id, recipientId: userId } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'session.delete' })
|
@OnEvent({ name: 'SessionDelete' })
|
||||||
onSessionDelete({ sessionId }: ArgOf<'session.delete'>) {
|
onSessionDelete({ sessionId }: ArgOf<'SessionDelete'>) {
|
||||||
// after the response is sent
|
// after the response is sent
|
||||||
setTimeout(() => this.eventRepository.clientSend('on_session_delete', sessionId, sessionId), 500);
|
setTimeout(() => this.eventRepository.clientSend('on_session_delete', sessionId, sessionId), 500);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ import { isDuplicateDetectionEnabled, isFacialRecognitionEnabled, isSmartSearchE
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServerService extends BaseService {
|
export class ServerService extends BaseService {
|
||||||
@OnEvent({ name: 'app.bootstrap' })
|
@OnEvent({ name: 'AppBootstrap' })
|
||||||
async onBootstrap(): Promise<void> {
|
async onBootstrap(): Promise<void> {
|
||||||
const featureFlags = await this.getFeatures();
|
const featureFlags = await this.getFeatures();
|
||||||
if (featureFlags.configFile) {
|
if (featureFlags.configFile) {
|
||||||
|
@ -10,18 +10,18 @@ import { getCLIPModelInfo, isSmartSearchEnabled } from 'src/utils/misc';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SmartInfoService extends BaseService {
|
export class SmartInfoService extends BaseService {
|
||||||
@OnEvent({ name: 'config.init', workers: [ImmichWorker.MICROSERVICES] })
|
@OnEvent({ name: 'ConfigInit', workers: [ImmichWorker.MICROSERVICES] })
|
||||||
async onConfigInit({ newConfig }: ArgOf<'config.init'>) {
|
async onConfigInit({ newConfig }: ArgOf<'ConfigInit'>) {
|
||||||
await this.init(newConfig);
|
await this.init(newConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.update', workers: [ImmichWorker.MICROSERVICES], server: true })
|
@OnEvent({ name: 'ConfigUpdate', workers: [ImmichWorker.MICROSERVICES], server: true })
|
||||||
async onConfigUpdate({ oldConfig, newConfig }: ArgOf<'config.update'>) {
|
async onConfigUpdate({ oldConfig, newConfig }: ArgOf<'ConfigUpdate'>) {
|
||||||
await this.init(newConfig, oldConfig);
|
await this.init(newConfig, oldConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.validate' })
|
@OnEvent({ name: 'ConfigValidate' })
|
||||||
onConfigValidate({ newConfig }: ArgOf<'config.validate'>) {
|
onConfigValidate({ newConfig }: ArgOf<'ConfigValidate'>) {
|
||||||
try {
|
try {
|
||||||
getCLIPModelInfo(newConfig.machineLearning.clip.modelName);
|
getCLIPModelInfo(newConfig.machineLearning.clip.modelName);
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -52,7 +52,7 @@ describe(StackService.name, () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('stack.create', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('StackCreate', {
|
||||||
stackId: 'stack-id',
|
stackId: 'stack-id',
|
||||||
userId: authStub.admin.user.id,
|
userId: authStub.admin.user.id,
|
||||||
});
|
});
|
||||||
@ -138,7 +138,7 @@ describe(StackService.name, () => {
|
|||||||
id: 'stack-id',
|
id: 'stack-id',
|
||||||
primaryAssetId: assetStub.image1.id,
|
primaryAssetId: assetStub.image1.id,
|
||||||
});
|
});
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('stack.update', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('StackUpdate', {
|
||||||
stackId: 'stack-id',
|
stackId: 'stack-id',
|
||||||
userId: authStub.admin.user.id,
|
userId: authStub.admin.user.id,
|
||||||
});
|
});
|
||||||
@ -160,7 +160,7 @@ describe(StackService.name, () => {
|
|||||||
await sut.delete(authStub.admin, 'stack-id');
|
await sut.delete(authStub.admin, 'stack-id');
|
||||||
|
|
||||||
expect(mocks.stack.delete).toHaveBeenCalledWith('stack-id');
|
expect(mocks.stack.delete).toHaveBeenCalledWith('stack-id');
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('stack.delete', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('StackDelete', {
|
||||||
stackId: 'stack-id',
|
stackId: 'stack-id',
|
||||||
userId: authStub.admin.user.id,
|
userId: authStub.admin.user.id,
|
||||||
});
|
});
|
||||||
@ -182,7 +182,7 @@ describe(StackService.name, () => {
|
|||||||
await sut.deleteAll(authStub.admin, { ids: ['stack-id'] });
|
await sut.deleteAll(authStub.admin, { ids: ['stack-id'] });
|
||||||
|
|
||||||
expect(mocks.stack.deleteAll).toHaveBeenCalledWith(['stack-id']);
|
expect(mocks.stack.deleteAll).toHaveBeenCalledWith(['stack-id']);
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith('stacks.delete', {
|
expect(mocks.event.emit).toHaveBeenCalledWith('StackDeleteAll', {
|
||||||
stackIds: ['stack-id'],
|
stackIds: ['stack-id'],
|
||||||
userId: authStub.admin.user.id,
|
userId: authStub.admin.user.id,
|
||||||
});
|
});
|
||||||
|
@ -21,7 +21,7 @@ export class StackService extends BaseService {
|
|||||||
|
|
||||||
const stack = await this.stackRepository.create({ ownerId: auth.user.id }, dto.assetIds);
|
const stack = await this.stackRepository.create({ ownerId: auth.user.id }, dto.assetIds);
|
||||||
|
|
||||||
await this.eventRepository.emit('stack.create', { stackId: stack.id, userId: auth.user.id });
|
await this.eventRepository.emit('StackCreate', { stackId: stack.id, userId: auth.user.id });
|
||||||
|
|
||||||
return mapStack(stack, { auth });
|
return mapStack(stack, { auth });
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ export class StackService extends BaseService {
|
|||||||
|
|
||||||
const updatedStack = await this.stackRepository.update(id, { id, primaryAssetId: dto.primaryAssetId });
|
const updatedStack = await this.stackRepository.update(id, { id, primaryAssetId: dto.primaryAssetId });
|
||||||
|
|
||||||
await this.eventRepository.emit('stack.update', { stackId: id, userId: auth.user.id });
|
await this.eventRepository.emit('StackUpdate', { stackId: id, userId: auth.user.id });
|
||||||
|
|
||||||
return mapStack(updatedStack, { auth });
|
return mapStack(updatedStack, { auth });
|
||||||
}
|
}
|
||||||
@ -49,13 +49,13 @@ export class StackService extends BaseService {
|
|||||||
async delete(auth: AuthDto, id: string): Promise<void> {
|
async delete(auth: AuthDto, id: string): Promise<void> {
|
||||||
await this.requireAccess({ auth, permission: Permission.STACK_DELETE, ids: [id] });
|
await this.requireAccess({ auth, permission: Permission.STACK_DELETE, ids: [id] });
|
||||||
await this.stackRepository.delete(id);
|
await this.stackRepository.delete(id);
|
||||||
await this.eventRepository.emit('stack.delete', { stackId: id, userId: auth.user.id });
|
await this.eventRepository.emit('StackDelete', { stackId: id, userId: auth.user.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteAll(auth: AuthDto, dto: BulkIdsDto): Promise<void> {
|
async deleteAll(auth: AuthDto, dto: BulkIdsDto): Promise<void> {
|
||||||
await this.requireAccess({ auth, permission: Permission.STACK_DELETE, ids: dto.ids });
|
await this.requireAccess({ auth, permission: Permission.STACK_DELETE, ids: dto.ids });
|
||||||
await this.stackRepository.deleteAll(dto.ids);
|
await this.stackRepository.deleteAll(dto.ids);
|
||||||
await this.eventRepository.emit('stacks.delete', { stackIds: dto.ids, userId: auth.user.id });
|
await this.eventRepository.emit('StackDeleteAll', { stackIds: dto.ids, userId: auth.user.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
private async findOrFail(id: string) {
|
private async findOrFail(id: string) {
|
||||||
|
@ -75,8 +75,8 @@ export class StorageTemplateService extends BaseService {
|
|||||||
return this._template;
|
return this._template;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.init' })
|
@OnEvent({ name: 'ConfigInit' })
|
||||||
onConfigInit({ newConfig }: ArgOf<'config.init'>) {
|
onConfigInit({ newConfig }: ArgOf<'ConfigInit'>) {
|
||||||
const template = newConfig.storageTemplate.template;
|
const template = newConfig.storageTemplate.template;
|
||||||
if (!this._template || template !== this.template.raw) {
|
if (!this._template || template !== this.template.raw) {
|
||||||
this.logger.debug(`Compiling new storage template: ${template}`);
|
this.logger.debug(`Compiling new storage template: ${template}`);
|
||||||
@ -84,13 +84,13 @@ export class StorageTemplateService extends BaseService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.update', server: true })
|
@OnEvent({ name: 'ConfigUpdate', server: true })
|
||||||
onConfigUpdate({ newConfig }: ArgOf<'config.update'>) {
|
onConfigUpdate({ newConfig }: ArgOf<'ConfigUpdate'>) {
|
||||||
this.onConfigInit({ newConfig });
|
this.onConfigInit({ newConfig });
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.validate' })
|
@OnEvent({ name: 'ConfigValidate' })
|
||||||
onConfigValidate({ newConfig }: ArgOf<'config.validate'>) {
|
onConfigValidate({ newConfig }: ArgOf<'ConfigValidate'>) {
|
||||||
try {
|
try {
|
||||||
const { compiled } = this.compile(newConfig.storageTemplate.template);
|
const { compiled } = this.compile(newConfig.storageTemplate.template);
|
||||||
this.render(compiled, {
|
this.render(compiled, {
|
||||||
@ -116,8 +116,8 @@ export class StorageTemplateService extends BaseService {
|
|||||||
return { ...storageTokens, presetOptions: storagePresets };
|
return { ...storageTokens, presetOptions: storagePresets };
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.metadataExtracted' })
|
@OnEvent({ name: 'AssetMetadataExtracted' })
|
||||||
async onAssetMetadataExtracted({ source, assetId }: ArgOf<'asset.metadataExtracted'>) {
|
async onAssetMetadataExtracted({ source, assetId }: ArgOf<'AssetMetadataExtracted'>) {
|
||||||
await this.jobRepository.queue({ name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE, data: { source, id: assetId } });
|
await this.jobRepository.queue({ name: JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE, data: { source, id: assetId } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,8 +182,8 @@ export class StorageTemplateService extends BaseService {
|
|||||||
return JobStatus.SUCCESS;
|
return JobStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'asset.delete' })
|
@OnEvent({ name: 'AssetDelete' })
|
||||||
async handleMoveHistoryCleanup({ assetId }: ArgOf<'asset.delete'>) {
|
async handleMoveHistoryCleanup({ assetId }: ArgOf<'AssetDelete'>) {
|
||||||
this.logger.debug(`Cleaning up move history for asset ${assetId}`);
|
this.logger.debug(`Cleaning up move history for asset ${assetId}`);
|
||||||
await this.moveRepository.cleanMoveHistorySingle(assetId);
|
await this.moveRepository.cleanMoveHistorySingle(assetId);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ const docsMessage = `Please see https://immich.app/docs/administration/system-in
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StorageService extends BaseService {
|
export class StorageService extends BaseService {
|
||||||
@OnEvent({ name: 'app.bootstrap' })
|
@OnEvent({ name: 'AppBootstrap' })
|
||||||
async onBootstrap() {
|
async onBootstrap() {
|
||||||
const envData = this.configRepository.getEnv();
|
const envData = this.configRepository.getEnv();
|
||||||
|
|
||||||
|
@ -412,7 +412,7 @@ describe(SystemConfigService.name, () => {
|
|||||||
mocks.systemMetadata.get.mockResolvedValue(partialConfig);
|
mocks.systemMetadata.get.mockResolvedValue(partialConfig);
|
||||||
await expect(sut.updateSystemConfig(updatedConfig)).resolves.toEqual(updatedConfig);
|
await expect(sut.updateSystemConfig(updatedConfig)).resolves.toEqual(updatedConfig);
|
||||||
expect(mocks.event.emit).toHaveBeenCalledWith(
|
expect(mocks.event.emit).toHaveBeenCalledWith(
|
||||||
'config.update',
|
'ConfigUpdate',
|
||||||
expect.objectContaining({ oldConfig: expect.any(Object), newConfig: updatedConfig }),
|
expect.objectContaining({ oldConfig: expect.any(Object), newConfig: updatedConfig }),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -12,10 +12,10 @@ import { toPlainObject } from 'src/utils/object';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SystemConfigService extends BaseService {
|
export class SystemConfigService extends BaseService {
|
||||||
@OnEvent({ name: 'app.bootstrap', priority: BootstrapEventPriority.SystemConfig })
|
@OnEvent({ name: 'AppBootstrap', priority: BootstrapEventPriority.SystemConfig })
|
||||||
async onBootstrap() {
|
async onBootstrap() {
|
||||||
const config = await this.getConfig({ withCache: false });
|
const config = await this.getConfig({ withCache: false });
|
||||||
await this.eventRepository.emit('config.init', { newConfig: config });
|
await this.eventRepository.emit('ConfigInit', { newConfig: config });
|
||||||
}
|
}
|
||||||
|
|
||||||
async getSystemConfig(): Promise<SystemConfigDto> {
|
async getSystemConfig(): Promise<SystemConfigDto> {
|
||||||
@ -27,8 +27,8 @@ export class SystemConfigService extends BaseService {
|
|||||||
return mapConfig(defaults);
|
return mapConfig(defaults);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.init', priority: -100 })
|
@OnEvent({ name: 'ConfigInit', priority: -100 })
|
||||||
onConfigInit({ newConfig: { logging } }: ArgOf<'config.init'>) {
|
onConfigInit({ newConfig: { logging } }: ArgOf<'ConfigInit'>) {
|
||||||
const { logLevel: envLevel } = this.configRepository.getEnv();
|
const { logLevel: envLevel } = this.configRepository.getEnv();
|
||||||
const configLevel = logging.enabled ? logging.level : false;
|
const configLevel = logging.enabled ? logging.level : false;
|
||||||
const level = envLevel ?? configLevel;
|
const level = envLevel ?? configLevel;
|
||||||
@ -36,14 +36,14 @@ export class SystemConfigService extends BaseService {
|
|||||||
this.logger.log(`LogLevel=${level} ${envLevel ? '(set via IMMICH_LOG_LEVEL)' : '(set via system config)'}`);
|
this.logger.log(`LogLevel=${level} ${envLevel ? '(set via IMMICH_LOG_LEVEL)' : '(set via system config)'}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.update', server: true })
|
@OnEvent({ name: 'ConfigUpdate', server: true })
|
||||||
onConfigUpdate({ newConfig }: ArgOf<'config.update'>) {
|
onConfigUpdate({ newConfig }: ArgOf<'ConfigUpdate'>) {
|
||||||
this.onConfigInit({ newConfig });
|
this.onConfigInit({ newConfig });
|
||||||
clearConfigCache();
|
clearConfigCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'config.validate' })
|
@OnEvent({ name: 'ConfigValidate' })
|
||||||
onConfigValidate({ newConfig, oldConfig }: ArgOf<'config.validate'>) {
|
onConfigValidate({ newConfig, oldConfig }: ArgOf<'ConfigValidate'>) {
|
||||||
const { logLevel } = this.configRepository.getEnv();
|
const { logLevel } = this.configRepository.getEnv();
|
||||||
if (!_.isEqual(instanceToPlain(newConfig.logging), oldConfig.logging) && logLevel) {
|
if (!_.isEqual(instanceToPlain(newConfig.logging), oldConfig.logging) && logLevel) {
|
||||||
throw new Error('Logging cannot be changed while the environment variable IMMICH_LOG_LEVEL is set.');
|
throw new Error('Logging cannot be changed while the environment variable IMMICH_LOG_LEVEL is set.');
|
||||||
@ -59,7 +59,7 @@ export class SystemConfigService extends BaseService {
|
|||||||
const oldConfig = await this.getConfig({ withCache: false });
|
const oldConfig = await this.getConfig({ withCache: false });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.eventRepository.emit('config.validate', { newConfig: toPlainObject(dto), oldConfig });
|
await this.eventRepository.emit('ConfigValidate', { newConfig: toPlainObject(dto), oldConfig });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.warn(`Unable to save system config due to a validation error: ${error}`);
|
this.logger.warn(`Unable to save system config due to a validation error: ${error}`);
|
||||||
throw new BadRequestException(error instanceof Error ? error.message : error);
|
throw new BadRequestException(error instanceof Error ? error.message : error);
|
||||||
@ -67,7 +67,7 @@ export class SystemConfigService extends BaseService {
|
|||||||
|
|
||||||
const newConfig = await this.updateConfig(dto);
|
const newConfig = await this.updateConfig(dto);
|
||||||
|
|
||||||
await this.eventRepository.emit('config.update', { newConfig, oldConfig });
|
await this.eventRepository.emit('ConfigUpdate', { newConfig, oldConfig });
|
||||||
|
|
||||||
return mapConfig(newConfig);
|
return mapConfig(newConfig);
|
||||||
}
|
}
|
||||||
|
@ -90,7 +90,7 @@ export class TagService extends BaseService {
|
|||||||
|
|
||||||
const results = await this.tagRepository.upsertAssetIds(items);
|
const results = await this.tagRepository.upsertAssetIds(items);
|
||||||
for (const assetId of new Set(results.map((item) => item.assetsId))) {
|
for (const assetId of new Set(results.map((item) => item.assetsId))) {
|
||||||
await this.eventRepository.emit('asset.tag', { assetId });
|
await this.eventRepository.emit('AssetTag', { assetId });
|
||||||
}
|
}
|
||||||
|
|
||||||
return { count: results.length };
|
return { count: results.length };
|
||||||
@ -107,7 +107,7 @@ export class TagService extends BaseService {
|
|||||||
|
|
||||||
for (const { id: assetId, success } of results) {
|
for (const { id: assetId, success } of results) {
|
||||||
if (success) {
|
if (success) {
|
||||||
await this.eventRepository.emit('asset.tag', { assetId });
|
await this.eventRepository.emit('AssetTag', { assetId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ export class TagService extends BaseService {
|
|||||||
|
|
||||||
for (const { id: assetId, success } of results) {
|
for (const { id: assetId, success } of results) {
|
||||||
if (success) {
|
if (success) {
|
||||||
await this.eventRepository.emit('asset.untag', { assetId });
|
await this.eventRepository.emit('AssetUntag', { assetId });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ export class TrashService extends BaseService {
|
|||||||
|
|
||||||
await this.requireAccess({ auth, permission: Permission.ASSET_DELETE, ids });
|
await this.requireAccess({ auth, permission: Permission.ASSET_DELETE, ids });
|
||||||
await this.trashRepository.restoreAll(ids);
|
await this.trashRepository.restoreAll(ids);
|
||||||
await this.eventRepository.emit('assets.restore', { assetIds: ids, userId: auth.user.id });
|
await this.eventRepository.emit('AssetRestoreAll', { assetIds: ids, userId: auth.user.id });
|
||||||
|
|
||||||
this.logger.log(`Restored ${ids.length} asset(s) from trash`);
|
this.logger.log(`Restored ${ids.length} asset(s) from trash`);
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ export class TrashService extends BaseService {
|
|||||||
return { count };
|
return { count };
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'assets.delete' })
|
@OnEvent({ name: 'AssetDeleteAll' })
|
||||||
async onAssetsDelete() {
|
async onAssetsDelete() {
|
||||||
await this.jobRepository.queue({ name: JobName.QUEUE_TRASH_EMPTY, data: {} });
|
await this.jobRepository.queue({ name: JobName.QUEUE_TRASH_EMPTY, data: {} });
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ export class UserAdminService extends BaseService {
|
|||||||
|
|
||||||
const user = await this.createUser(userDto);
|
const user = await this.createUser(userDto);
|
||||||
|
|
||||||
await this.eventRepository.emit('user.signup', {
|
await this.eventRepository.emit('UserSignup', {
|
||||||
notify: !!notify,
|
notify: !!notify,
|
||||||
id: user.id,
|
id: user.id,
|
||||||
tempPassword: user.shouldChangePassword ? userDto.password : undefined,
|
tempPassword: user.shouldChangePassword ? userDto.password : undefined,
|
||||||
|
@ -20,7 +20,7 @@ const asNotification = ({ checkedAt, releaseVersion }: VersionCheckMetadata): Re
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class VersionService extends BaseService {
|
export class VersionService extends BaseService {
|
||||||
@OnEvent({ name: 'app.bootstrap' })
|
@OnEvent({ name: 'AppBootstrap' })
|
||||||
async onBootstrap(): Promise<void> {
|
async onBootstrap(): Promise<void> {
|
||||||
await this.handleVersionCheck();
|
await this.handleVersionCheck();
|
||||||
|
|
||||||
@ -102,8 +102,8 @@ export class VersionService extends BaseService {
|
|||||||
return JobStatus.SUCCESS;
|
return JobStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnEvent({ name: 'websocket.connect' })
|
@OnEvent({ name: 'WebsocketConnect' })
|
||||||
async onWebsocketConnection({ userId }: ArgOf<'websocket.connect'>) {
|
async onWebsocketConnection({ userId }: ArgOf<'WebsocketConnect'>) {
|
||||||
this.eventRepository.clientSend('on_server_version', userId, serverVersion);
|
this.eventRepository.clientSend('on_server_version', userId, serverVersion);
|
||||||
const metadata = await this.systemMetadataRepository.get(SystemMetadataKey.VERSION_CHECK_STATE);
|
const metadata = await this.systemMetadataRepository.get(SystemMetadataKey.VERSION_CHECK_STATE);
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
|
@ -152,7 +152,7 @@ export const onBeforeLink = async (
|
|||||||
|
|
||||||
if (motionAsset && motionAsset.visibility === AssetVisibility.TIMELINE) {
|
if (motionAsset && motionAsset.visibility === AssetVisibility.TIMELINE) {
|
||||||
await assetRepository.update({ id: livePhotoVideoId, visibility: AssetVisibility.HIDDEN });
|
await assetRepository.update({ id: livePhotoVideoId, visibility: AssetVisibility.HIDDEN });
|
||||||
await eventRepository.emit('asset.hide', { assetId: motionAsset.id, userId });
|
await eventRepository.emit('AssetHide', { assetId: motionAsset.id, userId });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ export const onAfterUnlink = async (
|
|||||||
{ userId, livePhotoVideoId, visibility }: { userId: string; livePhotoVideoId: string; visibility: AssetVisibility },
|
{ userId, livePhotoVideoId, visibility }: { userId: string; livePhotoVideoId: string; visibility: AssetVisibility },
|
||||||
) => {
|
) => {
|
||||||
await assetRepository.update({ id: livePhotoVideoId, visibility });
|
await assetRepository.update({ id: livePhotoVideoId, visibility });
|
||||||
await eventRepository.emit('asset.show', { assetId: livePhotoVideoId, userId });
|
await eventRepository.emit('AssetShow', { assetId: livePhotoVideoId, userId });
|
||||||
};
|
};
|
||||||
|
|
||||||
export function mapToUploadFile(file: ImmichFile): UploadFile {
|
export function mapToUploadFile(file: ImmichFile): UploadFile {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user