()
| 81 | * Hashes rule file content + router rules + code version. |
| 82 | */ |
| 83 | export async function getOrCreateConfigVersion(): Promise<ConfigVersion> { |
| 84 | const routerHash = computeRouterRulesHash(); |
| 85 | const rulesHash = computeRulesContentHash(); |
| 86 | const configHash = computeConfigHash(rulesHash, routerHash); |
| 87 | |
| 88 | // Check cache first |
| 89 | const now = Date.now(); |
| 90 | if (cachedVersion && cachedVersion.config_hash === configHash && now < cacheExpiry) { |
| 91 | return cachedVersion; |
| 92 | } |
| 93 | |
| 94 | try { |
| 95 | // Try to find existing version with this hash |
| 96 | const existing = await query<ConfigVersion>( |
| 97 | `SELECT * FROM addie_config_versions WHERE config_hash = $1`, |
| 98 | [configHash] |
| 99 | ); |
| 100 | |
| 101 | if (existing.rows.length > 0) { |
| 102 | cachedVersion = existing.rows[0]; |
| 103 | cacheExpiry = now + CACHE_TTL_MS; |
| 104 | return cachedVersion; |
| 105 | } |
| 106 | |
| 107 | // Create new version |
| 108 | const result = await query<ConfigVersion>( |
| 109 | `INSERT INTO addie_config_versions ( |
| 110 | config_hash, active_rule_ids, rules_snapshot, router_rules_hash, code_version |
| 111 | ) VALUES ($1, $2, $3, $4, $5) |
| 112 | RETURNING *`, |
| 113 | [ |
| 114 | configHash, |
| 115 | [], // Rule IDs no longer used — rules are in files |
| 116 | JSON.stringify({ rules_content_hash: rulesHash }), |
| 117 | routerHash, |
| 118 | CODE_VERSION, |
| 119 | ] |
| 120 | ); |
| 121 | |
| 122 | cachedVersion = result.rows[0]; |
| 123 | cacheExpiry = now + CACHE_TTL_MS; |
| 124 | |
| 125 | logger.info({ |
| 126 | version_id: cachedVersion.version_id, |
| 127 | config_hash: configHash, |
| 128 | rules_hash: rulesHash, |
| 129 | code_version: CODE_VERSION, |
| 130 | }, 'Config: Created new configuration version'); |
| 131 | |
| 132 | return cachedVersion; |
| 133 | } catch (error) { |
| 134 | // If DB is temporarily unreachable but we have a cached version, return stale |
| 135 | // cache instead of crashing callers. Config rarely changes so stale is fine. |
| 136 | if (cachedVersion) { |
| 137 | logger.warn({ error }, 'Config: DB unreachable, returning stale cached version'); |
| 138 | return cachedVersion; |
| 139 | } |
| 140 | logger.error({ error }, 'Config: Failed to get/create config version'); |
no test coverage detected