@lunora/runtime 1.0.0-alpha.133 → 1.0.0-alpha.134
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts
CHANGED
|
@@ -1261,7 +1261,18 @@ interface ShardCdcOutcome {
|
|
|
1261
1261
|
* resumes from the same pair rather than dropping the timeline half.
|
|
1262
1262
|
*/
|
|
1263
1263
|
epoch?: string;
|
|
1264
|
+
/**
|
|
1265
|
+
* Why this shard served no page. `code` is the shard's own verdict — see
|
|
1266
|
+
* {@link ShardError.code} — and it is the half a consumer has to branch on:
|
|
1267
|
+
* `CDC_TIMELINE_FORKED` means re-seed from a snapshot on the new timeline,
|
|
1268
|
+
* `CDC_LOG_TRIMMED` / `CDC_PAYLOAD_COMPACTED` mean re-seed from a snapshot,
|
|
1269
|
+
* and a transport code (`SHARD_TIMEOUT`, `SHARD_HTTP_ERROR`, `INTERNAL`)
|
|
1270
|
+
* means retry the same cursor. Reported through `message` alone they are one
|
|
1271
|
+
* indistinguishable failure, and the epoch guard's whole value is the
|
|
1272
|
+
* verdict it reaches the caller with.
|
|
1273
|
+
*/
|
|
1264
1274
|
error?: {
|
|
1275
|
+
code: string;
|
|
1265
1276
|
message: string;
|
|
1266
1277
|
timedOut: boolean;
|
|
1267
1278
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1261,7 +1261,18 @@ interface ShardCdcOutcome {
|
|
|
1261
1261
|
* resumes from the same pair rather than dropping the timeline half.
|
|
1262
1262
|
*/
|
|
1263
1263
|
epoch?: string;
|
|
1264
|
+
/**
|
|
1265
|
+
* Why this shard served no page. `code` is the shard's own verdict — see
|
|
1266
|
+
* {@link ShardError.code} — and it is the half a consumer has to branch on:
|
|
1267
|
+
* `CDC_TIMELINE_FORKED` means re-seed from a snapshot on the new timeline,
|
|
1268
|
+
* `CDC_LOG_TRIMMED` / `CDC_PAYLOAD_COMPACTED` mean re-seed from a snapshot,
|
|
1269
|
+
* and a transport code (`SHARD_TIMEOUT`, `SHARD_HTTP_ERROR`, `INTERNAL`)
|
|
1270
|
+
* means retry the same cursor. Reported through `message` alone they are one
|
|
1271
|
+
* indistinguishable failure, and the epoch guard's whole value is the
|
|
1272
|
+
* verdict it reaches the caller with.
|
|
1273
|
+
*/
|
|
1264
1274
|
error?: {
|
|
1275
|
+
code: string;
|
|
1265
1276
|
message: string;
|
|
1266
1277
|
timedOut: boolean;
|
|
1267
1278
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{BACKUP_KEY_PREFIX as t,backupManifestKey as a,backupObjectKey as s,backupObjectKeyOfManifest as i,isBackupManifestEntry as n,isBackupManifestKey as p,normalizeBackupPrefix as c}from"./packem_shared/BACKUP_KEY_PREFIX-BOtSu-_3.mjs";import{toAirbyteMessages as f,toFivetranResponse as E}from"./packem_shared/toAirbyteMessages-2d_iJXPf.mjs";import{composeWorker as x,createLunoraHandler as S,createWorker as l,defineRpcEnvelope as u,resolveLunoraOptions as _,withFrameworkWorker as d}from"./packem_shared/composeWorker-BcXyMOMk.mjs";import{createCrossShardRelationCapabilities as y}from"./packem_shared/createCrossShardRelationCapabilities-D_S3beMO.mjs";import{DEFAULT_REGISTRY_CACHE_TTL_MS as O,SHARD_REGISTRY_DO_NAME as b,createDynamicShardRegistry as A}from"./packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-D5O7elXI.mjs";import{LunoraError as T,toErrorResponse as h}from"./packem_shared/LunoraError-DksAgIpa.mjs";import{c as P,a as g,d as v,r as I,b as D,s as M,w as F}from"./packem_shared/export-tap-CAyZ2TWC.mjs";import{HEALTH_PATH as G,HEALTH_READY_PATH as K,buildHealthRoutes as U,d1Probe as B,durableObjectProbe as Y,presenceProbe as w}from"./packem_shared/HEALTH_PATH-D0i8LhwT.mjs";import{LOG_ARCHIVE_PATH as X,resolveLogArchiveFromEnv as j}from"./packem_shared/LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs";import{memoizeIdentity as W,memoizeIdentityPerRequest as q}from"./packem_shared/memoizeIdentity-DnOj3QRi.mjs";import{e as J,a as Z}from"./packem_shared/observability-B1hLjwgx.mjs";import{analyticsEngineSink as ee,combineSinks as re,consoleSink as oe,otlpSink as te,pipelineLogSink as ae,sentrySink as se,webhookSink as ie}from"./packem_shared/analyticsEngineSink-JUcPmzoo.mjs";import{D as pe,c as ce}from"./packem_shared/pipeline-log-reader-C-nuWG_e.mjs";import{createQueryCoordinator as fe,createStaticShardRegistry as Ee}from"./packem_shared/createQueryCoordinator-
|
|
1
|
+
import{BACKUP_KEY_PREFIX as t,backupManifestKey as a,backupObjectKey as s,backupObjectKeyOfManifest as i,isBackupManifestEntry as n,isBackupManifestKey as p,normalizeBackupPrefix as c}from"./packem_shared/BACKUP_KEY_PREFIX-BOtSu-_3.mjs";import{toAirbyteMessages as f,toFivetranResponse as E}from"./packem_shared/toAirbyteMessages-2d_iJXPf.mjs";import{composeWorker as x,createLunoraHandler as S,createWorker as l,defineRpcEnvelope as u,resolveLunoraOptions as _,withFrameworkWorker as d}from"./packem_shared/composeWorker-BcXyMOMk.mjs";import{createCrossShardRelationCapabilities as y}from"./packem_shared/createCrossShardRelationCapabilities-D_S3beMO.mjs";import{DEFAULT_REGISTRY_CACHE_TTL_MS as O,SHARD_REGISTRY_DO_NAME as b,createDynamicShardRegistry as A}from"./packem_shared/DEFAULT_REGISTRY_CACHE_TTL_MS-D5O7elXI.mjs";import{LunoraError as T,toErrorResponse as h}from"./packem_shared/LunoraError-DksAgIpa.mjs";import{c as P,a as g,d as v,r as I,b as D,s as M,w as F}from"./packem_shared/export-tap-CAyZ2TWC.mjs";import{HEALTH_PATH as G,HEALTH_READY_PATH as K,buildHealthRoutes as U,d1Probe as B,durableObjectProbe as Y,presenceProbe as w}from"./packem_shared/HEALTH_PATH-D0i8LhwT.mjs";import{LOG_ARCHIVE_PATH as X,resolveLogArchiveFromEnv as j}from"./packem_shared/LOG_ARCHIVE_PATH-Hmjpz_Ko.mjs";import{memoizeIdentity as W,memoizeIdentityPerRequest as q}from"./packem_shared/memoizeIdentity-DnOj3QRi.mjs";import{e as J,a as Z}from"./packem_shared/observability-B1hLjwgx.mjs";import{analyticsEngineSink as ee,combineSinks as re,consoleSink as oe,otlpSink as te,pipelineLogSink as ae,sentrySink as se,webhookSink as ie}from"./packem_shared/analyticsEngineSink-JUcPmzoo.mjs";import{D as pe,c as ce}from"./packem_shared/pipeline-log-reader-C-nuWG_e.mjs";import{createQueryCoordinator as fe,createStaticShardRegistry as Ee}from"./packem_shared/createQueryCoordinator-D3__w6LU.mjs";import{applyJurisdiction as xe,resolveShard as Se}from"./packem_shared/applyJurisdiction-C0ddU7Tg.mjs";import{a as ue,r as _e,b as de}from"./packem_shared/rest-cache-D1BlbZb1.mjs";import{a as ye,b as Ce,c as Oe,r as be}from"./packem_shared/rest-routes-CpbO5QEx.mjs";import{decorateResponse as Le,enforceOrigin as Te,handleCorsPreflight as he,resolveSecurity as He}from"./packem_shared/decorateResponse-Y2sCM0w1.mjs";import{createShardClient as ge}from"./packem_shared/createShardClient-I984JFkv.mjs";import{STORAGE_UPLOAD_MAX_BODY_BYTES as Ie}from"./packem_shared/STORAGE_UPLOAD_MAX_BODY_BYTES-KGQR1LvR.mjs";import{LOG_ARCHIVE_NOT_CONFIGURED as Me}from"./packem_shared/LOG_ARCHIVE_NOT_CONFIGURED-CDpi4yFD.mjs";import{NOOP_EXECUTION_CONTEXT as Ne}from"./packem_shared/NOOP_EXECUTION_CONTEXT-YmXqH-jH.mjs";import{composeIdentityResolvers as Ke,routeIdentityResolvers as Ue}from"./packem_shared/composeIdentityResolvers-BHZ4jH8o.mjs";const e="0.0.0";export{t as BACKUP_KEY_PREFIX,pe as DEFAULT_LOG_COLUMNS,O as DEFAULT_REGISTRY_CACHE_TTL_MS,G as HEALTH_PATH,K as HEALTH_READY_PATH,Me as LOG_ARCHIVE_NOT_CONFIGURED,X as LOG_ARCHIVE_PATH,T as LunoraError,Ne as NOOP_EXECUTION_CONTEXT,b as SHARD_REGISTRY_DO_NAME,Ie as STORAGE_UPLOAD_MAX_BODY_BYTES,e as VERSION,ee as analyticsEngineSink,xe as applyJurisdiction,ue as applyRestCache,ye as argsFromQuery,a as backupManifestKey,s as backupObjectKey,i as backupObjectKeyOfManifest,U as buildHealthRoutes,Ce as buildRestRoutes,re as combineSinks,Ke as composeIdentityResolvers,x as composeWorker,oe as consoleSink,y as createCrossShardRelationCapabilities,A as createDynamicShardRegistry,P as createKvCursorStore,S as createLunoraHandler,g as createMemoryCursorStore,ce as createPipelineLogReader,fe as createQueryCoordinator,Oe as createRestRateLimit,ge as createShardClient,Ee as createStaticShardRegistry,l as createWorker,B as d1Probe,Le as decorateResponse,v as defineExportSink,u as defineRpcEnvelope,Y as durableObjectProbe,J as emitLogEvent,Z as emitRpcEvent,Te as enforceOrigin,he as handleCorsPreflight,n as isBackupManifestEntry,p as isBackupManifestKey,W as memoizeIdentity,q as memoizeIdentityPerRequest,c as normalizeBackupPrefix,te as otlpSink,ae as pipelineLogSink,w as presenceProbe,I as r2Sink,_e as requestCarriesCredentials,j as resolveLogArchiveFromEnv,_ as resolveLunoraOptions,He as resolveSecurity,Se as resolveShard,de as restCacheHeaders,be as restSurfaceFromRegistry,Ue as routeIdentityResolvers,D as runExportTap,M as sanitizeChange,se as sentrySink,f as toAirbyteMessages,h as toErrorResponse,E as toFivetranResponse,F as webhookExportSink,ie as webhookSink,d as withFrameworkWorker};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{toErrorBody as T}from"@lunora/errors";import{b as E,a as I}from"./base64-Bl1_r2k1.mjs";import{LunoraError as U}from"./LunoraError-DksAgIpa.mjs";import{resolveShard as B}from"./applyJurisdiction-C0ddU7Tg.mjs";const be=t=>({listShardKeys(e){return t[e]??[]}}),F=16,D=5e3,y=t=>t!==null&&typeof t=="object"&&"result"in t?t.result:t,V=t=>{const e=t??{};return{changed:typeof e.changed=="number"?e.changed:0,processed:typeof e.processed=="number"?e.processed:0,status:typeof e.status=="string"?e.status:void 0}},L=(t,e)=>t?"failed":e?"in_progress":"completed",j=t=>{const e=[];let s=0,o=0,r=0,n=0,a=!1,c=!1;for(const i of t){if(i.kind==="err"){o+=1,e.push({error:{message:i.message,timedOut:i.timedOut},shardKey:i.shardKey});continue}s+=1;const d=y(i.value),u=V(d);r+=u.changed,n+=u.processed,a||=u.status==="in_progress",c||=u.status==="failed",e.push({result:d,shardKey:i.shardKey})}return{changed:r,failed:o,ok:s,processed:n,shards:e,status:L(c,a||o>0)}},$=t=>{const e=t??{};return{before:typeof e.before=="number"&&Number.isFinite(e.before)?e.before:0,total:typeof e.total=="number"&&Number.isFinite(e.total)?e.total:0}},J=t=>{const e=[];let s=0,o=0,r=0,n=0;for(const a of t){if(a.kind==="err"){o+=1,e.push({error:{message:a.message,timedOut:a.timedOut},shardKey:a.shardKey});continue}s+=1;const c=$(y(a.value));r+=c.before,n+=c.total,e.push({result:c,shardKey:a.shardKey})}return{failed:o,ok:s,partial:o>0,position:r+1,shards:e,total:n}},x=0,P=1,G=2,k=(t,e)=>t<e?-1:t>e?1:0,M=t=>t==null?x:typeof t=="number"?P:G,O=(t,e)=>{const s=M(t),o=M(e);return s!==o?s<o?-1:1:s===x?0:s===P?k(t,e):k(String(t),String(e))},H=(t,e,s)=>{const o=O(t.partitionKey,e.partitionKey);if(o!==0)return o;const r=Math.max(t.sortValues.length,e.sortValues.length);for(let n=0;n<r;n+=1){const a=O(t.sortValues[n],e.sortValues[n]);if(a!==0)return s[n]==="desc"?-a:a}return O(t.rowId,e.rowId)},Q=t=>I(new TextEncoder().encode(JSON.stringify(t))),Y=t=>{try{const e=JSON.parse(new TextDecoder().decode(E(t)));if(e!==null&&typeof e=="object"&&"perShard"in e){const{perShard:s}=e;if(s!==null&&typeof s=="object")return{perShard:s}}}catch{}return{perShard:{}}},W=t=>{const e=t??{},s=Array.isArray(e.rows)?e.rows:[];return{directions:Array.isArray(e.directions)?e.directions:[],hasMore:e.hasMore===!0,rows:s}},X=(t,e)=>{let s;for(const o of t){const r=o.rows[o.head];r!==void 0&&(s===void 0||H(r.key,s.row.key,e)<0)&&(s={row:r,slice:o})}return s},z=(t,e)=>{let s=!1;const o=new Set;for(const n of t)o.add(n.shardKey),(n.head<n.rows.length||n.hasMore)&&(s=!0);const r={...e};for(const n of Object.keys(e))o.has(n)||(s=!0);return s?Q({perShard:r}):null},Z=(t,e,s,o)=>{const r=[],n={...o};for(;r.length<e;){const c=X(t,s);if(c===void 0)break;r.push(c.row.doc),n[c.slice.shardKey]=c.row.key,c.slice.head+=1}const a=z(t,n);return{isDone:a===null,nextCursor:a,page:r}},q=t=>{const e=[];let s=0,o=0;for(const r of t){if(r.kind==="err"){o+=1,e.push({error:{message:r.message,timedOut:r.timedOut},shardKey:r.shardKey});continue}s+=1;const n=y(r.value),a=Array.isArray(n?.rows)?n.rows:[];e.push({rows:a,shardKey:r.shardKey})}return{failed:o,ok:s,shards:e}},ee=t=>{const e=[];let s=0,o=0;for(const{outcome:r,sinceEpoch:n,sinceSeq:a}of t){if(r.kind==="err"){o+=1,e.push({cursor:a,error:{code:r.code,message:r.message,timedOut:r.timedOut},shardKey:r.shardKey,...n===void 0?{}:{epoch:n}});continue}s+=1;const c=y(r.value),i=Array.isArray(c?.changes)?c.changes:[],d=typeof c?.cursor=="number"?c.cursor:a,u=typeof c?.epoch=="string"&&c.epoch.length>0?c.epoch:n;e.push({changes:i,cursor:d,shardKey:r.shardKey,...u===void 0?{}:{epoch:u}})}return{failed:o,ok:s,shards:e}},re=t=>{let e=0,s=0,o=0;for(const r of t){if(r.kind==="err"){s+=1;continue}e+=1;const n=y(r.value);o+=typeof n?.applied=="number"?n.applied:0}return{applied:o,failed:s,ok:e}},te=t=>{const e=t??{};return typeof e.requests=="number"&&Number.isFinite(e.requests)&&e.requests>=0?e.requests:0},se=t=>{const e=[];let s=0,o=0;for(const r of t){if(r.kind==="err"){o+=1,e.push({requests:0,shardKey:r.shardKey});continue}s+=1,e.push({requests:te(y(r.value)),shardKey:r.shardKey})}return{failed:o,ok:s,shards:e}},oe=t=>{const e=[],s={},o=[];let r=0,n=0,a=0;for(const c of t){if(c.kind==="err"){a+=1,e.push({error:{message:c.message,timedOut:c.timedOut},shardKey:c.shardKey});continue}n+=1;const i=y(c.value),d=i?.inserted??{};for(const[l,h]of Object.entries(d))s[l]=(s[l]??0)+h;const u=i?.errors;Array.isArray(u)&&o.push(...u),r+=i?.conflicts??0,e.push({result:{conflicts:i?.conflicts??0,errors:i?.errors??[],inserted:d},shardKey:c.shardKey})}return{conflicts:r,errors:o,failed:a,inserted:s,ok:n,shards:e}},g=t=>({body:JSON.stringify({args:t.args??{},functionPath:t.functionPath}),headers:{"content-type":"application/json",...t.headers}}),ne=async t=>{try{const s=(await t.json())?.error;return typeof s?.code!="string"||s.code.length===0?void 0:{code:s.code,message:typeof s.message=="string"?s.message:""}}catch{return}},w=async(t,e,s,o)=>{const r=B(t,e),n=new AbortController,a=new Request("https://shard.internal/rpc",{body:s.body,headers:s.headers,method:"POST",signal:n.signal});let c;const i=new Promise(u=>{c=setTimeout(()=>{try{n.abort()}catch{}u({code:"SHARD_TIMEOUT",kind:"err",message:`shard "${e}" timed out after ${String(o)}ms`,shardKey:e,timedOut:!0})},o)}),d=(async()=>{try{const u=await r.fetch(a);if(!u.ok){const h=await ne(u),m=`shard "${e}" returned ${String(u.status)}`;return{code:h?.code??"SHARD_HTTP_ERROR",kind:"err",message:h===void 0||h.message.length===0?m:`${m}: ${h.message}`,shardKey:e,timedOut:!1}}const l=await u.json();return{kind:"ok",shardKey:e,value:l}}catch(u){const{body:l}=T(u,{fallbackCode:"INTERNAL",redactedMessage:"shard call failed"});return{code:l.code,kind:"err",message:`shard "${e}" failed: ${l.message}`,shardKey:e,timedOut:!1}}})();try{return await Promise.race([d,i])}finally{c!==void 0&&clearTimeout(c)}},b=async(t,e,s)=>{if(t.length===0)return[];const o=Array.from({length:t.length});let r=0;const n=async()=>{for(;;){const c=r;r+=1;const i=t[c];if(c>=t.length||i===void 0)return;o[c]=await s(i,c)}},a=Math.min(e,t.length);return await Promise.all(Array.from({length:a},()=>n())),o},K=(t,e)=>t.length>0||e===null?t:[e],v=async(t,e,s)=>{const o=await Promise.all(e.map(async r=>K(await t.listShardKeys(r),s)));return[...new Set(o.flat())]},p=async(t,e,s,o,r)=>{const n=g(s);return b(e,o,async a=>w(t,a,n,r))},ae=t=>{const e={};for(const s of Object.keys(t).toSorted(k))e[s]=t[s]??null;return JSON.stringify(e)},ce=t=>t.flatMap(e=>Array.isArray(e)?e:[]),ie=(t,e,s)=>{switch(s){case"max":return Math.max(t,e);case"min":return Math.min(t,e);case"sum":return t+e;default:return t}},ue=(t,e,s)=>{if(e===null||typeof e!="object")return;const o=e.key??{},r=e.value??null,n=ae(o),a=t.get(n);if(!a){t.set(n,{key:o,value:r});return}if(a.value===null){a.value=r;return}r!==null&&(a.value=ie(a.value,r,s))},de=(t,e)=>{const s=new Map;for(const o of t)if(Array.isArray(o))for(const r of o)ue(s,r,e);return[...s.values()]},N=(t,e)=>{let s=null;for(const o of t)typeof o=="number"&&Number.isFinite(o)&&(s=s===null?o:e(s,o));return s},le=t=>{let e=0;for(const s of t)typeof s=="number"&&Number.isFinite(s)&&(e+=s);return e},fe=t=>{let e=0,s=0;for(const o of t){if(o===null||typeof o!="object")continue;const r=o;typeof r.before=="number"&&Number.isFinite(r.before)&&(e+=r.before),typeof r.total=="number"&&Number.isFinite(r.total)&&(s+=r.total)}return{position:e+1,total:s}},he=(t,e)=>{const s=[];for(const r of t)if(Array.isArray(r))for(const n of r){if(n===null||typeof n!="object")continue;const a=n[e.by],c=typeof a=="number"&&Number.isFinite(a)?a:Number.NEGATIVE_INFINITY;s.push({row:n,score:c})}const o=e.direction??"desc";return s.sort((r,n)=>o==="asc"?k(r.score,n.score):k(n.score,r.score)),s.slice(0,e.k).map(r=>r.row)},ye=(t,e)=>{switch(e.kind){case"concat":return ce(t);case"first":return t[0];case"groupBy":return de(t,e.op??"sum");case"max":return N(t,Math.max);case"min":return N(t,Math.min);case"rank":return fe(t);case"sum":return le(t);case"topK":return he(t,e);default:return t}},ke=t=>{const e=t.maxConcurrency??F,s=t.perShardTimeoutMs??D;if(e<1)throw new U("maxConcurrency must be >= 1",{code:"BAD_REQUEST",status:400});return{async fanOut(o,r){const n=await t.registry.listShardKeys(r.fanOut.table),a=await p(o,n,r,e,s),c=[],i=[];for(const d of a)d.kind==="ok"?c.push(d.value):i.push({code:d.code,message:d.message,shardKey:d.shardKey,timedOut:d.timedOut});return{data:ye(c,r.fanOut.merge),errors:i,failed:i.length,ok:c.length}},async orchestrateExport(o,r){const n=await v(t.registry,r.tables,r.defaultShardKey),a=K(n,r.defaultShardKey),c={args:{...r.args,tables:[...r.tables]},functionPath:"__lunora_admin__:exportShard",headers:r.headers},i=await p(o,a,c,e,s);return q(i)},async orchestrateCdcSync(o,r){const n=K(await v(t.registry,r.tables,r.defaultShardKey),r.defaultShardKey),a=r.cursors??{},c=r.epochs??{},i=await b(n,e,async d=>{const u=a[d]??0,l=c[d];return{outcome:await w(o,d,g({args:{limit:r.limit,sinceEpoch:l,sinceSeq:u},functionPath:"__lunora_admin__:cdcSync",headers:r.headers}),s),sinceEpoch:l,sinceSeq:u}});return ee(i)},async orchestrateImport(o,r){const{batches:n}=r,a=await b(n,e,async c=>w(o,c.shardKey,g({args:{rows:[...c.rows],startLine:c.startLine??1},functionPath:"__lunora_admin__:importShard",headers:r.headers}),s));return oe(a)},async orchestrateApplyCdc(o,r){const{batches:n}=r,a=await b(n,e,async c=>w(o,c.shardKey,g({args:{changes:[...c.changes]},functionPath:"__lunora_admin__:applyCdc",headers:r.headers}),s));return re(a)},async orchestrateMigration(o,r){const n=K(await t.registry.listShardKeys(r.table),r.defaultShardKey),a=await p(o,n,r,e,s);return j(a)},async orchestrateRank(o,r){const n=await t.registry.listShardKeys(r.table),a={args:{index:r.index,partitionKey:r.partitionKey,rowId:r.rowId,sortValues:[...r.sortValues],table:r.table},functionPath:"__lunora_admin__:rankBefore",headers:r.headers},c=await p(o,n,a,e,s);return J(c)},async orchestrateRankPage(o,r){const n=await t.registry.listShardKeys(r.table),a=Math.max(1,Math.min(1e3,Math.floor(r.take??100))),c=r.directions??[],i=r.cursor?Y(r.cursor):{perShard:{}},d=await b(n,e,async f=>{const C=i.perShard[f],A={index:r.index,table:r.table,take:a};r.partitionKey!==void 0&&(A.partitionKey=r.partitionKey),C!==void 0&&(A.after=C);const S=await w(o,f,g({args:A,functionPath:"__lunora_admin__:rankPage",headers:r.headers}),s);if(S.kind==="err")return{error:{message:S.message,timedOut:S.timedOut},shardKey:f};const R=W(y(S.value));return{directions:R.directions,hasMore:R.hasMore,rows:R.rows,shardKey:f}}),u=[];let l=0,h=0,m;for(const f of d){if(f.error){h+=1;continue}l+=1,m===void 0&&f.directions&&f.directions.length>0&&(m=f.directions),u.push({hasMore:f.hasMore??!1,head:0,rows:f.rows??[],shardKey:f.shardKey})}const _=Z(u,a,m??c,i.perShard);return{continueCursor:_.nextCursor,failed:h,isDone:_.isDone,ok:l,page:_.page,partial:h>0,shards:d}},async orchestrateShardTraffic(o,r){const n=await t.registry.listShardKeys(r.table),a={functionPath:"__lunora_admin__:getMetrics",headers:r.headers},c=await p(o,n,a,e,s);return se(c)},registry:t.registry}};export{ke as createQueryCoordinator,be as createStaticShardRegistry};
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{toErrorBody as v}from"@lunora/errors";import{b as E,a as I}from"./base64-Bl1_r2k1.mjs";import{LunoraError as U}from"./LunoraError-DksAgIpa.mjs";import{resolveShard as B}from"./applyJurisdiction-C0ddU7Tg.mjs";const we=t=>({listShardKeys(e){return t[e]??[]}}),F=16,D=5e3,h=t=>t!==null&&typeof t=="object"&&"result"in t?t.result:t,V=t=>{const e=t??{};return{changed:typeof e.changed=="number"?e.changed:0,processed:typeof e.processed=="number"?e.processed:0,status:typeof e.status=="string"?e.status:void 0}},L=(t,e)=>t?"failed":e?"in_progress":"completed",j=t=>{const e=[];let s=0,o=0,r=0,n=0,a=!1,c=!1;for(const i of t){if(i.kind==="err"){o+=1,e.push({error:{message:i.message,timedOut:i.timedOut},shardKey:i.shardKey});continue}s+=1;const l=h(i.value),u=V(l);r+=u.changed,n+=u.processed,a||=u.status==="in_progress",c||=u.status==="failed",e.push({result:l,shardKey:i.shardKey})}return{changed:r,failed:o,ok:s,processed:n,shards:e,status:L(c,a||o>0)}},J=t=>{const e=t??{};return{before:typeof e.before=="number"&&Number.isFinite(e.before)?e.before:0,total:typeof e.total=="number"&&Number.isFinite(e.total)?e.total:0}},$=t=>{const e=[];let s=0,o=0,r=0,n=0;for(const a of t){if(a.kind==="err"){o+=1,e.push({error:{message:a.message,timedOut:a.timedOut},shardKey:a.shardKey});continue}s+=1;const c=J(h(a.value));r+=c.before,n+=c.total,e.push({result:c,shardKey:a.shardKey})}return{failed:o,ok:s,partial:o>0,position:r+1,shards:e,total:n}},P=0,T=1,G=2,k=(t,e)=>t<e?-1:t>e?1:0,M=t=>t==null?P:typeof t=="number"?T:G,O=(t,e)=>{const s=M(t),o=M(e);return s!==o?s<o?-1:1:s===P?0:s===T?k(t,e):k(String(t),String(e))},H=(t,e,s)=>{const o=O(t.partitionKey,e.partitionKey);if(o!==0)return o;const r=Math.max(t.sortValues.length,e.sortValues.length);for(let n=0;n<r;n+=1){const a=O(t.sortValues[n],e.sortValues[n]);if(a!==0)return s[n]==="desc"?-a:a}return O(t.rowId,e.rowId)},Q=t=>I(new TextEncoder().encode(JSON.stringify(t))),Y=t=>{try{const e=JSON.parse(new TextDecoder().decode(E(t)));if(e!==null&&typeof e=="object"&&"perShard"in e){const{perShard:s}=e;if(s!==null&&typeof s=="object")return{perShard:s}}}catch{}return{perShard:{}}},W=t=>{const e=t??{},s=Array.isArray(e.rows)?e.rows:[];return{directions:Array.isArray(e.directions)?e.directions:[],hasMore:e.hasMore===!0,rows:s}},X=(t,e)=>{let s;for(const o of t){const r=o.rows[o.head];r!==void 0&&(s===void 0||H(r.key,s.row.key,e)<0)&&(s={row:r,slice:o})}return s},z=(t,e)=>{let s=!1;const o=new Set;for(const n of t)o.add(n.shardKey),(n.head<n.rows.length||n.hasMore)&&(s=!0);const r={...e};for(const n of Object.keys(e))o.has(n)||(s=!0);return s?Q({perShard:r}):null},Z=(t,e,s,o)=>{const r=[],n={...o};for(;r.length<e;){const c=X(t,s);if(c===void 0)break;r.push(c.row.doc),n[c.slice.shardKey]=c.row.key,c.slice.head+=1}const a=z(t,n);return{isDone:a===null,nextCursor:a,page:r}},q=t=>{const e=[];let s=0,o=0;for(const r of t){if(r.kind==="err"){o+=1,e.push({error:{message:r.message,timedOut:r.timedOut},shardKey:r.shardKey});continue}s+=1;const n=h(r.value),a=Array.isArray(n?.rows)?n.rows:[];e.push({rows:a,shardKey:r.shardKey})}return{failed:o,ok:s,shards:e}},ee=t=>{const e=[];let s=0,o=0;for(const{outcome:r,sinceEpoch:n,sinceSeq:a}of t){if(r.kind==="err"){o+=1,e.push({cursor:a,error:{message:r.message,timedOut:r.timedOut},shardKey:r.shardKey,...n===void 0?{}:{epoch:n}});continue}s+=1;const c=h(r.value),i=Array.isArray(c?.changes)?c.changes:[],l=typeof c?.cursor=="number"?c.cursor:a,u=typeof c?.epoch=="string"&&c.epoch.length>0?c.epoch:n;e.push({changes:i,cursor:l,shardKey:r.shardKey,...u===void 0?{}:{epoch:u}})}return{failed:o,ok:s,shards:e}},re=t=>{let e=0,s=0,o=0;for(const r of t){if(r.kind==="err"){s+=1;continue}e+=1;const n=h(r.value);o+=typeof n?.applied=="number"?n.applied:0}return{applied:o,failed:s,ok:e}},te=t=>{const e=t??{};return typeof e.requests=="number"&&Number.isFinite(e.requests)&&e.requests>=0?e.requests:0},se=t=>{const e=[];let s=0,o=0;for(const r of t){if(r.kind==="err"){o+=1,e.push({requests:0,shardKey:r.shardKey});continue}s+=1,e.push({requests:te(h(r.value)),shardKey:r.shardKey})}return{failed:o,ok:s,shards:e}},oe=t=>{const e=[],s={},o=[];let r=0,n=0,a=0;for(const c of t){if(c.kind==="err"){a+=1,e.push({error:{message:c.message,timedOut:c.timedOut},shardKey:c.shardKey});continue}n+=1;const i=h(c.value),l=i?.inserted??{};for(const[d,y]of Object.entries(l))s[d]=(s[d]??0)+y;const u=i?.errors;Array.isArray(u)&&o.push(...u),r+=i?.conflicts??0,e.push({result:{conflicts:i?.conflicts??0,errors:i?.errors??[],inserted:l},shardKey:c.shardKey})}return{conflicts:r,errors:o,failed:a,inserted:s,ok:n,shards:e}},p=t=>({body:JSON.stringify({args:t.args??{},functionPath:t.functionPath}),headers:{"content-type":"application/json",...t.headers}}),g=async(t,e,s,o)=>{const r=B(t,e),n=new AbortController,a=new Request("https://shard.internal/rpc",{body:s.body,headers:s.headers,method:"POST",signal:n.signal});let c;const i=new Promise(u=>{c=setTimeout(()=>{try{n.abort()}catch{}u({code:"SHARD_TIMEOUT",kind:"err",message:`shard "${e}" timed out after ${String(o)}ms`,shardKey:e,timedOut:!0})},o)}),l=(async()=>{try{const u=await r.fetch(a);if(!u.ok)return{code:"SHARD_HTTP_ERROR",kind:"err",message:`shard "${e}" returned ${String(u.status)}`,shardKey:e,timedOut:!1};const d=await u.json();return{kind:"ok",shardKey:e,value:d}}catch(u){const{body:d}=v(u,{fallbackCode:"INTERNAL",redactedMessage:"shard call failed"});return{code:d.code,kind:"err",message:`shard "${e}" failed: ${d.message}`,shardKey:e,timedOut:!1}}})();try{return await Promise.race([l,i])}finally{c!==void 0&&clearTimeout(c)}},w=async(t,e,s)=>{if(t.length===0)return[];const o=Array.from({length:t.length});let r=0;const n=async()=>{for(;;){const c=r;r+=1;const i=t[c];if(c>=t.length||i===void 0)return;o[c]=await s(i,c)}},a=Math.min(e,t.length);return await Promise.all(Array.from({length:a},()=>n())),o},S=(t,e)=>t.length>0||e===null?t:[e],N=async(t,e,s)=>{const o=await Promise.all(e.map(async r=>S(await t.listShardKeys(r),s)));return[...new Set(o.flat())]},m=async(t,e,s,o,r)=>{const n=p(s);return w(e,o,async a=>g(t,a,n,r))},ne=t=>{const e={};for(const s of Object.keys(t).toSorted(k))e[s]=t[s]??null;return JSON.stringify(e)},ae=t=>t.flatMap(e=>Array.isArray(e)?e:[]),ce=(t,e,s)=>{switch(s){case"max":return Math.max(t,e);case"min":return Math.min(t,e);case"sum":return t+e;default:return t}},ie=(t,e,s)=>{if(e===null||typeof e!="object")return;const o=e.key??{},r=e.value??null,n=ne(o),a=t.get(n);if(!a){t.set(n,{key:o,value:r});return}if(a.value===null){a.value=r;return}r!==null&&(a.value=ce(a.value,r,s))},ue=(t,e)=>{const s=new Map;for(const o of t)if(Array.isArray(o))for(const r of o)ie(s,r,e);return[...s.values()]},x=(t,e)=>{let s=null;for(const o of t)typeof o=="number"&&Number.isFinite(o)&&(s=s===null?o:e(s,o));return s},le=t=>{let e=0;for(const s of t)typeof s=="number"&&Number.isFinite(s)&&(e+=s);return e},de=t=>{let e=0,s=0;for(const o of t){if(o===null||typeof o!="object")continue;const r=o;typeof r.before=="number"&&Number.isFinite(r.before)&&(e+=r.before),typeof r.total=="number"&&Number.isFinite(r.total)&&(s+=r.total)}return{position:e+1,total:s}},fe=(t,e)=>{const s=[];for(const r of t)if(Array.isArray(r))for(const n of r){if(n===null||typeof n!="object")continue;const a=n[e.by],c=typeof a=="number"&&Number.isFinite(a)?a:Number.NEGATIVE_INFINITY;s.push({row:n,score:c})}const o=e.direction??"desc";return s.sort((r,n)=>o==="asc"?k(r.score,n.score):k(n.score,r.score)),s.slice(0,e.k).map(r=>r.row)},he=(t,e)=>{switch(e.kind){case"concat":return ae(t);case"first":return t[0];case"groupBy":return ue(t,e.op??"sum");case"max":return x(t,Math.max);case"min":return x(t,Math.min);case"rank":return de(t);case"sum":return le(t);case"topK":return fe(t,e);default:return t}},ke=t=>{const e=t.maxConcurrency??F,s=t.perShardTimeoutMs??D;if(e<1)throw new U("maxConcurrency must be >= 1",{code:"BAD_REQUEST",status:400});return{async fanOut(o,r){const n=await t.registry.listShardKeys(r.fanOut.table),a=await m(o,n,r,e,s),c=[],i=[];for(const l of a)l.kind==="ok"?c.push(l.value):i.push({code:l.code,message:l.message,shardKey:l.shardKey,timedOut:l.timedOut});return{data:he(c,r.fanOut.merge),errors:i,failed:i.length,ok:c.length}},async orchestrateExport(o,r){const n=await N(t.registry,r.tables,r.defaultShardKey),a=S(n,r.defaultShardKey),c={args:{...r.args,tables:[...r.tables]},functionPath:"__lunora_admin__:exportShard",headers:r.headers},i=await m(o,a,c,e,s);return q(i)},async orchestrateCdcSync(o,r){const n=S(await N(t.registry,r.tables,r.defaultShardKey),r.defaultShardKey),a=r.cursors??{},c=r.epochs??{},i=await w(n,e,async l=>{const u=a[l]??0,d=c[l];return{outcome:await g(o,l,p({args:{limit:r.limit,sinceEpoch:d,sinceSeq:u},functionPath:"__lunora_admin__:cdcSync",headers:r.headers}),s),sinceEpoch:d,sinceSeq:u}});return ee(i)},async orchestrateImport(o,r){const{batches:n}=r,a=await w(n,e,async c=>g(o,c.shardKey,p({args:{rows:[...c.rows],startLine:c.startLine??1},functionPath:"__lunora_admin__:importShard",headers:r.headers}),s));return oe(a)},async orchestrateApplyCdc(o,r){const{batches:n}=r,a=await w(n,e,async c=>g(o,c.shardKey,p({args:{changes:[...c.changes]},functionPath:"__lunora_admin__:applyCdc",headers:r.headers}),s));return re(a)},async orchestrateMigration(o,r){const n=S(await t.registry.listShardKeys(r.table),r.defaultShardKey),a=await m(o,n,r,e,s);return j(a)},async orchestrateRank(o,r){const n=await t.registry.listShardKeys(r.table),a={args:{index:r.index,partitionKey:r.partitionKey,rowId:r.rowId,sortValues:[...r.sortValues],table:r.table},functionPath:"__lunora_admin__:rankBefore",headers:r.headers},c=await m(o,n,a,e,s);return $(c)},async orchestrateRankPage(o,r){const n=await t.registry.listShardKeys(r.table),a=Math.max(1,Math.min(1e3,Math.floor(r.take??100))),c=r.directions??[],i=r.cursor?Y(r.cursor):{perShard:{}},l=await w(n,e,async f=>{const C=i.perShard[f],A={index:r.index,table:r.table,take:a};r.partitionKey!==void 0&&(A.partitionKey=r.partitionKey),C!==void 0&&(A.after=C);const b=await g(o,f,p({args:A,functionPath:"__lunora_admin__:rankPage",headers:r.headers}),s);if(b.kind==="err")return{error:{message:b.message,timedOut:b.timedOut},shardKey:f};const R=W(h(b.value));return{directions:R.directions,hasMore:R.hasMore,rows:R.rows,shardKey:f}}),u=[];let d=0,y=0,K;for(const f of l){if(f.error){y+=1;continue}d+=1,K===void 0&&f.directions&&f.directions.length>0&&(K=f.directions),u.push({hasMore:f.hasMore??!1,head:0,rows:f.rows??[],shardKey:f.shardKey})}const _=Z(u,a,K??c,i.perShard);return{continueCursor:_.nextCursor,failed:y,isDone:_.isDone,ok:d,page:_.page,partial:y>0,shards:l}},async orchestrateShardTraffic(o,r){const n=await t.registry.listShardKeys(r.table),a={functionPath:"__lunora_admin__:getMetrics",headers:r.headers},c=await m(o,n,a,e,s);return se(c)},registry:t.registry}};export{ke as createQueryCoordinator,we as createStaticShardRegistry};
|