From 5f79ffce344346a5ec260afd6d55da15b750316c Mon Sep 17 00:00:00 2001 From: johnmasking Date: Mon, 28 Oct 2024 11:08:48 +0100 Subject: [PATCH 1/5] #343 Resillience code plus test --- .../getRecentAggregated/feature.ts | 19 ++++++++++++++- src/domain/post/exploreAggregated/feature.ts | 19 ++++++++++++++- src/domain/post/getAllAggregated/feature.ts | 19 ++++++++++++++- .../post/getByCreatorAggregated/feature.ts | 20 +++++++++++++++- .../post/getByFollowingAggregated/feature.ts | 19 ++++++++++++++- .../reaction/getByPostAggregated/feature.ts | 19 ++++++++++++++- .../notification/getAllAggregated.spec.ts | 24 +++++++++++++++++++ 7 files changed, 133 insertions(+), 6 deletions(-) diff --git a/src/domain/notification/getRecentAggregated/feature.ts b/src/domain/notification/getRecentAggregated/feature.ts index 87ca29c0..21770f73 100644 --- a/src/domain/notification/getRecentAggregated/feature.ts +++ b/src/domain/notification/getRecentAggregated/feature.ts @@ -2,6 +2,7 @@ import type { Requester } from '^/domain/authentication/types'; import { Range } from '^/domain/common/types'; import validateRange from '^/domain/common/validateRange/feature'; +import logger from '^/integrations/logging/module'; import aggregate from '../aggregate/feature'; import type { AggregatedData } from '../aggregate/types'; @@ -13,5 +14,21 @@ export default async function feature(requester: Requester, range: Range): Promi const data = await getRecent(requester.id, range.limit, range.offset); - return Promise.all(data.map(item => aggregate(requester, item))); + const notifications: AggregatedData[] = []; + + const promises = await Promise.allSettled(data.map(item => aggregate(requester, item))); + + promises.forEach((promise) => + { + if (promise.status === 'rejected') + { + logger.logError('Error on aggregating Notification', promise.reason); + + return; + } + + notifications.push(promise.value); + }); + + return (notifications); } diff --git a/src/domain/post/exploreAggregated/feature.ts b/src/domain/post/exploreAggregated/feature.ts index 646b259d..dc886507 100644 --- a/src/domain/post/exploreAggregated/feature.ts +++ b/src/domain/post/exploreAggregated/feature.ts @@ -2,6 +2,7 @@ import type { Requester } from '^/domain/authentication/types'; import type { Range } from '^/domain/common/types'; import validateRange from '^/domain/common/validateRange/feature'; +import logger from '^/integrations/logging/module'; import aggregate from '../aggregate/feature'; import type { AggregatedData } from '../aggregate/types'; @@ -13,5 +14,21 @@ export default async function feature(requester: Requester, range: Range): Promi const data = await explore(requester, range.limit, range.offset); - return Promise.all(data.map(item => aggregate(requester, item))); + const posts: AggregatedData[] = []; + + const promises = await Promise.allSettled(data.map(item => aggregate(requester, item))); + + promises.forEach((promise) => + { + if (promise.status === 'rejected') + { + logger.logError('Error on aggregating Post', promise.reason); + + return; + } + + posts.push(promise.value); + }); + + return posts; } diff --git a/src/domain/post/getAllAggregated/feature.ts b/src/domain/post/getAllAggregated/feature.ts index eaf828bc..b4003e4c 100644 --- a/src/domain/post/getAllAggregated/feature.ts +++ b/src/domain/post/getAllAggregated/feature.ts @@ -2,6 +2,7 @@ import type { Requester } from '^/domain/authentication/types'; import type { Range } from '^/domain/common/types'; import validateRange from '^/domain/common/validateRange/feature'; +import logger from '^/integrations/logging/module'; import aggregate from '../aggregate/feature'; import type { AggregatedData } from '../aggregate/types'; @@ -13,5 +14,21 @@ export default async function feature(requester: Requester, range: Range): Promi const data = await getAll(requester, range.limit, range.offset); - return Promise.all(data.map(item => aggregate(requester, item))); + const posts: AggregatedData[] = []; + + const promises = await Promise.allSettled(data.map(item => aggregate(requester, item))); + + promises.forEach((promise) => + { + if (promise.status === 'rejected') + { + logger.logError('Error on aggregating Post', promise.reason); + + return; + } + + posts.push(promise.value); + }); + + return posts; } diff --git a/src/domain/post/getByCreatorAggregated/feature.ts b/src/domain/post/getByCreatorAggregated/feature.ts index c07de6fb..852567f9 100644 --- a/src/domain/post/getByCreatorAggregated/feature.ts +++ b/src/domain/post/getByCreatorAggregated/feature.ts @@ -2,6 +2,7 @@ import type { Requester } from '^/domain/authentication/types'; import { Range } from '^/domain/common/types'; import validateRange from '^/domain/common/validateRange/feature'; +import logger from '^/integrations/logging/module'; import aggregate from '../aggregate/feature'; import type { AggregatedData } from '../aggregate/types'; @@ -15,5 +16,22 @@ export default async function feature(requester: Requester, creatorId: string, r const data = await getByCreator(creatorId, range.limit, range.offset); - return Promise.all(data.map(item => aggregate(requester, item))); + const posts: AggregatedData[] = []; + + const promises = Promise.allSettled(data.map(item => aggregate(requester, item))); + + (await promises).forEach((promise) => + { + if (promise.status === 'rejected') + { + logger.logError('Error on aggregating Post', promise.reason); + + return; + } + + posts.push(promise.value); + + }); + + return posts; } diff --git a/src/domain/post/getByFollowingAggregated/feature.ts b/src/domain/post/getByFollowingAggregated/feature.ts index 8085cb03..64d3aef9 100644 --- a/src/domain/post/getByFollowingAggregated/feature.ts +++ b/src/domain/post/getByFollowingAggregated/feature.ts @@ -2,6 +2,7 @@ import type { Requester } from '^/domain/authentication/types'; import type { Range } from '^/domain/common/types'; import validateRange from '^/domain/common/validateRange/feature'; +import logger from '^/integrations/logging/module'; import aggregate from '../aggregate/feature'; import type { AggregatedData } from '../aggregate/types'; @@ -13,5 +14,21 @@ export default async function feature(requester: Requester, range: Range): Promi const data = await getByFollowing(requester, range.limit, range.offset); - return Promise.all(data.map(item => aggregate(requester, item))); + const posts: AggregatedData[] = []; + + const promises = await Promise.allSettled(data.map(item => aggregate(requester, item))); + + promises.forEach((promise) => + { + if (promise.status === 'rejected') + { + logger.logError('Error aggrgating Post', promise.reason); + + return; + } + + posts.push(promise.value); + }); + + return posts; } diff --git a/src/domain/reaction/getByPostAggregated/feature.ts b/src/domain/reaction/getByPostAggregated/feature.ts index c2789d23..5223e64a 100644 --- a/src/domain/reaction/getByPostAggregated/feature.ts +++ b/src/domain/reaction/getByPostAggregated/feature.ts @@ -1,6 +1,7 @@ import type { Requester } from '^/domain/authentication/types'; import { Range } from '^/domain/common/types'; +import logger from '^/integrations/logging/module'; import aggregate from '../aggregate/feature'; import type { AggregatedData } from '../aggregate/types'; @@ -10,5 +11,21 @@ export default async function feature(requester: Requester, postId: string, rang { const data = await getByPost(postId, range.limit, range.offset); - return Promise.all(data.map(item => aggregate(requester, item))); + const reactions: AggregatedData[] = []; + + const promises = await Promise.allSettled(data.map(item => aggregate(requester, item))); + + promises.forEach((promise) => + { + if (promise.status === 'rejected') + { + logger.logError('Error on aggregating Reaction', promise.reason); + + return; + } + + reactions.push(promise.value); + }); + + return reactions; } diff --git a/test/domain/notification/getAllAggregated.spec.ts b/test/domain/notification/getAllAggregated.spec.ts index a765dcc2..16529c76 100644 --- a/test/domain/notification/getAllAggregated.spec.ts +++ b/test/domain/notification/getAllAggregated.spec.ts @@ -3,6 +3,7 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { Types } from '^/domain/notification/definitions'; import getRecentAggregated from '^/domain/notification/getRecentAggregated/feature'; +import remove from '^/domain/post/remove/feature'; import { DATABASES, FILE_STORES, REQUESTERS, VALUES } from './fixtures'; beforeEach(async () => @@ -40,4 +41,27 @@ describe('domain/notification/getallAggregated', () => expect(notification3.reaction?.id).toBe(VALUES.IDS.REACTION_LIKED); expect(notification3.relation.following.id).toBe(VALUES.IDS.CREATOR2); }); + + it('should give the valid posts only', async () => + { + await remove(REQUESTERS.CREATOR1, VALUES.IDS.POST_RATED); + + const result = await getRecentAggregated(REQUESTERS.CREATOR1, { offset: 0, limit: 7 }); + + expect(result).toHaveLength(2); + + const notification1 = result[0]; + const notification2 = result[1]; + + expect(notification1.type).toBe(Types.STARTED_FOLLOWING); + expect(notification1.post).toBe(undefined); + expect(notification1.reaction).toBe(undefined); + expect(notification1.relation.following.id).toBe(VALUES.IDS.CREATOR2); + + expect(notification2.type).toBe(Types.RATED_REACTION); + expect(notification2.post).toBe(undefined); + expect(notification2.reaction?.id).toBe(VALUES.IDS.REACTION_LIKED); + expect(notification2.relation.following.id).toBe(VALUES.IDS.CREATOR2); + + }); }); From 88efc648b27da91532e2e36d88e460d527b80842 Mon Sep 17 00:00:00 2001 From: johnmasking Date: Mon, 4 Nov 2024 14:10:33 +0100 Subject: [PATCH 2/5] #343 proces review comment --- test/domain/notification/fixtures/records.fixture.ts | 4 +++- test/domain/notification/fixtures/values.fixture.ts | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/test/domain/notification/fixtures/records.fixture.ts b/test/domain/notification/fixtures/records.fixture.ts index 6df17b35..05e4a9aa 100644 --- a/test/domain/notification/fixtures/records.fixture.ts +++ b/test/domain/notification/fixtures/records.fixture.ts @@ -23,6 +23,7 @@ export const RECORDS: Record> = POSTS: [ { id: VALUES.IDS.POST_RATED, creatorId: REQUESTERS.CREATOR1.id, comicId: VALUES.IDS.COMIC, createdAt: new Date(), ratingCount: 10, reactionCount: 0, deleted: false }, + { id: VALUES.IDS.POST_DELETED, creatorId: REQUESTERS.CREATOR1.id, comicId: VALUES.IDS.COMIC, createdAt: new Date(), ratingCount: 5, reactionCount: 1, deleted: true }, ], REACTIONS: [ @@ -38,7 +39,8 @@ export const RECORDS: Record> = { id: VALUES.IDS.NOTIFICATION1, createdAt: new Date(), type: Types.STARTED_FOLLOWING, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR2, postId: undefined, reactionId: undefined }, { id: VALUES.IDS.NOTIFICATION2, createdAt: new Date(), type: Types.STARTED_FOLLOWING, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: undefined, reactionId: undefined }, { id: VALUES.IDS.NOTIFICATION3, createdAt: new Date('01-05-2024'), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR3, receiverId: VALUES.IDS.CREATOR1, postId: VALUES.IDS.POST_RATED, reactionId: undefined }, - { id: VALUES.IDS.NOTIFICATION4, createdAt: new Date('01-04-2024'), type: Types.RATED_REACTION, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: undefined, reactionId: VALUES.IDS.REACTION_LIKED } + { id: VALUES.IDS.NOTIFICATION4, createdAt: new Date('01-04-2024'), type: Types.RATED_REACTION, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: undefined, reactionId: VALUES.IDS.REACTION_LIKED }, + { id: VALUES.IDS.NOTIFICATION5, createdAt: new Date('01-03-2024'), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR1, postId: VALUES.IDS.POST_DELETED, reactionId: undefined }, ], }; diff --git a/test/domain/notification/fixtures/values.fixture.ts b/test/domain/notification/fixtures/values.fixture.ts index 6c8884b8..439b7037 100644 --- a/test/domain/notification/fixtures/values.fixture.ts +++ b/test/domain/notification/fixtures/values.fixture.ts @@ -5,6 +5,7 @@ export const VALUES = COMIC: 'C1', IMAGE: 'I1', POST_RATED: 'P1', + POST_DELETED: 'P2', REACTION_LIKED: 'R1', @@ -15,6 +16,7 @@ export const VALUES = NOTIFICATION2: 'N2', NOTIFICATION3: 'N3', NOTIFICATION4: 'N4', + NOTIFICATION5: 'N5', CREATOR1: 'CR1', CREATOR2: 'CR2', From c199416726e8fc1353b51734d8a8f8c3144a52f5 Mon Sep 17 00:00:00 2001 From: johnmasking Date: Mon, 4 Nov 2024 15:06:01 +0100 Subject: [PATCH 3/5] #343 correct fixtures --- .../notification/fixtures/records.fixture.ts | 2 +- .../notification/getAllAggregated.spec.ts | 18 +++++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/test/domain/notification/fixtures/records.fixture.ts b/test/domain/notification/fixtures/records.fixture.ts index 05e4a9aa..b71f5eac 100644 --- a/test/domain/notification/fixtures/records.fixture.ts +++ b/test/domain/notification/fixtures/records.fixture.ts @@ -38,7 +38,7 @@ export const RECORDS: Record> = NOTIFICATIONS: [ { id: VALUES.IDS.NOTIFICATION1, createdAt: new Date(), type: Types.STARTED_FOLLOWING, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR2, postId: undefined, reactionId: undefined }, { id: VALUES.IDS.NOTIFICATION2, createdAt: new Date(), type: Types.STARTED_FOLLOWING, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: undefined, reactionId: undefined }, - { id: VALUES.IDS.NOTIFICATION3, createdAt: new Date('01-05-2024'), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR3, receiverId: VALUES.IDS.CREATOR1, postId: VALUES.IDS.POST_RATED, reactionId: undefined }, + { id: VALUES.IDS.NOTIFICATION3, createdAt: new Date('01-05-2024'), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR3, receiverId: VALUES.IDS.CREATOR2, postId: VALUES.IDS.POST_RATED, reactionId: undefined }, { id: VALUES.IDS.NOTIFICATION4, createdAt: new Date('01-04-2024'), type: Types.RATED_REACTION, senderId: VALUES.IDS.CREATOR2, receiverId: VALUES.IDS.CREATOR1, postId: undefined, reactionId: VALUES.IDS.REACTION_LIKED }, { id: VALUES.IDS.NOTIFICATION5, createdAt: new Date('01-03-2024'), type: Types.RATED_POST, senderId: VALUES.IDS.CREATOR1, receiverId: VALUES.IDS.CREATOR1, postId: VALUES.IDS.POST_DELETED, reactionId: undefined }, ], diff --git a/test/domain/notification/getAllAggregated.spec.ts b/test/domain/notification/getAllAggregated.spec.ts index 16529c76..59780d78 100644 --- a/test/domain/notification/getAllAggregated.spec.ts +++ b/test/domain/notification/getAllAggregated.spec.ts @@ -3,7 +3,6 @@ import { beforeEach, describe, expect, it } from 'vitest'; import { Types } from '^/domain/notification/definitions'; import getRecentAggregated from '^/domain/notification/getRecentAggregated/feature'; -import remove from '^/domain/post/remove/feature'; import { DATABASES, FILE_STORES, REQUESTERS, VALUES } from './fixtures'; beforeEach(async () => @@ -16,36 +15,29 @@ beforeEach(async () => describe('domain/notification/getallAggregated', () => { - it('should give all posts for the requester', async () => + it('should give all posts for the requester2', async () => { - const result = await getRecentAggregated(REQUESTERS.CREATOR1, { offset: 0, limit: 7 }); + const result = await getRecentAggregated(REQUESTERS.CREATOR2, { offset: 0, limit: 7 }); - expect(result).toHaveLength(3); + expect(result).toHaveLength(2); const notification1 = result[0]; const notification2 = result[1]; - const notification3 = result[2]; expect(notification1.type).toBe(Types.STARTED_FOLLOWING); expect(notification1.post).toBe(undefined); expect(notification1.reaction).toBe(undefined); - expect(notification1.relation.following.id).toBe(VALUES.IDS.CREATOR2); + expect(notification1.relation.following.id).toBe(VALUES.IDS.CREATOR1); expect(notification2.type).toBe(Types.RATED_POST); expect(notification2.post?.id).toBe(VALUES.IDS.POST_RATED); expect(notification2.reaction).toBe(undefined); expect(notification2.relation.following.id).toBe(VALUES.IDS.CREATOR3); - expect(notification3.type).toBe(Types.RATED_REACTION); - expect(notification3.post).toBe(undefined); - expect(notification3.reaction?.id).toBe(VALUES.IDS.REACTION_LIKED); - expect(notification3.relation.following.id).toBe(VALUES.IDS.CREATOR2); }); - it('should give the valid posts only', async () => + it('should give the valid posts only for requester1', async () => { - await remove(REQUESTERS.CREATOR1, VALUES.IDS.POST_RATED); - const result = await getRecentAggregated(REQUESTERS.CREATOR1, { offset: 0, limit: 7 }); expect(result).toHaveLength(2); From b54f346c822337352a71b09bb2e0f40722586c50 Mon Sep 17 00:00:00 2001 From: johnmasking Date: Fri, 8 Nov 2024 08:29:24 +0100 Subject: [PATCH 4/5] #343 attempt to satisfy review comment --- test/domain/notification/getAllAggregated.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/domain/notification/getAllAggregated.spec.ts b/test/domain/notification/getAllAggregated.spec.ts index 59780d78..3ec2ce5d 100644 --- a/test/domain/notification/getAllAggregated.spec.ts +++ b/test/domain/notification/getAllAggregated.spec.ts @@ -36,7 +36,7 @@ describe('domain/notification/getallAggregated', () => }); - it('should give the valid posts only for requester1', async () => + it('should give only the posts without errors for requester1', async () => { const result = await getRecentAggregated(REQUESTERS.CREATOR1, { offset: 0, limit: 7 }); From 4290d62a1aeb83b0112d8fa183bad2cc27b4dcfc Mon Sep 17 00:00:00 2001 From: johnmasking Date: Fri, 15 Nov 2024 14:46:13 +0100 Subject: [PATCH 5/5] #343 correct testname/comments --- .../{getAllAggregated.spec.ts => getRecentAggregated.spec.ts} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename test/domain/notification/{getAllAggregated.spec.ts => getRecentAggregated.spec.ts} (92%) diff --git a/test/domain/notification/getAllAggregated.spec.ts b/test/domain/notification/getRecentAggregated.spec.ts similarity index 92% rename from test/domain/notification/getAllAggregated.spec.ts rename to test/domain/notification/getRecentAggregated.spec.ts index 3ec2ce5d..9b0c57f7 100644 --- a/test/domain/notification/getAllAggregated.spec.ts +++ b/test/domain/notification/getRecentAggregated.spec.ts @@ -15,7 +15,7 @@ beforeEach(async () => describe('domain/notification/getallAggregated', () => { - it('should give all posts for the requester2', async () => + it('should give all notifications for the requester2', async () => { const result = await getRecentAggregated(REQUESTERS.CREATOR2, { offset: 0, limit: 7 }); @@ -36,7 +36,7 @@ describe('domain/notification/getallAggregated', () => }); - it('should give only the posts without errors for requester1', async () => + it('should give only the notifications without aggregation errors for requester1', async () => { const result = await getRecentAggregated(REQUESTERS.CREATOR1, { offset: 0, limit: 7 });