import{and as w,eq as i,isNotNull as A,lt as m,sql as T}from"drizzle-orm";import{logger as p}from"../../../tools/notifiers/logger.js";import{cacheTable as a}from"../../../providers/database/databases/sqlite-db/schemas/cache-table.js";import{BATCH_TRANSIENT_RETRY as d,describeTransientError as y,withTransientErrorRetry as E}from"../../../providers/database/transient-sqld-error.js";const c="catalog-publisher-locks",I="catalog-entities::publisher",f=`${I}::remote-publish-lock`,O=1800*1e3,h=Math.floor(O/1e3),_=60*1e3,g=300*1e3,C=1e3;class s{static async getInternalCacheValue({remoteConnection:t,key:e}){return(await t.client.client.select({value:a.value}).from(a).where(w(i(a.key,e),i(a.namespace,c))).get())?.value??null}static async upsertInternalCacheValue({remoteConnection:t,key:e,value:r,ttl:n=null}){const o=new Date().toISOString();await t.client.client.insert(a).values({key:e,namespace:c,value:r,ttl:n,createdAt:o,updatedAt:o}).onConflictDoUpdate({target:[a.key],set:{namespace:c,value:r,ttl:n,updatedAt:o}}).run()}static async runUnderRemotePublishLock({runId:t,remoteConnection:e,run:r}){const n=JSON.stringify({ownerRunId:t});await s.#r({runId:t,lockValue:n,remoteConnection:e});const o=s.#a({runId:t,lockValue:n,remoteConnection:e}),u=await s.#n(r);clearInterval(o);const l=await s.#s({lockValue:n,remoteConnection:e});if(!u.ok)throw l&&p.warn(`Failed to release remote publish lock after publish error for runId=${t}: ${s.#t(l)}`),s.#e(u.error,`Remote publish failed for runId=${t}: ${s.#t(u.error)}`);if(l)throw s.#e(l,`Failed to release remote publish lock for runId=${t}: ${s.#t(l)}`);return u.result}static async#r({runId:t,lockValue:e,remoteConnection:r}){if(!await s.#i({lockValue:e,remoteConnection:r,timeoutMs:g}))throw new Error(`Timed out waiting for remote publish lock. runId=${t}`)}static#a({runId:t,lockValue:e,remoteConnection:r}){return setInterval(()=>{s.#l({remoteConnection:r,lockValue:e}).catch(n=>{p.warn(`Failed to refresh remote publish lock for runId=${t}: ${s.#t(n)}`)})},_)}static async#n(t){try{return{ok:!0,result:await t()}}catch(e){return{ok:!1,error:e}}}static async#s({lockValue:t,remoteConnection:e}){try{return await s.#c({remoteConnection:e,lockValue:t}),null}catch(r){return r}}static async#i({lockValue:t,remoteConnection:e,timeoutMs:r}){const n=Date.now();for(;Date.now()-n<r;){if(await s.#o({remoteConnection:e,lockValue:t}))return!0;await s.#w(C)}return p.warn("Lock wait timeout. Wait for the other build to finish publishing entities."),!1}static async#o({remoteConnection:t,lockValue:e}){const r=t.client.client,n=new Date().toISOString();await E(()=>r.delete(a).where(w(i(a.key,f),i(a.namespace,c),A(a.ttl),m(T`datetime(${a.createdAt}, '+' || ${a.ttl} || ' seconds')`,T`datetime('now')`))).run(),d);try{return await E(()=>r.insert(a).values({key:f,namespace:c,value:e,ttl:h,createdAt:n,updatedAt:n}).run(),d),!0}catch(o){if(s.#u(o))return!1;throw o}}static async#c({remoteConnection:t,lockValue:e}){await E(()=>t.client.client.delete(a).where(w(i(a.key,f),i(a.namespace,c),i(a.value,e))).run(),d)}static async#l({remoteConnection:t,lockValue:e}){const r=new Date().toISOString();await E(()=>t.client.client.update(a).set({ttl:h,createdAt:r,updatedAt:r}).where(w(i(a.key,f),i(a.namespace,c),i(a.value,e))).run(),d)}static#u(t){const e=new Set;for(let r=t;r instanceof Error&&!e.has(r);r=r.cause){e.add(r);const n=r.message.toLowerCase();if(n.includes("unique constraint failed")||n.includes("sqlite_constraint_unique"))return!0}return!1}static#w(t){return new Promise(e=>setTimeout(e,t))}static#e(t,e){return t instanceof Error?t:new Error(e)}static#t(t){return t instanceof Error?y(t):typeof t=="string"?t:JSON.stringify(t)}}export{c as INTERNAL_CATALOG_PUBLISH_CACHE_NAMESPACE,I as INTERNAL_CATALOG_PUBLISH_KEY_PREFIX,s as RemotePublishLockService};
