-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(server): wait 60 seconds before sending email on new album item
Album update jobs will now wait a minute to send. If a new image is added while that job is pending, the old job will be cancelled, and a new one will be enqueued for a minute. This is to prevent a flood of notifications by dragging in images directly to the album, which adds them to the album one at a time. Album updates now include a list of users to email, which is generally everybody except the updater. If somebody else updates the album within that minute, both people will get an album update email in a minute, as they both added images and the other should be notified.
- Loading branch information
1 parent
28bc7f3
commit d79fb91
Showing
9 changed files
with
99 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ import { newLoggerRepositoryMock } from 'test/repositories/logger.repository.moc | |
import { newNotificationRepositoryMock } from 'test/repositories/notification.repository.mock'; | ||
import { newSystemMetadataRepositoryMock } from 'test/repositories/system-metadata.repository.mock'; | ||
import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; | ||
import { Mocked } from 'vitest'; | ||
import { expect, Mocked } from 'vitest'; | ||
|
||
const configs = { | ||
smtpDisabled: Object.freeze<SystemConfig>({ | ||
|
@@ -148,10 +148,10 @@ describe(NotificationService.name, () => { | |
|
||
describe('onAlbumUpdateEvent', () => { | ||
it('should queue notify album update event', async () => { | ||
await sut.onAlbumUpdate({ id: '', updatedBy: '42' }); | ||
await sut.onAlbumUpdate({ id: 'album', recipientIds: ['42'] }); | ||
expect(jobMock.queue).toHaveBeenCalledWith({ | ||
name: JobName.NOTIFY_ALBUM_UPDATE, | ||
data: { id: '', senderId: '42' }, | ||
data: { id: 'album', recipientIds: ['42'], delay: 60_000 }, | ||
}); | ||
}); | ||
}); | ||
|
@@ -422,34 +422,17 @@ describe(NotificationService.name, () => { | |
|
||
describe('handleAlbumUpdate', () => { | ||
it('should skip if album could not be found', async () => { | ||
await expect(sut.handleAlbumUpdate({ id: '', senderId: '' })).resolves.toBe(JobStatus.SKIPPED); | ||
await expect(sut.handleAlbumUpdate({ id: '', recipientIds: ['1'] })).resolves.toBe(JobStatus.SKIPPED); | ||
expect(userMock.get).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should skip if owner could not be found', async () => { | ||
albumMock.getById.mockResolvedValue(albumStub.emptyWithValidThumbnail); | ||
|
||
await expect(sut.handleAlbumUpdate({ id: '', senderId: '' })).resolves.toBe(JobStatus.SKIPPED); | ||
await expect(sut.handleAlbumUpdate({ id: '', recipientIds: ['1'] })).resolves.toBe(JobStatus.SKIPPED); | ||
expect(systemMock.get).not.toHaveBeenCalled(); | ||
}); | ||
|
||
it('should filter out the sender', async () => { | ||
albumMock.getById.mockResolvedValue({ | ||
...albumStub.emptyWithValidThumbnail, | ||
albumUsers: [ | ||
{ user: { id: userStub.user1.id } } as AlbumUserEntity, | ||
{ user: { id: userStub.user2.id } } as AlbumUserEntity, | ||
], | ||
}); | ||
userMock.get.mockResolvedValue(userStub.user1); | ||
notificationMock.renderEmail.mockResolvedValue({ html: '', text: '' }); | ||
|
||
await sut.handleAlbumUpdate({ id: '', senderId: userStub.user1.id }); | ||
expect(userMock.get).not.toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); | ||
expect(userMock.get).toHaveBeenCalledWith(userStub.user2.id, { withDeleted: false }); | ||
expect(notificationMock.renderEmail).toHaveBeenCalledOnce(); | ||
}); | ||
|
||
it('should skip recipient that could not be looked up', async () => { | ||
albumMock.getById.mockResolvedValue({ | ||
...albumStub.emptyWithValidThumbnail, | ||
|
@@ -458,7 +441,7 @@ describe(NotificationService.name, () => { | |
userMock.get.mockResolvedValueOnce(userStub.user1); | ||
notificationMock.renderEmail.mockResolvedValue({ html: '', text: '' }); | ||
|
||
await sut.handleAlbumUpdate({ id: '', senderId: '' }); | ||
await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); | ||
expect(userMock.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); | ||
expect(notificationMock.renderEmail).not.toHaveBeenCalled(); | ||
}); | ||
|
@@ -481,7 +464,7 @@ describe(NotificationService.name, () => { | |
}); | ||
notificationMock.renderEmail.mockResolvedValue({ html: '', text: '' }); | ||
|
||
await sut.handleAlbumUpdate({ id: '', senderId: '' }); | ||
await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); | ||
expect(userMock.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); | ||
expect(notificationMock.renderEmail).not.toHaveBeenCalled(); | ||
}); | ||
|
@@ -504,7 +487,7 @@ describe(NotificationService.name, () => { | |
}); | ||
notificationMock.renderEmail.mockResolvedValue({ html: '', text: '' }); | ||
|
||
await sut.handleAlbumUpdate({ id: '', senderId: '' }); | ||
await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); | ||
expect(userMock.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); | ||
expect(notificationMock.renderEmail).not.toHaveBeenCalled(); | ||
}); | ||
|
@@ -517,11 +500,25 @@ describe(NotificationService.name, () => { | |
userMock.get.mockResolvedValue(userStub.user1); | ||
notificationMock.renderEmail.mockResolvedValue({ html: '', text: '' }); | ||
|
||
await sut.handleAlbumUpdate({ id: '', senderId: '' }); | ||
await sut.handleAlbumUpdate({ id: '', recipientIds: [userStub.user1.id] }); | ||
expect(userMock.get).toHaveBeenCalledWith(userStub.user1.id, { withDeleted: false }); | ||
expect(notificationMock.renderEmail).toHaveBeenCalled(); | ||
expect(jobMock.queue).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should add new recipients for new images if job is already queued', async () => { | ||
// @ts-ignore | ||
jobMock.removeJob.mockResolvedValue({ id: '1', recipientIds: ['2', '3', '4'] }); | ||
await sut.onAlbumUpdate({ id: '1', recipientIds: ['1', '2', '3'] }); | ||
expect(jobMock.queue).toHaveBeenCalledWith({ | ||
name: JobName.NOTIFY_ALBUM_UPDATE, | ||
data: { | ||
id: '1', | ||
delay: 60_000, | ||
recipientIds: ['1', '2', '3', '4'], | ||
}, | ||
}); | ||
}); | ||
}); | ||
|
||
Check failure on line 523 in server/src/services/notification.service.spec.ts GitHub Actions / Test & Lint Server
|
||
describe('handleSendEmail', () => { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters