diff --git a/server/src/db.d.ts b/server/src/db.d.ts index bc88d7de3c..ff4cb4a1d2 100644 --- a/server/src/db.d.ts +++ b/server/src/db.d.ts @@ -41,6 +41,7 @@ export interface Activity { id: Generated<string>; isLiked: Generated<boolean>; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; userId: string; } @@ -58,6 +59,7 @@ export interface Albums { order: Generated<string>; ownerId: string; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } export interface AlbumsAssetsAssets { @@ -79,6 +81,7 @@ export interface ApiKeys { name: string; permissions: Permission[]; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; userId: string; } @@ -103,6 +106,7 @@ export interface AssetFiles { path: string; type: string; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } export interface AssetJobStatus { @@ -143,6 +147,7 @@ export interface Assets { thumbhash: Buffer | null; type: string; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } export interface AssetStack { @@ -221,6 +226,7 @@ export interface Libraries { ownerId: string; refreshedAt: Timestamp | null; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } export interface Memories { @@ -236,6 +242,7 @@ export interface Memories { showAt: Timestamp | null; type: string; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } export interface MemoriesAssetsAssets { @@ -271,6 +278,7 @@ export interface Partners { sharedById: string; sharedWithId: string; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } export interface Person { @@ -285,6 +293,7 @@ export interface Person { ownerId: string; thumbnailPath: Generated<string>; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } export interface Sessions { @@ -294,6 +303,7 @@ export interface Sessions { id: Generated<string>; token: string; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; userId: string; } @@ -303,6 +313,7 @@ export interface SessionSyncCheckpoints { sessionId: string; type: SyncEntityType; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } @@ -358,6 +369,7 @@ export interface Tags { id: Generated<string>; parentId: string | null; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; userId: string; value: string; } @@ -399,6 +411,7 @@ export interface Users { status: Generated<string>; storageLabel: string | null; updatedAt: Generated<Timestamp>; + updateId: Generated<string>; } export interface UsersAudit { diff --git a/server/src/entities/activity.entity.ts b/server/src/entities/activity.entity.ts index 8de76ac894..dabb371977 100644 --- a/server/src/entities/activity.entity.ts +++ b/server/src/entities/activity.entity.ts @@ -25,6 +25,10 @@ export class ActivityEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_activity_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @Column() albumId!: string; diff --git a/server/src/entities/album.entity.ts b/server/src/entities/album.entity.ts index 5aec5a0f47..4cd7c82394 100644 --- a/server/src/entities/album.entity.ts +++ b/server/src/entities/album.entity.ts @@ -8,6 +8,7 @@ import { CreateDateColumn, DeleteDateColumn, Entity, + Index, JoinTable, ManyToMany, ManyToOne, @@ -39,6 +40,10 @@ export class AlbumEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_albums_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @DeleteDateColumn({ type: 'timestamptz' }) deletedAt!: Date | null; diff --git a/server/src/entities/api-key.entity.ts b/server/src/entities/api-key.entity.ts index 998ee4f8ef..f59bf0d918 100644 --- a/server/src/entities/api-key.entity.ts +++ b/server/src/entities/api-key.entity.ts @@ -1,6 +1,6 @@ import { UserEntity } from 'src/entities/user.entity'; import { Permission } from 'src/enum'; -import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; +import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; @Entity('api_keys') export class APIKeyEntity { @@ -27,4 +27,8 @@ export class APIKeyEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + + @Index('IDX_api_keys_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; } diff --git a/server/src/entities/asset-files.entity.ts b/server/src/entities/asset-files.entity.ts index a8a6ddfee1..09f96e849d 100644 --- a/server/src/entities/asset-files.entity.ts +++ b/server/src/entities/asset-files.entity.ts @@ -30,6 +30,10 @@ export class AssetFileEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_asset_files_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @Column() type!: AssetFileType; diff --git a/server/src/entities/asset.entity.ts b/server/src/entities/asset.entity.ts index a325febce7..7345d9a2e6 100644 --- a/server/src/entities/asset.entity.ts +++ b/server/src/entities/asset.entity.ts @@ -96,6 +96,10 @@ export class AssetEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_assets_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @DeleteDateColumn({ type: 'timestamptz', nullable: true }) deletedAt!: Date | null; diff --git a/server/src/entities/library.entity.ts b/server/src/entities/library.entity.ts index a6053e4213..a594fd83ad 100644 --- a/server/src/entities/library.entity.ts +++ b/server/src/entities/library.entity.ts @@ -5,6 +5,7 @@ import { CreateDateColumn, DeleteDateColumn, Entity, + Index, JoinTable, ManyToOne, OneToMany, @@ -42,6 +43,10 @@ export class LibraryEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_libraries_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @DeleteDateColumn({ type: 'timestamptz' }) deletedAt?: Date; diff --git a/server/src/entities/memory.entity.ts b/server/src/entities/memory.entity.ts index 1f53d7a5c1..dafd7eb21c 100644 --- a/server/src/entities/memory.entity.ts +++ b/server/src/entities/memory.entity.ts @@ -6,6 +6,7 @@ import { CreateDateColumn, DeleteDateColumn, Entity, + Index, JoinTable, ManyToMany, ManyToOne, @@ -30,6 +31,10 @@ export class MemoryEntity<T extends MemoryType = MemoryType> { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_memories_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @DeleteDateColumn({ type: 'timestamptz' }) deletedAt?: Date; diff --git a/server/src/entities/partner.entity.ts b/server/src/entities/partner.entity.ts index 189f6f51a7..877330a8e7 100644 --- a/server/src/entities/partner.entity.ts +++ b/server/src/entities/partner.entity.ts @@ -1,5 +1,14 @@ import { UserEntity } from 'src/entities/user.entity'; -import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm'; +import { + Column, + CreateDateColumn, + Entity, + Index, + JoinColumn, + ManyToOne, + PrimaryColumn, + UpdateDateColumn, +} from 'typeorm'; @Entity('partners') export class PartnerEntity { @@ -23,6 +32,10 @@ export class PartnerEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_partners_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @Column({ type: 'boolean', default: false }) inTimeline!: boolean; } diff --git a/server/src/entities/person.entity.ts b/server/src/entities/person.entity.ts index 3785e1985e..5ca74c12d2 100644 --- a/server/src/entities/person.entity.ts +++ b/server/src/entities/person.entity.ts @@ -5,6 +5,7 @@ import { Column, CreateDateColumn, Entity, + Index, ManyToOne, OneToMany, PrimaryGeneratedColumn, @@ -23,6 +24,10 @@ export class PersonEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_person_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @Column() ownerId!: string; diff --git a/server/src/entities/session.entity.ts b/server/src/entities/session.entity.ts index e21c6d52ba..cb208c958e 100644 --- a/server/src/entities/session.entity.ts +++ b/server/src/entities/session.entity.ts @@ -1,7 +1,7 @@ import { ExpressionBuilder } from 'kysely'; import { DB } from 'src/db'; import { UserEntity } from 'src/entities/user.entity'; -import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; +import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; @Entity('sessions') export class SessionEntity { @@ -23,6 +23,10 @@ export class SessionEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_sessions_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId!: string; + @Column({ default: '' }) deviceType!: string; diff --git a/server/src/entities/sync-checkpoint.entity.ts b/server/src/entities/sync-checkpoint.entity.ts index 2a91d2386c..7c6818aba0 100644 --- a/server/src/entities/sync-checkpoint.entity.ts +++ b/server/src/entities/sync-checkpoint.entity.ts @@ -1,6 +1,6 @@ import { SessionEntity } from 'src/entities/session.entity'; import { SyncEntityType } from 'src/enum'; -import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm'; +import { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm'; @Entity('session_sync_checkpoints') export class SessionSyncCheckpointEntity { @@ -19,6 +19,10 @@ export class SessionSyncCheckpointEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_session_sync_checkpoints_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @Column() ack!: string; } diff --git a/server/src/entities/tag.entity.ts b/server/src/entities/tag.entity.ts index ebcc6853c9..fcbde6c779 100644 --- a/server/src/entities/tag.entity.ts +++ b/server/src/entities/tag.entity.ts @@ -4,6 +4,7 @@ import { Column, CreateDateColumn, Entity, + Index, ManyToMany, ManyToOne, PrimaryGeneratedColumn, @@ -30,6 +31,10 @@ export class TagEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_tags_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @Column({ type: 'varchar', nullable: true, default: null }) color!: string | null; diff --git a/server/src/entities/user.entity.ts b/server/src/entities/user.entity.ts index b597d15cf9..5758e29098 100644 --- a/server/src/entities/user.entity.ts +++ b/server/src/entities/user.entity.ts @@ -58,6 +58,10 @@ export class UserEntity { @UpdateDateColumn({ type: 'timestamptz' }) updatedAt!: Date; + @Index('IDX_users_update_id') + @Column({ type: 'uuid', nullable: false, default: () => 'immich_uuid_v7()' }) + updateId?: string; + @OneToMany(() => TagEntity, (tag) => tag.user) tags!: TagEntity[]; diff --git a/server/src/migrations/1740586617223-AddUpdateIdColumns.ts b/server/src/migrations/1740586617223-AddUpdateIdColumns.ts new file mode 100644 index 0000000000..02d680ddf6 --- /dev/null +++ b/server/src/migrations/1740586617223-AddUpdateIdColumns.ts @@ -0,0 +1,134 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class AddUpdateIdColumns1740586617223 implements MigrationInterface { + name = 'AddUpdateIdColumns1740586617223' + + public async up(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(` + create or replace function immich_uuid_v7(p_timestamp timestamp with time zone default clock_timestamp()) + returns uuid + as $$ + select encode( + set_bit( + set_bit( + overlay(uuid_send(gen_random_uuid()) + placing substring(int8send(floor(extract(epoch from p_timestamp) * 1000)::bigint) from 3) + from 1 for 6 + ), + 52, 1 + ), + 53, 1 + ), + 'hex')::uuid; + $$ + language SQL + volatile; + `) + await queryRunner.query(` + CREATE OR REPLACE FUNCTION updated_at() RETURNS TRIGGER + LANGUAGE plpgsql + as $$ + BEGIN + return new; + END; + $$; + `) + await queryRunner.query(`ALTER TABLE "person" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "asset_files" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "libraries" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "tags" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "assets" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "users" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "albums" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "sessions" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "session_sync_checkpoints" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "partners" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "memories" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "api_keys" ADD "updateId" uuid`); + await queryRunner.query(`ALTER TABLE "activity" ADD "updateId" uuid`); + + await queryRunner.query(`UPDATE "person" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "asset_files" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "libraries" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "tags" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "assets" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "users" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "albums" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "sessions" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "session_sync_checkpoints" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "partners" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "memories" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "api_keys" SET "updateId" = immich_uuid_v7("updatedAt")`); + await queryRunner.query(`UPDATE "activity" SET "updateId" = immich_uuid_v7("updatedAt")`); + + await queryRunner.query(`ALTER TABLE "person" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "asset_files" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "libraries" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "tags" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "assets" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "users" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "albums" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "sessions" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "session_sync_checkpoints" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "partners" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "memories" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "api_keys" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + await queryRunner.query(`ALTER TABLE "activity" ALTER COLUMN "updateId" SET NOT NULL, ALTER COLUMN "updateId" SET DEFAULT immich_uuid_v7()`); + + await queryRunner.query(`CREATE INDEX "IDX_person_update_id" ON "person" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_asset_files_update_id" ON "asset_files" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_libraries_update_id" ON "libraries" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_tags_update_id" ON "tags" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_assets_update_id" ON "assets" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_users_update_id" ON "users" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_albums_update_id" ON "albums" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_sessions_update_id" ON "sessions" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_session_sync_checkpoints_update_id" ON "session_sync_checkpoints" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_partners_update_id" ON "partners" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_memories_update_id" ON "memories" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_api_keys_update_id" ON "api_keys" ("updateId")`); + await queryRunner.query(`CREATE INDEX "IDX_activity_update_id" ON "activity" ("updateId")`); + + await queryRunner.query(` + CREATE OR REPLACE FUNCTION updated_at() RETURNS TRIGGER + LANGUAGE plpgsql + as $$ + DECLARE + clock_timestamp TIMESTAMP := clock_timestamp(); + BEGIN + new."updatedAt" = clock_timestamp; + new."updateId" = immich_uuid_v7(clock_timestamp); + return new; + END; + $$; + `) + } + + public async down(queryRunner: QueryRunner): Promise<void> { + await queryRunner.query(`ALTER TABLE "activity" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "api_keys" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "memories" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "partners" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "session_sync_checkpoints" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "sessions" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "albums" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "users" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "assets" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "tags" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "libraries" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "asset_files" DROP COLUMN "updateId"`); + await queryRunner.query(`ALTER TABLE "person" DROP COLUMN "updateId"`); + await queryRunner.query(`DROP FUNCTION immich_uuid_v7`); + await queryRunner.query(` + CREATE OR REPLACE FUNCTION updated_at() RETURNS TRIGGER + LANGUAGE plpgsql + as $$ + BEGIN + new."updatedAt" = now(); + return new; + END; + $$; + `) + } + +} diff --git a/server/src/services/session.service.spec.ts b/server/src/services/session.service.spec.ts index 8c22abb7f0..96a1dacf64 100644 --- a/server/src/services/session.service.spec.ts +++ b/server/src/services/session.service.spec.ts @@ -33,6 +33,7 @@ describe('SessionService', () => { id: '123', token: '420', userId: '42', + updateId: 'uuid-v7', }, ]); diff --git a/server/test/fixtures/activity.stub.ts b/server/test/fixtures/activity.stub.ts index 9578bcd4a1..a81fd51ca8 100644 --- a/server/test/fixtures/activity.stub.ts +++ b/server/test/fixtures/activity.stub.ts @@ -19,6 +19,7 @@ export const activityStub = { albumId: albumStub.oneAsset.id, createdAt: new Date(), updatedAt: new Date(), + updateId: 'uuid-v7', }), liked: Object.freeze<ActivityItem>({ id: 'activity-2', @@ -36,5 +37,6 @@ export const activityStub = { albumId: albumStub.oneAsset.id, createdAt: new Date(), updatedAt: new Date(), + updateId: 'uuid-v7', }), }; diff --git a/server/test/fixtures/session.stub.ts b/server/test/fixtures/session.stub.ts index cdf499c8d1..af06237473 100644 --- a/server/test/fixtures/session.stub.ts +++ b/server/test/fixtures/session.stub.ts @@ -11,6 +11,7 @@ export const sessionStub = { updatedAt: new Date(), deviceType: '', deviceOS: '', + updateId: 'uuid-v7', }), inactive: Object.freeze<SessionEntity>({ id: 'not_active', @@ -21,5 +22,6 @@ export const sessionStub = { updatedAt: new Date('2021-01-01'), deviceType: 'Mobile', deviceOS: 'Android', + updateId: 'uuid-v7', }), };