@simonecoelhosfo/optimizely-mcp-server
Version:
Optimizely MCP Server for AI assistants with integrated CLI tools
375 lines • 14.7 kB
JavaScript
/**
* Field Resolution Strategy - JOIN Necessity Algorithm
*
* CRITICAL COMPONENT: Prevents JOIN explosion by implementing smart field resolution
*
* DESIGN PRINCIPLES:
* 1. Local First: Check primary entity fields before considering JOINs
* 2. Aggregation Aware: Different logic for COUNT/SUM vs detail queries
* 3. Cardinality Conscious: Prevent multiplication explosions
* 4. Necessity Driven: Require explicit need for JOINs, not just availability
*
* Created: July 5, 2025
* Purpose: Fix 700-1400x count inflation caused by unnecessary JOINs
*/
import { getLogger } from '../../logging/Logger.js';
const logger = getLogger();
/**
* JOIN Necessity Decision Tree Implementation
*/
export class FieldResolutionAlgorithm {
localFieldMaps = new Map();
dangerousJoins = new Set();
constructor() {
this.initializeLocalFieldMaps();
this.initializeDangerousJoins();
}
/**
* Main field resolution method using necessity-driven algorithm
*/
resolveFieldWithPriority(field, context) {
logger.info(`Resolving field '${field}' for entity '${context.primaryEntity}' (${context.queryType})`);
// STEP 1: Check if field exists locally (HIGHEST PRIORITY)
const localResult = this.checkLocalField(field, context);
if (localResult.confidence > 0.8) {
logger.info(`Field '${field}' resolved locally: ${localResult.fieldPath}`);
return localResult;
}
// STEP 2: Check if aggregation can be done without JOIN
if (context.isAggregation) {
const aggregationResult = this.checkAggregationWithoutJoin(field, context);
if (aggregationResult.confidence > 0.7) {
logger.info(`Aggregation for '${field}' resolved without JOIN: ${aggregationResult.fieldPath}`);
return aggregationResult;
}
}
// STEP 3: Evaluate JOIN necessity (CAREFUL EVALUATION)
const joinResult = this.evaluateJoinNecessity(field, context);
if (joinResult.confidence > 0.6 && this.isJoinSafe(joinResult.joinPath)) {
logger.info(`Field '${field}' requires JOIN: ${joinResult.fieldPath}`);
return joinResult;
}
// STEP 4: Fallback to simple field (SAFETY NET)
const fallbackResult = this.createFallbackResolution(field, context);
logger.warn(`🔄 Field '${field}' using fallback: ${fallbackResult.fieldPath}`);
return fallbackResult;
}
/**
* Step 1: Check if field exists in primary entity
*/
checkLocalField(field, context) {
const localFields = this.localFieldMaps.get(context.primaryEntity) || [];
// Direct field match
if (localFields.includes(field)) {
return {
source: 'local',
fieldPath: field,
joinRequired: false,
estimatedCost: 1,
confidence: 1.0,
reasoning: `Field '${field}' exists directly in ${context.primaryEntity} table`
};
}
// Common field variations (environment_key, environment, env)
const fieldVariations = this.generateFieldVariations(field);
for (const variation of fieldVariations) {
if (localFields.includes(variation)) {
return {
source: 'local',
fieldPath: variation,
joinRequired: false,
estimatedCost: 1,
confidence: 0.9,
reasoning: `Field variation '${variation}' found locally for '${field}'`
};
}
}
// Check junction table patterns (flag_environments for flags + environment)
const junctionResult = this.checkJunctionTableLocal(field, context);
if (junctionResult.confidence > 0.8) {
return junctionResult;
}
return {
source: 'local',
fieldPath: field,
joinRequired: false,
estimatedCost: 1,
confidence: 0.1,
reasoning: `Field '${field}' not found locally in ${context.primaryEntity}`
};
}
/**
* Step 2: Check if aggregation can be done without JOIN
*/
checkAggregationWithoutJoin(field, context) {
// Special handling for environment fields in flags context
if (context.primaryEntity === 'flags' && field === 'environment') {
return {
source: 'local',
fieldPath: 'flag_environments.environment_key',
joinRequired: false, // Use flag_environments directly, no JOIN to environments table
estimatedCost: 2,
confidence: 0.95,
reasoning: 'Environment field for flags can be aggregated from flag_environments without JOIN'
};
}
// Special handling for project fields
if (field === 'project' || field === 'project_id') {
return {
source: 'local',
fieldPath: 'project_id',
joinRequired: false,
estimatedCost: 1,
confidence: 0.9,
reasoning: 'Project field available locally in most entities'
};
}
// Check for common aggregation patterns that don't need JOINs
const aggregationPatterns = {
'status': 'status',
'enabled': 'enabled',
'archived': 'archived',
'created': 'created',
'last_modified': 'last_modified'
};
if (field in aggregationPatterns) {
return {
source: 'local',
fieldPath: aggregationPatterns[field],
joinRequired: false,
estimatedCost: 1,
confidence: 0.8,
reasoning: `Common aggregation field '${field}' typically available locally`
};
}
return {
source: 'local',
fieldPath: field,
joinRequired: false,
estimatedCost: 1,
confidence: 0.2,
reasoning: `No aggregation-specific resolution found for '${field}'`
};
}
/**
* Step 3: Evaluate if JOIN is truly necessary
*/
evaluateJoinNecessity(field, context) {
// DANGER: Avoid these JOINs that cause explosion
if (this.dangerousJoins.has(`${context.primaryEntity}_${field}`)) {
return {
source: 'fallback',
fieldPath: field,
joinRequired: false,
estimatedCost: 1,
confidence: 0.1,
reasoning: `JOIN for '${field}' marked as dangerous (causes explosion)`
};
}
// Evaluate potential JOIN paths
const potentialJoins = this.getPotentialJoins(context.primaryEntity, field);
for (const join of potentialJoins) {
// Skip JOINs that would cause multiplication for aggregations
if (context.isAggregation && join.estimatedMultiplier > 2) {
logger.warn(`Skipping JOIN to ${join.toTable} - would cause ${join.estimatedMultiplier}x multiplication in aggregation`);
continue;
}
// Skip JOINs to large lookup tables for COUNT queries
if (context.queryType === 'count' && this.isLargeLookupTable(join.toTable)) {
logger.warn(`Skipping JOIN to large lookup table ${join.toTable} for COUNT query`);
continue;
}
return {
source: 'related',
fieldPath: `${join.toTable}.${field}`,
joinRequired: true,
joinPath: join,
estimatedCost: join.estimatedMultiplier * 10,
confidence: 0.6,
reasoning: `Field '${field}' requires JOIN to ${join.toTable} (${join.estimatedMultiplier}x multiplier)`
};
}
return {
source: 'fallback',
fieldPath: field,
joinRequired: false,
estimatedCost: 1,
confidence: 0.1,
reasoning: `No safe JOIN path found for '${field}'`
};
}
/**
* Step 4: Create fallback resolution
*/
createFallbackResolution(field, context) {
return {
source: 'fallback',
fieldPath: field,
joinRequired: false,
estimatedCost: 1,
confidence: 0.5,
reasoning: `Using fallback resolution for '${field}' - field used as-is`
};
}
/**
* Check if a JOIN is safe (won't cause explosion)
*/
isJoinSafe(joinPath) {
if (!joinPath)
return false;
// Reject JOINs with high multiplication factors
if (joinPath.estimatedMultiplier > 5) {
logger.warn(`JOIN rejected - high multiplication factor: ${joinPath.estimatedMultiplier}x`);
return false;
}
// Reject JOINs to known dangerous tables
const dangerousTables = ['environments', 'projects', 'audiences'];
if (dangerousTables.includes(joinPath.toTable)) {
logger.warn(`JOIN rejected - dangerous table: ${joinPath.toTable}`);
return false;
}
return true;
}
/**
* Generate field variations for fuzzy matching
*/
generateFieldVariations(field) {
const variations = [field];
// Add common variations
if (field === 'environment') {
variations.push('environment_key', 'env', 'env_key');
}
if (field === 'project') {
variations.push('project_id', 'project_key');
}
if (field === 'audience') {
variations.push('audience_id', 'audience_key');
}
// Add underscore variations
if (!field.includes('_')) {
variations.push(`${field}_id`, `${field}_key`, `${field}_name`);
}
return variations;
}
/**
* Check junction tables for local field resolution
*/
checkJunctionTableLocal(field, context) {
// flags + environment → flag_environments table
if (context.primaryEntity === 'flags' && field === 'environment') {
return {
source: 'local',
fieldPath: 'flag_environments.environment_key',
joinRequired: false,
estimatedCost: 2,
confidence: 0.95,
reasoning: 'Environment data available in flag_environments junction table'
};
}
// experiments + page → experiment_pages table
if (context.primaryEntity === 'experiments' && field === 'page') {
return {
source: 'local',
fieldPath: 'experiment_pages.page_id',
joinRequired: false,
estimatedCost: 2,
confidence: 0.9,
reasoning: 'Page data available in experiment_pages junction table'
};
}
return {
source: 'local',
fieldPath: field,
joinRequired: false,
estimatedCost: 1,
confidence: 0.1,
reasoning: 'No junction table pattern found'
};
}
/**
* Get potential JOIN paths for a field
*/
getPotentialJoins(entity, field) {
const joins = [];
// Only return JOINs if absolutely necessary
// Most fields should be resolved locally
return joins; // Return empty array - prefer local resolution
}
/**
* Check if table is a large lookup table that causes explosions
*/
isLargeLookupTable(tableName) {
const largeTables = ['environments', 'projects', 'audiences', 'attributes'];
return largeTables.includes(tableName);
}
/**
* Initialize local field mappings for each entity
*/
initializeLocalFieldMaps() {
this.localFieldMaps = new Map([
['flags', [
'id', 'key', 'name', 'description', 'created', 'last_modified',
'project_id', 'archived', 'enabled'
]],
['flag_environments', [
'flag_key', 'environment_key', 'enabled', 'project_id'
]],
['experiments', [
'id', 'name', 'description', 'status', 'created', 'last_modified',
'project_id', 'campaign_id', 'archived'
]],
['audiences', [
'id', 'name', 'description', 'conditions', 'created', 'last_modified',
'project_id', 'archived'
]],
['features', [
'id', 'key', 'name', 'description', 'created', 'last_modified',
'project_id', 'archived'
]],
['pages', [
'id', 'name', 'key', 'conditions', 'activation_type', 'created',
'project_id', 'archived'
]]
]);
logger.info(`Initialized local field mappings for ${this.localFieldMaps.size} entities`);
}
/**
* Initialize dangerous JOINs that cause explosions
*/
initializeDangerousJoins() {
this.dangerousJoins = new Set([
'flags_environment', // flags to environments table
'flags_project', // flags to projects table
'experiments_audience', // experiments to audiences table
'flags_audience', // flags to audiences table
'experiments_project' // experiments to projects table
]);
logger.info(`Initialized ${this.dangerousJoins.size} dangerous JOIN patterns`);
}
}
/**
* Factory function to create field resolution strategy based on query context
*/
export function createFieldResolutionStrategy(context) {
// Aggregation queries need stricter JOIN prevention
if (context.isAggregation || context.queryType === 'count') {
return {
checkLocal: true,
requireExplicit: true,
aggregationAware: true,
cardinalityLimit: 2, // Max 2x multiplication for aggregations
fallbackToSimple: true,
timeoutLimit: 5000 // 5 second timeout
};
}
// Detail queries can be more permissive
return {
checkLocal: true,
requireExplicit: false,
aggregationAware: false,
cardinalityLimit: 10, // Allow higher multiplication for detail
fallbackToSimple: false,
timeoutLimit: 10000 // 10 second timeout
};
}
//# sourceMappingURL=FieldResolutionStrategy.js.map