From e8d2990c6caaf0825d315639782e8bef1ff66d48 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Wed, 9 Jul 2025 15:29:08 +0200 Subject: [PATCH] slim down rough idea --- src/lib/services/hubspot-reporting-service.ts | 197 ++---------------- 1 file changed, 14 insertions(+), 183 deletions(-) diff --git a/src/lib/services/hubspot-reporting-service.ts b/src/lib/services/hubspot-reporting-service.ts index aadd06b652..7153cd901e 100644 --- a/src/lib/services/hubspot-reporting-service.ts +++ b/src/lib/services/hubspot-reporting-service.ts @@ -1,65 +1,29 @@ import type EventEmitter from 'events'; -import groupBy from 'lodash.groupby'; import { - FEATURE_CREATED, - CLIENT_METRICS_ADDED, - FEATURE_ARCHIVED, - FEATURE_REVIVED, + FEATURE_ENVIRONMENT_ENABLED, + CLIENT_METRICS, } from '../events/index.js'; -import type { - FeatureLifecycleView, - IFeatureLifecycleStore, - NewStage, -} from '../features/feature-lifecycle/feature-lifecycle-store-type.js'; -import type { IClientMetricsEnv } from '../features/metrics/client-metrics/client-metrics-store-v2-type.js'; -import { STAGE_ENTERED } from '../metric-events.js'; import type { Logger } from '../logger.js'; -import { - FeatureCompletedEvent, - FeatureUncompletedEvent, - type IAuditUser, - type IEnvironmentStore, - type IFeatureEnvironmentStore, - type IFlagResolver, - type IUnleashConfig, - type IEventStore, +import type { + IFlagResolver, + IUnleashConfig, + IEventStore, } from '../types/index.js'; -import type EventService from '../features/events/event-service.js'; -import type { FeatureLifecycleCompletedSchema } from '../openapi/index.js'; export class FeatureLifecycleService { private eventStore: IEventStore; - private featureLifecycleStore: IFeatureLifecycleStore; - - private environmentStore: IEnvironmentStore; - - private featureEnvironmentStore: IFeatureEnvironmentStore; - private flagResolver: IFlagResolver; private eventBus: EventEmitter; - private eventService: EventService; - private logger: Logger; constructor( { eventStore, - featureLifecycleStore, - environmentStore, - featureEnvironmentStore, }: { eventStore: IEventStore; - environmentStore: IEnvironmentStore; - featureLifecycleStore: IFeatureLifecycleStore; - featureEnvironmentStore: IFeatureEnvironmentStore; - }, - { - eventService, - }: { - eventService: EventService; }, { flagResolver, @@ -68,159 +32,26 @@ export class FeatureLifecycleService { }: Pick, ) { this.eventStore = eventStore; - this.featureLifecycleStore = featureLifecycleStore; - this.environmentStore = environmentStore; - this.featureEnvironmentStore = featureEnvironmentStore; this.flagResolver = flagResolver; this.eventBus = eventBus; - this.eventService = eventService; this.logger = getLogger( 'feature-lifecycle/feature-lifecycle-service.ts', ); } listen() { - this.featureLifecycleStore.backfill(); - this.eventStore.on(FEATURE_CREATED, async (event) => { - await this.featureInitialized(event.featureName); + this.eventStore.on(FEATURE_ENVIRONMENT_ENABLED, async (event) => { + if (this.flagResolver.isEnabled('paygTrialEvents')) { + // report to HS + } }); this.eventBus.on( - CLIENT_METRICS_ADDED, - async (events: IClientMetricsEnv[]) => { - if (events.length > 0) { - const groupedByEnvironment = groupBy(events, 'environment'); - - for (const [environment, metrics] of Object.entries( - groupedByEnvironment, - )) { - const features = metrics.map( - (metric) => metric.featureName, - ); - await this.featuresReceivedMetrics( - features, - environment, - ); - } + CLIENT_METRICS, // or CLIENT_METRICS_ADDED? 🤷 + async (event) => { + if (this.flagResolver.isEnabled('paygTrialEvents')) { + // todo: report to HS } }, ); - this.eventStore.on(FEATURE_ARCHIVED, async (event) => { - await this.featureArchived(event.featureName); - }); - this.eventStore.on(FEATURE_REVIVED, async (event) => { - await this.featureRevived(event.featureName); - }); - } - - async getFeatureLifecycle(feature: string): Promise { - return this.featureLifecycleStore.get(feature); - } - - private async featureInitialized(feature: string) { - const result = await this.featureLifecycleStore.insert([ - { feature, stage: 'initial' }, - ]); - this.recordStagesEntered(result); - } - - private async stageReceivedMetrics( - features: string[], - stage: 'live' | 'pre-live', - ) { - const newlyEnteredStages = await this.featureLifecycleStore.insert( - features.map((feature) => ({ feature, stage })), - ); - this.recordStagesEntered(newlyEnteredStages); - } - - private recordStagesEntered(newlyEnteredStages: NewStage[]) { - newlyEnteredStages.forEach(({ stage, feature }) => { - this.eventBus.emit(STAGE_ENTERED, { stage, feature }); - }); - } - - private async featuresReceivedMetrics( - features: string[], - environment: string, - ) { - try { - const env = await this.environmentStore.get(environment); - - if (!env) { - return; - } - await this.stageReceivedMetrics(features, 'pre-live'); - if (env.type === 'production') { - const featureEnv = - await this.featureEnvironmentStore.getAllByFeatures( - features, - env.name, - ); - const enabledFeatures = featureEnv - .filter((feature) => feature.enabled) - .map((feature) => feature.featureName); - await this.stageReceivedMetrics(enabledFeatures, 'live'); - } - } catch (e) { - this.logger.warn( - `Error handling ${features.length} metrics in ${environment}`, - e, - ); - } - } - - public async featureCompleted( - feature: string, - projectId: string, - status: FeatureLifecycleCompletedSchema, - auditUser: IAuditUser, - ) { - const result = await this.featureLifecycleStore.insert([ - { - feature, - stage: 'completed', - status: status.status, - statusValue: status.statusValue, - }, - ]); - this.recordStagesEntered(result); - await this.eventService.storeEvent( - new FeatureCompletedEvent({ - project: projectId, - featureName: feature, - data: { ...status, kept: status.status === 'kept' }, - auditUser, - }), - ); - } - - public async featureUncompleted( - feature: string, - projectId: string, - auditUser: IAuditUser, - ) { - await this.featureLifecycleStore.deleteStage({ - feature, - stage: 'completed', - }); - await this.eventService.storeEvent( - new FeatureUncompletedEvent({ - project: projectId, - featureName: feature, - auditUser, - }), - ); - } - - private async featureArchived(feature: string) { - const result = await this.featureLifecycleStore.insert([ - { feature, stage: 'archived' }, - ]); - this.recordStagesEntered(result); - } - - private async featureRevived(feature: string) { - await this.featureLifecycleStore.delete(feature); - await this.featureInitialized(feature); } }