mirror of
https://github.com/immich-app/immich.git
synced 2025-12-06 09:13:13 +03:00
fix(server): include the previous year in memories for January 1, 2, 3 (#23832)
* Test memory creation in advance Use year 2035 to make sure it's in the future of current time of a test run * Use target year instead of current year when fetching assets during memory creation This fixes an edge case of creating memories in advance when target year is different from current year. Example: job runs on 2025-12-31 (current year is 2025) and creates memories to be shown on 2026-01-01 (target year is 2026). If using _current_ year in calculation then range of years is capped at (2025 - 1 = 2024) thus excluding 2025-01-01 from created memories. With _target_ year it is (2026 - 1 = 2025), so 2025-01-01 will be included in memories. * Update sql queries
This commit is contained in:
@@ -64,7 +64,7 @@ with
|
||||
from
|
||||
asset
|
||||
),
|
||||
date_part('year', current_date)::int - 1
|
||||
$3
|
||||
) as "year"
|
||||
)
|
||||
select
|
||||
@@ -81,21 +81,21 @@ with
|
||||
where
|
||||
"asset_job_status"."previewAt" is not null
|
||||
and (asset."localDateTime" at time zone 'UTC')::date = today.date
|
||||
and "asset"."ownerId" = any ($3::uuid[])
|
||||
and "asset"."visibility" = $4
|
||||
and "asset"."ownerId" = any ($4::uuid[])
|
||||
and "asset"."visibility" = $5
|
||||
and exists (
|
||||
select
|
||||
from
|
||||
"asset_file"
|
||||
where
|
||||
"assetId" = "asset"."id"
|
||||
and "asset_file"."type" = $5
|
||||
and "asset_file"."type" = $6
|
||||
)
|
||||
and "asset"."deletedAt" is null
|
||||
order by
|
||||
(asset."localDateTime" at time zone 'UTC')::date desc
|
||||
limit
|
||||
$6
|
||||
$7
|
||||
) as "a" on true
|
||||
inner join "asset_exif" on "a"."id" = "asset_exif"."assetId"
|
||||
)
|
||||
|
||||
@@ -73,9 +73,10 @@ export interface TimeBucketItem {
|
||||
count: number;
|
||||
}
|
||||
|
||||
export interface MonthDay {
|
||||
export interface YearMonthDay {
|
||||
day: number;
|
||||
month: number;
|
||||
year: number;
|
||||
}
|
||||
|
||||
interface AssetExploreFieldOptions {
|
||||
@@ -259,8 +260,8 @@ export class AssetRepository {
|
||||
return this.db.insertInto('asset').values(assets).returningAll().execute();
|
||||
}
|
||||
|
||||
@GenerateSql({ params: [DummyValue.UUID, { day: 1, month: 1 }] })
|
||||
getByDayOfYear(ownerIds: string[], { day, month }: MonthDay) {
|
||||
@GenerateSql({ params: [DummyValue.UUID, { year: 2000, day: 1, month: 1 }] })
|
||||
getByDayOfYear(ownerIds: string[], { year, day, month }: YearMonthDay) {
|
||||
return this.db
|
||||
.with('res', (qb) =>
|
||||
qb
|
||||
@@ -270,7 +271,7 @@ export class AssetRepository {
|
||||
eb
|
||||
.fn('generate_series', [
|
||||
sql`(select date_part('year', min(("localDateTime" at time zone 'UTC')::date))::int from asset)`,
|
||||
sql`date_part('year', current_date)::int - 1`,
|
||||
sql`${year - 1}`,
|
||||
])
|
||||
.as('year'),
|
||||
)
|
||||
|
||||
@@ -153,6 +153,46 @@ describe(MemoryService.name, () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should create a memory from an asset - in advance', async () => {
|
||||
const { sut, ctx } = setup();
|
||||
const assetRepo = ctx.get(AssetRepository);
|
||||
const memoryRepo = ctx.get(MemoryRepository);
|
||||
const now = DateTime.fromObject({ year: 2035, month: 2, day: 26 }, { zone: 'utc' }) as DateTime<true>;
|
||||
const { user } = await ctx.newUser();
|
||||
const { asset } = await ctx.newAsset({ ownerId: user.id, localDateTime: now.minus({ years: 1 }).toISO() });
|
||||
await Promise.all([
|
||||
ctx.newExif({ assetId: asset.id, make: 'Canon' }),
|
||||
ctx.newJobStatus({ assetId: asset.id }),
|
||||
assetRepo.upsertFiles([
|
||||
{ assetId: asset.id, type: AssetFileType.Preview, path: '/path/to/preview.jpg' },
|
||||
{ assetId: asset.id, type: AssetFileType.Thumbnail, path: '/path/to/thumbnail.jpg' },
|
||||
]),
|
||||
]);
|
||||
|
||||
vi.setSystemTime(now.toJSDate());
|
||||
await sut.onMemoriesCreate();
|
||||
|
||||
const memories = await memoryRepo.search(user.id, {});
|
||||
expect(memories.length).toBe(1);
|
||||
expect(memories[0]).toEqual(
|
||||
expect.objectContaining({
|
||||
id: expect.any(String),
|
||||
createdAt: expect.any(Date),
|
||||
memoryAt: expect.any(Date),
|
||||
updatedAt: expect.any(Date),
|
||||
deletedAt: null,
|
||||
ownerId: user.id,
|
||||
assets: expect.arrayContaining([expect.objectContaining({ id: asset.id })]),
|
||||
isSaved: false,
|
||||
showAt: now.startOf('day').toJSDate(),
|
||||
hideAt: now.endOf('day').toJSDate(),
|
||||
seenAt: null,
|
||||
type: 'on_this_day',
|
||||
data: { year: 2034 },
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should not generate a memory twice for the same day', async () => {
|
||||
const { sut, ctx } = setup();
|
||||
const assetRepo = ctx.get(AssetRepository);
|
||||
|
||||
Reference in New Issue
Block a user