mirror of
https://github.com/standardnotes/server
synced 2026-07-14 00:01:54 -04:00
feat(analytics): add calculation retention for two activities
This commit is contained in:
@@ -6,6 +6,12 @@ export interface AnalyticsStoreInterface {
|
||||
markActivity(activities: AnalyticsActivity[], analyticsId: number, periods: Period[]): Promise<void>
|
||||
wasActivityDone(activity: AnalyticsActivity, analyticsId: number, period: Period): Promise<boolean>
|
||||
calculateActivityRetention(activity: AnalyticsActivity, firstPeriod: Period, secondPeriod: Period): Promise<number>
|
||||
calculateActivitiesRetention(parameters: {
|
||||
firstActivity: AnalyticsActivity
|
||||
firstActivityPeriodKey: string
|
||||
secondActivity: AnalyticsActivity
|
||||
secondActivityPeriodKey: string
|
||||
}): Promise<number>
|
||||
calculateActivityTotalCount(activity: AnalyticsActivity, period: Period): Promise<number>
|
||||
calculateActivityChangesTotalCount(
|
||||
activity: AnalyticsActivity,
|
||||
|
||||
@@ -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',
|
||||
)
|
||||
|
||||
@@ -95,21 +95,19 @@ export class RedisAnalyticsStore implements AnalyticsStoreInterface {
|
||||
return bitValue === 1
|
||||
}
|
||||
|
||||
async calculateActivityRetention(
|
||||
activity: AnalyticsActivity,
|
||||
firstPeriod: Period,
|
||||
secondPeriod: Period,
|
||||
): Promise<number> {
|
||||
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<number> {
|
||||
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<number> {
|
||||
return this.calculateActivitiesRetention({
|
||||
firstActivity: activity,
|
||||
firstActivityPeriodKey: this.periodKeyGenerator.getPeriodKey(firstPeriod),
|
||||
secondActivity: activity,
|
||||
secondActivityPeriodKey: this.periodKeyGenerator.getPeriodKey(secondPeriod),
|
||||
})
|
||||
}
|
||||
|
||||
async calculateActivityTotalCount(activity: AnalyticsActivity, period: Period): Promise<number> {
|
||||
return this.redisClient.bitcount(
|
||||
`bitmap:action:${activity}:timespan:${this.periodKeyGenerator.getPeriodKey(period)}`,
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user