fix(server): include the previous year in memories for January 1, 2, 3 (#23832)
Some checks failed
CodeQL / Analyze (javascript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docker / pre-job (push) Has been cancelled
Docker / Re-Tag ML () (push) Has been cancelled
Docker / Re-Tag ML (-armnn) (push) Has been cancelled
Docker / Re-Tag ML (-cuda) (push) Has been cancelled
Docker / Re-Tag ML (-openvino) (push) Has been cancelled
Docker / Re-Tag ML (-rknn) (push) Has been cancelled
Docker / Re-Tag ML (-rocm) (push) Has been cancelled
Docker / Re-Tag Server () (push) Has been cancelled
Docker / Build and Push ML (armnn, linux/arm64, -armnn) (push) Has been cancelled
Docker / Build and Push ML (cpu) (push) Has been cancelled
Docker / Build and Push ML (cuda, linux/amd64, -cuda) (push) Has been cancelled
Docker / Build and Push ML (openvino, linux/amd64, -openvino) (push) Has been cancelled
Docker / Build and Push ML (rknn, linux/arm64, -rknn) (push) Has been cancelled
Docker / Build and Push ML (rocm, linux/amd64, {"linux/amd64": "mich"}, -rocm) (push) Has been cancelled
Docker / Build and Push Server (push) Has been cancelled
Docker / Docker Build & Push Server Success (push) Has been cancelled
Docker / Docker Build & Push ML Success (push) Has been cancelled
Docs build / pre-job (push) Has been cancelled
Docs build / Docs Build (push) Has been cancelled
Zizmor / Zizmor (push) Has been cancelled
Manage release PR / bump (push) Has been cancelled
Static Code Analysis / pre-job (push) Has been cancelled
Static Code Analysis / Run Dart Code Analysis (push) Has been cancelled
Test / pre-job (push) Has been cancelled
Test / Test & Lint Server (push) Has been cancelled
Test / Unit Test CLI (push) Has been cancelled
Test / Unit Test CLI (Windows) (push) Has been cancelled
Test / Lint Web (push) Has been cancelled
Test / Test Web (push) Has been cancelled
Test / Test i18n (push) Has been cancelled
Test / End-to-End Lint (push) Has been cancelled
Test / Medium Tests (Server) (push) Has been cancelled
Test / End-to-End Tests (Server & CLI) (ubuntu-24.04-arm) (push) Has been cancelled
Test / End-to-End Tests (Server & CLI) (ubuntu-latest) (push) Has been cancelled
Test / End-to-End Tests (Web) (ubuntu-24.04-arm) (push) Has been cancelled
Test / End-to-End Tests (Web) (ubuntu-latest) (push) Has been cancelled
Test / End-to-End Tests Success (push) Has been cancelled
Test / Unit Test Mobile (push) Has been cancelled
Test / Unit Test ML (push) Has been cancelled
Test / .github Files Formatting (push) Has been cancelled
Test / ShellCheck (push) Has been cancelled
Test / OpenAPI Clients (push) Has been cancelled
Test / SQL Schema Checks (push) Has been cancelled

* 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:
Sergey Katsubo
2025-11-13 00:38:03 +03:00
committed by GitHub
parent 8969b8bdb2
commit 2c54b506b3
3 changed files with 50 additions and 9 deletions

View File

@@ -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"
)

View File

@@ -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'),
)

View File

@@ -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);