From 7132dc3ac0cf878d2c326243747343e8a6746e2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20S=C3=B3jko?= Date: Wed, 7 Sep 2022 16:16:27 +0200 Subject: [PATCH] feat(analytics): add calculation retention for two activities --- .../Analytics/AnalyticsStoreInterface.ts | 6 ++++ .../Infra/Redis/RedisAnalyticsStore.spec.ts | 2 +- .../src/Infra/Redis/RedisAnalyticsStore.ts | 35 ++++++++++++------- .../Infra/Redis/RedisStatisticsStore.spec.ts | 8 ++--- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/packages/analytics/src/Domain/Analytics/AnalyticsStoreInterface.ts b/packages/analytics/src/Domain/Analytics/AnalyticsStoreInterface.ts index 62bd8f778..6912bde6d 100644 --- a/packages/analytics/src/Domain/Analytics/AnalyticsStoreInterface.ts +++ b/packages/analytics/src/Domain/Analytics/AnalyticsStoreInterface.ts @@ -6,6 +6,12 @@ export interface AnalyticsStoreInterface { markActivity(activities: AnalyticsActivity[], analyticsId: number, periods: Period[]): Promise wasActivityDone(activity: AnalyticsActivity, analyticsId: number, period: Period): Promise calculateActivityRetention(activity: AnalyticsActivity, firstPeriod: Period, secondPeriod: Period): Promise + calculateActivitiesRetention(parameters: { + firstActivity: AnalyticsActivity + firstActivityPeriodKey: string + secondActivity: AnalyticsActivity + secondActivityPeriodKey: string + }): Promise calculateActivityTotalCount(activity: AnalyticsActivity, period: Period): Promise calculateActivityChangesTotalCount( activity: AnalyticsActivity, diff --git a/packages/analytics/src/Infra/Redis/RedisAnalyticsStore.spec.ts b/packages/analytics/src/Infra/Redis/RedisAnalyticsStore.spec.ts index a511dde5d..346fd43c1 100644 --- a/packages/analytics/src/Infra/Redis/RedisAnalyticsStore.spec.ts +++ b/packages/analytics/src/Infra/Redis/RedisAnalyticsStore.spec.ts @@ -125,7 +125,7 @@ describe('RedisAnalyticsStore', () => { expect(redisClient.bitop).toHaveBeenCalledWith( 'AND', - 'bitmap:action:editing-items:timespan:period-key-period-key', + 'bitmap:action:editing-items-editing-items:timespan:period-key', 'bitmap:action:editing-items:timespan:period-key', 'bitmap:action:editing-items:timespan:period-key', ) diff --git a/packages/analytics/src/Infra/Redis/RedisAnalyticsStore.ts b/packages/analytics/src/Infra/Redis/RedisAnalyticsStore.ts index 7812a534d..b2baef024 100644 --- a/packages/analytics/src/Infra/Redis/RedisAnalyticsStore.ts +++ b/packages/analytics/src/Infra/Redis/RedisAnalyticsStore.ts @@ -95,21 +95,19 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface { return bitValue === 1 } - async calculateActivityRetention( - activity: AnalyticsActivity, - firstPeriod: Period, - secondPeriod: Period, - ): Promise { - const initialPeriodKey = this.periodKeyGenerator.getPeriodKey(firstPeriod) - const subsequentPeriodKey = this.periodKeyGenerator.getPeriodKey(secondPeriod) - - const diffKey = `bitmap:action:${activity}:timespan:${initialPeriodKey}-${subsequentPeriodKey}` + async calculateActivitiesRetention(parameters: { + firstActivity: AnalyticsActivity + firstActivityPeriodKey: string + secondActivity: AnalyticsActivity + secondActivityPeriodKey: string + }): Promise { + const diffKey = `bitmap:action:${parameters.firstActivity}-${parameters.secondActivity}:timespan:${parameters.secondActivityPeriodKey}` await this.redisClient.bitop( 'AND', diffKey, - `bitmap:action:${activity}:timespan:${initialPeriodKey}`, - `bitmap:action:${activity}:timespan:${subsequentPeriodKey}`, + `bitmap:action:${parameters.firstActivity}:timespan:${parameters.firstActivityPeriodKey}`, + `bitmap:action:${parameters.secondActivity}:timespan:${parameters.secondActivityPeriodKey}`, ) await this.redisClient.expire(diffKey, 3600) @@ -117,12 +115,25 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface { const retainedTotalInActivity = await this.redisClient.bitcount(diffKey) const initialTotalInActivity = await this.redisClient.bitcount( - `bitmap:action:${activity}:timespan:${initialPeriodKey}`, + `bitmap:action:${parameters.firstActivity}:timespan:${parameters.firstActivityPeriodKey}`, ) return Math.ceil((retainedTotalInActivity * 100) / initialTotalInActivity) } + async calculateActivityRetention( + activity: AnalyticsActivity, + firstPeriod: Period, + secondPeriod: Period, + ): Promise { + return this.calculateActivitiesRetention({ + firstActivity: activity, + firstActivityPeriodKey: this.periodKeyGenerator.getPeriodKey(firstPeriod), + secondActivity: activity, + secondActivityPeriodKey: this.periodKeyGenerator.getPeriodKey(secondPeriod), + }) + } + async calculateActivityTotalCount(activity: AnalyticsActivity, period: Period): Promise { return this.redisClient.bitcount( `bitmap:action:${activity}:timespan:${this.periodKeyGenerator.getPeriodKey(period)}`, diff --git a/packages/analytics/src/Infra/Redis/RedisStatisticsStore.spec.ts b/packages/analytics/src/Infra/Redis/RedisStatisticsStore.spec.ts index 92e061bef..e8b9832d1 100644 --- a/packages/analytics/src/Infra/Redis/RedisStatisticsStore.spec.ts +++ b/packages/analytics/src/Infra/Redis/RedisStatisticsStore.spec.ts @@ -93,7 +93,7 @@ describe('RedisStatisticsStore', () => { }) it('should increment measure by a value', async () => { - await createStore().incrementMeasure(StatisticsMeasure.PaymentSuccess, 2, [Period.Today, Period.ThisMonth]) + await createStore().incrementMeasure(StatisticsMeasure.Income, 2, [Period.Today, Period.ThisMonth]) expect(pipeline.incr).toHaveBeenCalledTimes(2) expect(pipeline.incrbyfloat).toHaveBeenCalledTimes(2) @@ -103,18 +103,18 @@ describe('RedisStatisticsStore', () => { it('should count a measurement average', async () => { redisClient.get = jest.fn().mockReturnValueOnce('5').mockReturnValueOnce('2') - expect(await createStore().getMeasureAverage(StatisticsMeasure.PaymentSuccess, Period.Today)).toEqual(2 / 5) + expect(await createStore().getMeasureAverage(StatisticsMeasure.Income, Period.Today)).toEqual(2 / 5) }) it('should count a measurement average - 0 increments', async () => { redisClient.get = jest.fn().mockReturnValueOnce(null).mockReturnValueOnce(null) - expect(await createStore().getMeasureAverage(StatisticsMeasure.PaymentSuccess, Period.Today)).toEqual(0) + expect(await createStore().getMeasureAverage(StatisticsMeasure.Income, Period.Today)).toEqual(0) }) it('should count a measurement average - 0 total value', async () => { redisClient.get = jest.fn().mockReturnValueOnce(5).mockReturnValueOnce(null) - expect(await createStore().getMeasureAverage(StatisticsMeasure.PaymentSuccess, Period.Today)).toEqual(0) + expect(await createStore().getMeasureAverage(StatisticsMeasure.Income, Period.Today)).toEqual(0) }) })