UNPKG

unleash-server

Version:

Unleash is an enterprise ready feature toggles service. It provides different strategies for handling feature toggles.

103 lines 4.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const date_fns_1 = require("date-fns"); class ProjectHealthService { constructor({ projectStore, featureTypeStore, featureToggleStore, }, { getLogger }, featureToggleService, favoritesService) { this.logger = getLogger('services/project-health-service.ts'); this.projectStore = projectStore; this.featureTypeStore = featureTypeStore; this.featureToggleStore = featureToggleStore; this.featureTypes = new Map(); this.healthRatingTimer = setInterval(() => this.setHealthRating(), (0, date_fns_1.hoursToMilliseconds)(1)).unref(); this.featureToggleService = featureToggleService; this.favoritesService = favoritesService; } // TODO: duplicate from project-service. async getProjectOverview(projectId, archived = false, userId) { const project = await this.projectStore.get(projectId); const environments = await this.projectStore.getEnvironmentsForProject(projectId); const features = await this.featureToggleService.getFeatureOverview({ projectId, archived, userId, }); const members = await this.projectStore.getMembersCountByProject(projectId); const favorite = await this.favoritesService.isFavoriteProject({ project: projectId, userId, }); return { name: project.name, description: project.description, health: project.health, favorite: favorite, updatedAt: project.updatedAt, environments, features, members, version: 1, }; } async getProjectHealthReport(projectId) { const overview = await this.getProjectOverview(projectId, false, undefined); return { ...overview, potentiallyStaleCount: await this.potentiallyStaleCount(overview.features), activeCount: this.activeCount(overview.features), staleCount: this.staleCount(overview.features), }; } async potentiallyStaleCount(features) { const today = new Date().valueOf(); if (this.featureTypes.size === 0) { const types = await this.featureTypeStore.getAll(); types.forEach((type) => { this.featureTypes.set(type.name.toLowerCase(), type.lifetimeDays); }); } return features.filter((feature) => { const diff = today - feature.createdAt.valueOf(); const featureTypeExpectedLifetime = this.featureTypes.get(feature.type); return (!feature.stale && diff >= featureTypeExpectedLifetime * (0, date_fns_1.hoursToMilliseconds)(24)); }).length; } activeCount(features) { return features.filter((f) => !f.stale).length; } staleCount(features) { return features.filter((f) => f.stale).length; } async calculateHealthRating(project) { const toggles = await this.featureToggleStore.getAll({ project: project.id, archived: false, }); const activeToggles = toggles.filter((feature) => !feature.stale); const staleToggles = toggles.length - activeToggles.length; const potentiallyStaleToggles = await this.potentiallyStaleCount(activeToggles); return this.getHealthRating(toggles.length, staleToggles, potentiallyStaleToggles); } getHealthRating(toggleCount, staleToggleCount, potentiallyStaleCount) { const startPercentage = 100; const stalePercentage = (staleToggleCount / toggleCount) * 100 || 0; const potentiallyStalePercentage = (potentiallyStaleCount / toggleCount) * 100 || 0; const rating = Math.round(startPercentage - stalePercentage - potentiallyStalePercentage); return rating; } async setHealthRating() { const projects = await this.projectStore.getAll(); await Promise.all(projects.map(async (project) => { const newHealth = await this.calculateHealthRating(project); await this.projectStore.updateHealth({ id: project.id, health: newHealth, }); })); } destroy() { clearInterval(this.healthRatingTimer); } } exports.default = ProjectHealthService; //# sourceMappingURL=project-health-service.js.map