import{logger as c}from"../../tools/notifiers/logger.js";import{SqldNotRunningError as y}from"./sqld-not-running-error.js";import{retryAsyncOperation as f}from"./utils/retry-async-operation.js";import{DatabasePathGenerator as h}from"./database-path-generator.js";import{DatabaseClient as w}from"./client.js";const m="_redocly_db_preconnect_cache_";class i{static get#t(){const t=globalThis;if(!t[m]){const n={connections:new Map,pendingConnections:new Map,failedConnections:new Set};t[m]=n}return t[m]}static get#i(){return i.#t.connections}static get#e(){return i.#t.failedConnections}static get#n(){return i.#t.pendingConnections}static async getLocalConnection(t){return i.#r(t,async()=>i.#a(t))}static async getRemoteConnection(t){return i.#r(t,async()=>i.#d(t))}static async#r(t,n){const e=i.#o(t),r=i.#i.get(e);if(r)if(r.client.dbClient.$client.closed)c.warn("Cached database client is closed. Reinitializing connection..."),i.#i.delete(e);else return r;return i.#l({key:e,initializer:n})}static#o=t=>{const n="syncUrl"in t&&typeof t.syncUrl=="string"?`|${t.syncUrl}`:"",e=t.additionalFolder??"";return`${t.baseDbDir}|${e}|${t.databaseName}${n}`};static async#l({key:t,initializer:n}){let e=i.#n.get(t);e||(i.#e.has(t)&&c.warn("Error connecting to the database, retrying..."),e=i.#s(t,n),i.#n.set(t,e));try{return await e}catch(r){return c.error("Error connecting to the database",r),i.#e.add(t),null}finally{i.#n.delete(t)}}static async#s(t,n){const e=await n();return i.#i.set(t,e),i.#e.delete(t),e}static async#a({removeExisting:t,baseDbDir:n,runWithPragmaWalWriteOptimization:e,databaseName:r,additionalFolder:a,migrationsFolder:d}){c.info("Initializing local database client...");const l=c.startTiming(),s=await i.#c({removeExisting:t,baseDbDir:n,databaseName:r,additionalFolder:a,migrationsFolder:d,runWithPragmaWalWriteOptimization:e});return c.infoTime(l,"Local database client initialized"),s}static async#d({removeExisting:t,baseDbDir:n,syncUrl:e,authToken:r,databaseName:a,additionalFolder:d,migrationsFolder:l}){c.info("Initializing remote database client...");const s=c.startTiming();return await f(async()=>{try{const o=await i.#c({removeExisting:t,baseDbDir:n,databaseName:a,additionalFolder:d,migrationsFolder:l,syncUrl:e,authToken:r});return c.infoTime(s,"Remote database client initialized"),o}catch(o){throw y.isSqldNotRunningError(o)?new y("SQLD server is not running yet, wait for production deployment",{cause:o}):o}},{maxRetries:3,retryStrategy:"exponential",delay:1e3,logger:c,messages:{retry:"Retrying remote database client initialization",maxRetriesReached:"Max retries reached, remote database client initialization failed"}})}static async#c({removeExisting:t,baseDbDir:n,databaseName:e,additionalFolder:r,migrationsFolder:a,runWithPragmaWalWriteOptimization:d,syncUrl:l,authToken:s}){const{databasePath:o}=await h.prepareDatabasePath({baseDir:n,databaseName:e,additionalFolder:r,removeExisting:t}),p=l&&s?{url:`file:${o}`,syncUrl:l,authToken:s}:{url:`file:${o}`},u=await w.init(p,{runWithPragmaWalWriteOptimization:d});return await u.migrate(n,a),{client:u,path:o}}}export{i as DatabaseConnectionsManager};
