fix(analytics): throwing errors on unexisting users

This commit is contained in:
Karol Sójko 2023-09-01 08:17:22 +02:00
parent f77ed8ef94
commit c511f259c7
No known key found for this signature in database
GPG key ID: C2F813669419D05F
13 changed files with 65 additions and 28 deletions

View file

@ -17,7 +17,11 @@ export class PaymentFailedEventHandler implements DomainEventHandlerInterface {
) {}
async handle(event: PaymentFailedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId } = analyticsMetadataOrError.getValue()
await this.analyticsStore.markActivity([AnalyticsActivity.PaymentFailed], analyticsId, [
Period.Today,
Period.ThisWeek,

View file

@ -88,7 +88,11 @@ export class PaymentSuccessEventHandler implements DomainEventHandlerInterface {
) {}
async handle(event: PaymentSuccessEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId } = analyticsMetadataOrError.getValue()
await this.analyticsStore.markActivity([AnalyticsActivity.PaymentSuccess], analyticsId, [
Period.Today,
Period.ThisWeek,

View file

@ -17,8 +17,11 @@ export class RefundProcessedEventHandler implements DomainEventHandlerInterface
) {}
async handle(event: RefundProcessedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId } = analyticsMetadataOrError.getValue()
await this.statisticsStore.incrementMeasure(StatisticMeasureName.NAMES.Refunds, event.payload.amount, [
Period.Today,
Period.ThisWeek,

View file

@ -13,7 +13,11 @@ export class SessionCreatedEventHandler implements DomainEventHandlerInterface {
) {}
async handle(event: SessionCreatedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: event.payload.userUuid })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userUuid: event.payload.userUuid })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId } = analyticsMetadataOrError.getValue()
if (this.mixpanelClient !== null) {
this.mixpanelClient.track(event.type, {

View file

@ -13,7 +13,11 @@ export class SessionRefreshedEventHandler implements DomainEventHandlerInterface
) {}
async handle(event: SessionRefreshedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userUuid: event.payload.userUuid })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userUuid: event.payload.userUuid })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId } = analyticsMetadataOrError.getValue()
if (this.mixpanelClient !== null) {
this.mixpanelClient.track(event.type, {

View file

@ -29,7 +29,11 @@ export class SubscriptionCancelledEventHandler implements DomainEventHandlerInte
) {}
async handle(event: SubscriptionCancelledEvent): Promise<void> {
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId, userUuid } = analyticsMetadataOrError.getValue()
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionCancelled], analyticsId, [
Period.Today,
Period.ThisWeek,

View file

@ -27,7 +27,11 @@ export class SubscriptionExpiredEventHandler implements DomainEventHandlerInterf
) {}
async handle(event: SubscriptionExpiredEvent): Promise<void> {
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId, userUuid } = analyticsMetadataOrError.getValue()
await this.analyticsStore.markActivity(
[AnalyticsActivity.SubscriptionExpired, AnalyticsActivity.ExistingCustomersChurn],
analyticsId,

View file

@ -29,7 +29,11 @@ export class SubscriptionPurchasedEventHandler implements DomainEventHandlerInte
) {}
async handle(event: SubscriptionPurchasedEvent): Promise<void> {
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId, userUuid } = analyticsMetadataOrError.getValue()
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionPurchased], analyticsId, [
Period.Today,
Period.ThisWeek,

View file

@ -19,7 +19,11 @@ export class SubscriptionReactivatedEventHandler implements DomainEventHandlerIn
) {}
async handle(event: SubscriptionReactivatedEvent): Promise<void> {
const { analyticsId } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId } = analyticsMetadataOrError.getValue()
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionReactivated], analyticsId, [
Period.Today,
Period.ThisWeek,

View file

@ -27,7 +27,11 @@ export class SubscriptionRefundedEventHandler implements DomainEventHandlerInter
) {}
async handle(event: SubscriptionRefundedEvent): Promise<void> {
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId, userUuid } = analyticsMetadataOrError.getValue()
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionRefunded], analyticsId, [
Period.Today,
Period.ThisWeek,

View file

@ -26,7 +26,11 @@ export class SubscriptionRenewedEventHandler implements DomainEventHandlerInterf
) {}
async handle(event: SubscriptionRenewedEvent): Promise<void> {
const { analyticsId, userUuid } = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
const analyticsMetadataOrError = await this.getUserAnalyticsId.execute({ userEmail: event.payload.userEmail })
if (analyticsMetadataOrError.isFailed()) {
return
}
const { analyticsId, userUuid } = analyticsMetadataOrError.getValue()
await this.analyticsStore.markActivity([AnalyticsActivity.SubscriptionRenewed], analyticsId, [
Period.Today,
Period.ThisWeek,

View file

@ -24,23 +24,18 @@ describe('GetUserAnalyticsId', () => {
})
it('should return analytics id for a user by uuid', async () => {
expect((await createUseCase().execute({ userUuid: '1-2-3' })).analyticsId).toEqual(123)
expect((await createUseCase().execute({ userUuid: '1-2-3' })).getValue().analyticsId).toEqual(123)
})
it('should return analytics id for a user by email', async () => {
expect((await createUseCase().execute({ userEmail: 'test@test.te' })).analyticsId).toEqual(123)
expect((await createUseCase().execute({ userEmail: 'test@test.te' })).getValue().analyticsId).toEqual(123)
})
it('should throw error if user is missing analytics entity', async () => {
analyticsEntityRepository.findOneByUserUuid = jest.fn().mockReturnValue(null)
let error = null
try {
await createUseCase().execute({ userUuid: '1-2-3' })
} catch (caughtError) {
error = caughtError
}
const result = await createUseCase().execute({ userUuid: '1-2-3' })
expect(error).not.toBeNull()
expect(result.isFailed()).toEqual(true)
})
})

View file

@ -1,19 +1,18 @@
import { inject, injectable } from 'inversify'
import { Username, Uuid } from '@standardnotes/domain-core'
import { Result, UseCaseInterface, Username, Uuid } from '@standardnotes/domain-core'
import TYPES from '../../../Bootstrap/Types'
import { AnalyticsEntityRepositoryInterface } from '../../Entity/AnalyticsEntityRepositoryInterface'
import { UseCaseInterface } from '../UseCaseInterface'
import { GetUserAnalyticsIdDTO } from './GetUserAnalyticsIdDTO'
import { GetUserAnalyticsIdResponse } from './GetUserAnalyticsIdResponse'
@injectable()
export class GetUserAnalyticsId implements UseCaseInterface {
export class GetUserAnalyticsId implements UseCaseInterface<GetUserAnalyticsIdResponse> {
constructor(
@inject(TYPES.AnalyticsEntityRepository) private analyticsEntityRepository: AnalyticsEntityRepositoryInterface,
) {}
async execute(dto: GetUserAnalyticsIdDTO): Promise<GetUserAnalyticsIdResponse> {
async execute(dto: GetUserAnalyticsIdDTO): Promise<Result<GetUserAnalyticsIdResponse>> {
let analyticsEntity = null
if (dto.userUuid) {
analyticsEntity = await this.analyticsEntityRepository.findOneByUserUuid(dto.userUuid)
@ -22,13 +21,13 @@ export class GetUserAnalyticsId implements UseCaseInterface {
}
if (analyticsEntity === null) {
throw new Error(`Could not find analytics entity for user ${dto.userUuid}`)
return Result.fail(`Could not find analytics entity ${dto.userUuid}`)
}
return {
return Result.ok({
analyticsId: analyticsEntity.id,
userUuid: Uuid.create(analyticsEntity.userUuid).getValue(),
username: Username.create(analyticsEntity.username).getValue(),
}
})
}
}