diff --git a/src/lib/db/feature-strategy-store.ts b/src/lib/db/feature-strategy-store.ts index 297d4bd5d8..c7f76bc4b5 100644 --- a/src/lib/db/feature-strategy-store.ts +++ b/src/lib/db/feature-strategy-store.ts @@ -507,6 +507,11 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore { 'feature_environments.feature_name', 'features.name', ) + .leftJoin( + 'feature_environments_metrics', + 'feature_environments_metrics.feature_name', + 'features.name', + ) .leftJoin( 'environments', 'feature_environments.environment', @@ -525,7 +530,7 @@ class FeatureStrategiesStore implements IFeatureStrategiesStore { 'feature_environments.enabled as enabled', 'feature_environments.environment as environment', 'feature_environments.variants as variants', - 'feature_environments.last_seen_at as env_last_seen_at', + 'feature_environments_metrics.last_seen_at as env_last_seen_at', 'environments.type as environment_type', 'environments.sort_order as environment_sort_order', 'ft.tag_value as tag_value', diff --git a/src/lib/db/feature-toggle-store.ts b/src/lib/db/feature-toggle-store.ts index b8dc6d3af0..5fd2522157 100644 --- a/src/lib/db/feature-toggle-store.ts +++ b/src/lib/db/feature-toggle-store.ts @@ -42,6 +42,7 @@ interface VariantDTO { } const TABLE = 'features'; +const FEATURE_ENVIRONMENTS_METRICS_TABLE = 'feature_environments_metrics'; const FEATURE_ENVIRONMENTS_TABLE = 'feature_environments'; export default class FeatureToggleStore implements IFeatureToggleStore { @@ -175,12 +176,12 @@ export default class FeatureToggleStore implements IFeatureToggleStore { try { for (const env of Object.keys(environmentArrays)) { const toggleNames = environmentArrays[env].sort(); - await this.db(FEATURE_ENVIRONMENTS_TABLE) + await this.db(FEATURE_ENVIRONMENTS_METRICS_TABLE) .update({ last_seen_at: now }) .where('environment', env) .whereIn( 'feature_name', - this.db(FEATURE_ENVIRONMENTS_TABLE) + this.db(FEATURE_ENVIRONMENTS_METRICS_TABLE) .select('feature_name') .whereIn('feature_name', toggleNames) .forUpdate() diff --git a/src/migrations/20230919103955-create-feature-environments-metrics-table.js b/src/migrations/20230919103955-create-feature-environments-metrics-table.js new file mode 100644 index 0000000000..06d6ee73eb --- /dev/null +++ b/src/migrations/20230919103955-create-feature-environments-metrics-table.js @@ -0,0 +1,110 @@ +'use strict'; + +exports.up = function (db, cb) { + db.runSql( + ` + CREATE TABLE IF NOT EXISTS feature_environments_metrics( + environment varchar(100) not null + references environments(name) + on delete cascade, + feature_name varchar(255) not null + references features(name) + on delete cascade, + last_seen_at timestamp with time zone, + primary key (environment, feature_name) + ); + + INSERT INTO feature_environments_metrics (environment, feature_name, last_seen_at) + SELECT + feature_environments.environment, + feature_environments.feature_name, + feature_environments.last_seen_at + FROM feature_environments + ON CONFLICT (environment, feature_name) + DO NOTHING; + + DROP VIEW features_view; + + CREATE VIEW features_view AS + SELECT features.name as name, + features.description as description, + features.type as type, + features.project as project, + features.stale as stale, + features.impression_data as impression_data, + features.created_at as created_at, + features.archived_at as archived_at, + features.last_seen_at as last_seen_at, + feature_environments_metrics.last_seen_at as env_last_seen_at, + feature_environments.enabled as enabled, + feature_environments.environment as environment, + feature_environments.variants as variants, + environments.name as environment_name, + environments.type as environment_type, + environments.sort_order as environment_sort_order, + feature_strategies.id as strategy_id, + feature_strategies.strategy_name as strategy_name, + feature_strategies.parameters as parameters, + feature_strategies.constraints as constraints, + feature_strategies.sort_order as sort_order, + fss.segment_id as segments, + feature_strategies.title as strategy_title, + feature_strategies.disabled as strategy_disabled, + feature_strategies.variants as strategy_variants + FROM features + LEFT JOIN feature_environments ON feature_environments.feature_name = features.name + LEFT JOIN feature_environments_metrics ON feature_environments_metrics.feature_name = features.name + LEFT JOIN feature_strategies ON feature_strategies.feature_name = feature_environments.feature_name + and feature_strategies.environment = feature_environments.environment + LEFT JOIN environments ON feature_environments.environment = environments.name + LEFT JOIN feature_strategy_segment as fss ON fss.feature_strategy_id = feature_strategies.id; + `, + cb(), + ); +}; + +exports.down = function (db, cb) { + db.runSql( + ` + DROP VIEW features_view; + + CREATE VIEW features_view AS + SELECT + features.name as name, + features.description as description, + features.type as type, + features.project as project, + features.stale as stale, + features.impression_data as impression_data, + features.created_at as created_at, + features.archived_at as archived_at, + features.last_seen_at as last_seen_at, + feature_environments.last_seen_at as env_last_seen_at, + feature_environments.enabled as enabled, + feature_environments.environment as environment, + feature_environments.variants as variants, + environments.name as environment_name, + environments.type as environment_type, + environments.sort_order as environment_sort_order, + feature_strategies.id as strategy_id, + feature_strategies.strategy_name as strategy_name, + feature_strategies.parameters as parameters, + feature_strategies.constraints as constraints, + feature_strategies.sort_order as sort_order, + fss.segment_id as segments, + feature_strategies.title as strategy_title, + feature_strategies.disabled as strategy_disabled, + feature_strategies.variants as strategy_variants + FROM + features + LEFT JOIN feature_environments ON feature_environments.feature_name = features.name + LEFT JOIN feature_strategies ON feature_strategies.feature_name = feature_environments.feature_name + and feature_strategies.environment = feature_environments.environment + LEFT JOIN environments ON feature_environments.environment = environments.name + LEFT JOIN feature_strategy_segment as fss ON fss.feature_strategy_id = feature_strategies.id; + + DROP TABLE IF EXISTS feature_environments_metrics + `, + cb, + ); +};