@lunora/platform-node 1.0.0-alpha.66 → 1.0.0-alpha.68
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/conformance/index.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/packem_shared/{createNodePlatform-BnplJiAw.mjs → createNodePlatform-CvtWQfL-.mjs} +1 -1
- package/dist/packem_shared/createNodeShardHost-Da19DFX0.mjs +1 -0
- package/dist/packem_shared/{createNodeShardRegistry-Dzqi0Q8l.mjs → createNodeShardRegistry-D-KxwdUc.mjs} +1 -1
- package/dist/packem_shared/createNodeWorkflowHost-B5Aiwj3L.mjs +1 -0
- package/package.json +7 -7
- package/dist/packem_shared/createNodeShardHost-CfX2IrZ8.mjs +0 -1
- package/dist/packem_shared/createNodeWorkflowHost-CTVBYiuj.mjs +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createNodeShardKvStore as N}from"../packem_shared/createNodeShardKvStore-DVi1OsvH.mjs";import{createNodeSchedulerHost as k}from"../packem_shared/createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as D}from"../packem_shared/createNodeShardHost-
|
|
1
|
+
import{createNodeShardKvStore as N}from"../packem_shared/createNodeShardKvStore-DVi1OsvH.mjs";import{createNodeSchedulerHost as k}from"../packem_shared/createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as D}from"../packem_shared/createNodeShardHost-Da19DFX0.mjs";import{createNodeShardRegistry as H}from"../packem_shared/createNodeShardRegistry-D-KxwdUc.mjs";import{createNodeSocketHost as T}from"../packem_shared/createNodeSocketHost-DQs85G7W.mjs";const P=()=>{const{database:o,dispose:m,host:p}=D(),h=N(o),c=H(),{directory:l}=c,{readFrames:w,restoreSocket:u,simulateRecycle:S,socket:y}=T(o),d=new Set,s=new Map,{dispose:f,scheduler:i,simulateDeadLetter:g}=k(o,{onDispatch:(e,a,t)=>{d.add(t.id),s.set(e,(s.get(e)??0)+1)}}),n=()=>{f(),m(),c.close()};return{awaitAlarmFired:async e=>{await new Promise(a=>{setTimeout(a,Math.max(0,e-Date.now())+30)})},awaitJobDispatched:async e=>{const t=(await i.list?.())?.find(r=>r.id===e);return t!==void 0&&await new Promise(r=>{setTimeout(r,Math.max(0,t.scheduledFor-Date.now())+30)}),d.has(e)},cleanup:n,cronTicks:e=>s.get(e)??0,directory:l,disposeTerminally:n,kv:h,readFrames:w,restoreSocket:u,scheduler:i,shard:p,simulateDeadLetter:g,simulateRecycle:S,socket:y}};export{P as createNodeConformanceHost};
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createNodeGlobalStore as r,createNodeSqlExec as t}from"./packem_shared/createNodeGlobalStore-nAJ4WO7w.mjs";import{createNodeShardKvStore as d}from"./packem_shared/createNodeShardKvStore-DVi1OsvH.mjs";import{createNodePlatform as f}from"./packem_shared/createNodePlatform-
|
|
1
|
+
import{createNodeGlobalStore as r,createNodeSqlExec as t}from"./packem_shared/createNodeGlobalStore-nAJ4WO7w.mjs";import{createNodeShardKvStore as d}from"./packem_shared/createNodeShardKvStore-DVi1OsvH.mjs";import{createNodePlatform as f}from"./packem_shared/createNodePlatform-CvtWQfL-.mjs";import{createNodeQueueHost as x}from"./packem_shared/createNodeQueueHost--mBLGSxF.mjs";import{createNodeR2Bucket as p}from"./packem_shared/createNodeR2Bucket-BzNH1lBp.mjs";import{createNodeSchedulerHost as l}from"./packem_shared/createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as h}from"./packem_shared/createNodeShardHost-Da19DFX0.mjs";import{createNodeShardRegistry as k}from"./packem_shared/createNodeShardRegistry-D-KxwdUc.mjs";import{createNodeShardState as w}from"./packem_shared/createNodeShardState-D6XMWbFs.mjs";import{createNodeSocketHost as W}from"./packem_shared/createNodeSocketHost-DQs85G7W.mjs";import{createNodeWorkflowHost as g}from"./packem_shared/createNodeWorkflowHost-B5Aiwj3L.mjs";import{createNodeWorkflowStore as q}from"./packem_shared/createNodeWorkflowStore-CL7RYP6H.mjs";export{r as createNodeGlobalStore,f as createNodePlatform,x as createNodeQueueHost,p as createNodeR2Bucket,l as createNodeSchedulerHost,h as createNodeShardHost,d as createNodeShardKvStore,k as createNodeShardRegistry,w as createNodeShardState,W as createNodeSocketHost,t as createNodeSqlExec,g as createNodeWorkflowHost,q as createNodeWorkflowStore};
|
package/dist/packem_shared/{createNodePlatform-BnplJiAw.mjs → createNodePlatform-CvtWQfL-.mjs}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{LunoraError as S}from"@lunora/errors";import{NODE_CAPABILITIES as b}from"@lunora/platform";import{createNodeGlobalStore as N}from"./createNodeGlobalStore-nAJ4WO7w.mjs";import{createNodeShardKvStore as k}from"./createNodeShardKvStore-DVi1OsvH.mjs";import{createNodeQueueHost as g}from"./createNodeQueueHost--mBLGSxF.mjs";import{createNodeR2Bucket as y}from"./createNodeR2Bucket-BzNH1lBp.mjs";import{createNodeSchedulerHost as R}from"./createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as q}from"./createNodeShardHost-
|
|
1
|
+
import{LunoraError as S}from"@lunora/errors";import{NODE_CAPABILITIES as b}from"@lunora/platform";import{createNodeGlobalStore as N}from"./createNodeGlobalStore-nAJ4WO7w.mjs";import{createNodeShardKvStore as k}from"./createNodeShardKvStore-DVi1OsvH.mjs";import{createNodeQueueHost as g}from"./createNodeQueueHost--mBLGSxF.mjs";import{createNodeR2Bucket as y}from"./createNodeR2Bucket-BzNH1lBp.mjs";import{createNodeSchedulerHost as R}from"./createNodeSchedulerHost-BEAX6I4m.mjs";import{createNodeShardHost as q}from"./createNodeShardHost-Da19DFX0.mjs";import{createNodeShardRegistry as B}from"./createNodeShardRegistry-D-KxwdUc.mjs";import{createNodeSocketHost as H}from"./createNodeSocketHost-DQs85G7W.mjs";import{createNodeWorkflowHost as I}from"./createNodeWorkflowHost-B5Aiwj3L.mjs";import{createNodeWorkflowStore as P}from"./createNodeWorkflowStore-CL7RYP6H.mjs";const G=(o={})=>{const e=[],{database:r,dispose:d,drain:u,host:i}=q(o);e.push(d);try{const s=k(r),t=B(o);e.push(()=>{t.close()});const{directory:l}=t,{socket:h}=H(r),{dispose:m,scheduler:f}=R(r,o);e.push(m);const n=o.queues===void 0?void 0:g(r,{onBatch:o.onQueueBatch??(()=>{throw new S("VALIDATION_ERROR","@lunora/platform-node: createNodePlatform was given `queues` without `onQueueBatch`, so a delivered batch has nowhere to go — pass dispatchQueueBatch from @lunora/queue")}),queues:o.queues}),p=o.objectStorageDirectory===void 0?void 0:y({directory:o.objectStorageDirectory}),a=o.globalTablesPath===void 0?void 0:N({path:o.globalTablesPath});a!==void 0&&e.push(()=>{a.dispose()});const w=o.workflows===void 0?void 0:I({store:P(r),workflows:o.workflows}),c=()=>{for(const v of e.toReversed())v()};return{capabilities:b,close:c,directory:l,drain:u,globalTables:a,kv:s,objectStorage:p,queues:n,scheduler:f,shard:i,sockets:h,workflows:w,[Symbol.dispose]:c}}catch(s){for(const t of e.toReversed())try{t()}catch{}throw s}};export{G as createNodePlatform};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{AsyncLocalStorage as S}from"node:async_hooks";import{LunoraError as v}from"@lunora/errors";import L from"better-sqlite3";const y=2147483647,R=6,O=100,I=e=>e===void 0?null:e,M=(e,t)=>({get databaseSize(){const l=e.pragma("page_count",{simple:!0}),r=e.pragma("page_size",{simple:!0});return l*r},exec:(l,...r)=>{t("run SQL");const o=e.prepare(l),s=r.map(c=>I(c)),n=o.reader?o.all(...s):(o.run(...s),[]);return{get columnNames(){return o.reader?o.columns().map(c=>c.name):void 0},[Symbol.iterator]:()=>n[Symbol.iterator](),one:()=>{if(n.length!==1)throw new Error(`expected exactly one row, got ${String(n.length)}`);return n[0]},...o.reader?{raw:()=>e.prepare(l).raw(!0).all(...s)[Symbol.iterator]()}:{},toArray:()=>[...n]}}}),N=(e,t,l)=>{let r,o,s=0,n;e.exec("CREATE TABLE IF NOT EXISTS _lunora_alarm (id INTEGER PRIMARY KEY CHECK (id = 0), scheduled_for INTEGER NOT NULL)");const c=a=>{a===void 0?e.prepare("DELETE FROM _lunora_alarm WHERE id = 0").run():e.prepare("INSERT INTO _lunora_alarm (id, scheduled_for) VALUES (0, ?) ON CONFLICT (id) DO UPDATE SET scheduled_for = excluded.scheduled_for").run(a)},p=()=>{o!==void 0&&(clearTimeout(o),o=void 0)},m=a=>{p();const d=Math.max(0,a-Date.now());if(d>y){o=setTimeout(()=>{m(a)},y);return}o=setTimeout(()=>{r=void 0,o=void 0,e.open&&(c(void 0),(async()=>{await l?.(),s=0})().catch(()=>{if(!e.open||r!==void 0)return;if(s+=1,s>R){s=0;return}const E=Date.now()+O*2**(s-1);r=E,c(E),m(E)}))},d)},f={delete:()=>{if(!e.open)throw new Error("platform closed: cannot delete an alarm");if(t.assertOwnTurn("delete an alarm"),s=0,c(void 0),t.inside()){n={at:void 0};return}r=void 0,p()},get:()=>(n===void 0?r:n.at)??null,set:a=>{if(!e.open)throw new Error("platform closed: cannot set an alarm");t.assertOwnTurn("set an alarm");const d=typeof a=="number"?a:a.getTime();if(s=0,c(d),t.inside()){n={at:d};return}r=d,m(d)}},h=()=>{if(n===void 0)return;const{at:a}=n;if(n=void 0,a===void 0){r=void 0,p();return}r=a,m(a)},T=()=>{n=void 0},w=e.prepare("SELECT scheduled_for FROM _lunora_alarm WHERE id = 0").get();return w!==void 0&&(r=w.scheduled_for,m(w.scheduled_for)),{alarms:f,commit:h,dispose:p,rollback:T}},k=(e={})=>{const t=new L(e.path??":memory:");t.pragma("journal_mode = WAL");const l=new S;let r=!1;const o=i=>{if(r&&l.getStore()!==!0)throw new v("SHARD_UNAVAILABLE",`shard busy: cannot ${i} while another task holds this shard's transaction`)},s=M(t,o),{alarms:n,commit:c,dispose:p,rollback:m}=N(t,{assertOwnTurn:o,inside:()=>l.getStore()===!0},e.onAlarm),f=new Set,h=new S;let T=Promise.resolve();const w=async i=>{if(h.getStore()===!0)return await i();const u=T;let A=()=>{};T=new Promise(g=>{A=g}),await u;try{return await h.run(!0,i)}finally{A()}},a=i=>w(i),d=async i=>{t.exec("BEGIN"),r=!0;try{const u=await l.run(!0,i);return t.exec("COMMIT"),r=!1,c(),u}catch(u){r=!1,m();try{t.exec("ROLLBACK")}catch{}throw u}},E=i=>w(async()=>d(i)),_={alarms:n,runSerialized:a,shardKey:e.shardKey,sql:s,transaction:E,waitUntil:i=>{const u=i.catch(()=>{}).finally(()=>{f.delete(u)});f.add(u)}};return{database:t,dispose:()=>{p(),t.open&&t.close()},drain:async()=>{for(;f.size>0;)await Promise.all(f)},host:_}};export{k as createNodeShardHost};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{mkdirSync as y,readdirSync as S}from"node:fs";import{join as h}from"node:path";import{LunoraError as l}from"@lunora/errors";import{createNodeShardKvStore as v}from"./createNodeShardKvStore-DVi1OsvH.mjs";import{createNodeShardHost as w}from"./createNodeShardHost-
|
|
1
|
+
import{mkdirSync as y,readdirSync as S}from"node:fs";import{join as h}from"node:path";import{LunoraError as l}from"@lunora/errors";import{createNodeShardKvStore as v}from"./createNodeShardKvStore-DVi1OsvH.mjs";import{createNodeShardHost as w}from"./createNodeShardHost-Da19DFX0.mjs";import{createNodeSocketHost as A}from"./createNodeSocketHost-DQs85G7W.mjs";const c=".sqlite3",f=r=>r.replaceAll(/[^\da-z._-]/gu,t=>[...Buffer.from(t,"utf8")].map(o=>`%${o.toString(16).padStart(2,"0").toUpperCase()}`).join("")),g=r=>decodeURIComponent(r),$=(r,t)=>{const o=t.slice(0,-c.length),d=h(r,t);let a;try{a=g(o)}catch{throw new l("SHARD_UNAVAILABLE",`@lunora/platform-node: shard database "${d}" has a basename that is not valid percent-encoding, so the shard key it holds cannot be recovered. Rename or remove the file.`)}const e=`${f(a)}${c}`;if(e!==t)throw new l("SHARD_UNAVAILABLE",`@lunora/platform-node: shard database "${d}" was written under an older shard-key encoding. It decodes to shard key "${a}", which this build stores as "${e}" — so the key would be listed for fan-out while every read opened a new, empty database. Rename it: mv "${d}" "${h(r,e)}"`);return a},I=(r={})=>{const t=new Map,o=new Set;if(r.directory!==void 0){y(r.directory,{recursive:!0});for(const e of S(r.directory))e.endsWith(c)&&o.add($(r.directory,e))}const d=e=>{const s=t.get(e);if(s!==void 0)return s.shard;const i=r.directory===void 0?void 0:h(r.directory,`${f(e)}${c}`);let n;const{database:m,dispose:u,host:p}=w({onAlarm:()=>r.onAlarm?.(n),path:i,shardKey:e});return n={kv:v(m),shard:p,shardKey:e,sockets:A(m).socket},t.set(e,{dispose:u,shard:n}),o.add(e),n},a=e=>({fetch:async s=>{const i=d(e);return r.onFetch===void 0?new Response(e):r.onFetch(s,i)}});return{close:()=>{for(const e of t.values())e.dispose();t.clear()},directory:{get:e=>a(String(e)),getByName:e=>a(e),idForName:e=>e},listShardKeys:()=>[...o],shardFor:d}};export{I as createNodeShardRegistry};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{LunoraError as l}from"@lunora/errors";import{isWorkflowDefinition as N,workflowDefaultName as T,createWorkflowRunContext as D,workflowBindingName as _}from"@lunora/workflow";import{defineWorkflow as b,createRuntime as M}from"@visulima/workflow";const v="@lunora/platform-node:terminated",O={d:864e5,day:864e5,days:864e5,h:36e5,hour:36e5,hours:36e5,m:6e4,millisecond:1,milliseconds:1,minute:6e4,minutes:6e4,ms:1,s:1e3,second:1e3,seconds:1e3,w:6048e5,week:6048e5,weeks:6048e5,month:2592e6,months:2592e6},$=/^(\d+(?:\.\d+)?)\s*([a-z]+)$/i,E=n=>{if(typeof n=="number"){if(!Number.isFinite(n))throw new l("VALIDATION_ERROR",`@lunora/platform-node: workflow duration must be finite, got ${String(n)}`);return Math.max(0,n)}const i=$.exec(n.trim());if(i===null)throw new l("VALIDATION_ERROR",`@lunora/platform-node: unsupported workflow duration "${n}"`);const o=Number(i[1]),r=(i[2]??"").toLowerCase(),s=O[r];if(s===void 0)throw new l("VALIDATION_ERROR",`@lunora/platform-node: unsupported workflow duration "${n}"`);const c=o*s;if(!Number.isFinite(c))throw new l("VALIDATION_ERROR",`@lunora/platform-node: workflow duration "${n}" overflows`);return Math.max(0,c)},R="@lunora/platform-node:alias",A=(n,i,o)=>({attempt:i,config:o,step:{count:1,name:n}}),L={retries:{limit:1}},S=2147483647,F=async n=>new Promise(i=>{setTimeout(i,Math.min(n,S))}),x=(n,i,o)=>{switch(i){case"exponential":return n*2**(o-1);case"linear":return n*o;default:return n}},U=async(n,i)=>{const o=i instanceof Error?i:new Error(String(i));for(const r of n.splice(0).toSorted((s,c)=>c.order-s.order))try{await r.handler({ctx:r.context,error:o,output:r.output,stepName:r.name})}catch{}},V=n=>{switch(n){case"completed":return"complete";case"failed":return"errored";default:return"waiting"}},P=n=>{const i=[];let o=0;return{do:async(r,s,c,y)=>{const w=o;o+=1;const m=typeof s!="function",I=m?c:s,h=m?y:c;if(typeof I!="function")throw new l("VALIDATION_ERROR",`@lunora/platform-node: step.do("${r}") requires a callback`);const f=m?s:L,t=f.retries?.limit??1;if(!Number.isFinite(t))throw new l("VALIDATION_ERROR",`@lunora/platform-node: step.do("${r}") retries.limit must be a finite number, got ${String(t)}`);const e=Math.max(1,Math.trunc(t)),a=f.retries?.delay===void 0?0:E(f.retries.delay);let u=A(r,1,f);try{const d=await n.step(r,async()=>{for(let p=1;;p+=1){u=A(r,p,f);try{return await I(u)}catch(k){if(p>=e)throw k;const g=x(a,f.retries?.backoff,p);g>0&&await F(g)}}});return h?.rollback!==void 0&&i.push({context:u,handler:h.rollback,name:r,order:w,output:d}),d}catch(d){throw h?.rollback!==void 0&&i.push({context:u,handler:h.rollback,name:r,order:w,output:void 0}),await U(i,d),d}},sleep:async(r,s)=>{const c=E(s);c!==0&&await n.sleep(r,c)},sleepUntil:async(r,s)=>{const c=typeof s=="number"?s:s.getTime();if(!Number.isFinite(c))throw new l("VALIDATION_ERROR",`@lunora/platform-node: step.sleepUntil("${r}") needs a valid timestamp`);const y=Math.max(0,c-Date.now());y!==0&&await n.sleep(r,y)},waitForEvent:(async(r,s)=>({payload:await n.waitForEvent(r,s.type,{timeout:s.timeout===void 0?void 0:E(s.timeout)}),type:s.type}))}},j=n=>{const i=Object.entries(n.workflows).map(([t,e])=>{if(!N(e))throw new l("VALIDATION_ERROR",`@lunora/platform-node: "${t}" is not a defineWorkflow result`);return{definition:e,exportName:t,id:e.name??T(t)}}),{store:o}=n,r={...n.env},s=i.map(({definition:t,exportName:e,id:a})=>b({id:a,tags:[e],run:async u=>{const d=P(u),p=D({env:r,event:{instanceId:u.runId,payload:u.payload,timestamp:new Date,workflowName:a},exportName:e,step:d});return await t.handler(p)}})),c=new Set,y={acquire:o.acquire===void 0?void 0:async(t,e,a)=>o.acquire?.(t,e,a)??!1,delete:async t=>o.delete(t),due:async(t,e)=>o.due(t,e),load:async t=>{const e=await o.load(t);return e===void 0||e.definitionId===v||e.definitionId===R?void 0:e},release:o.release===void 0?void 0:async(t,e)=>o.release?.(t,e),save:async t=>{c.has(t.runId)||await o.save(t)}},w=M({leaseTtlMs:n.leaseTtlMs,store:y,workflows:s}),m=t=>({id:t,pause:()=>Promise.reject(new l("NOT_IMPLEMENTED",`@lunora/platform-node: workflow instance "${t}" cannot be paused — the visulima engine has no pause equivalent`)),restart:()=>Promise.reject(new l("NOT_IMPLEMENTED",`@lunora/platform-node: workflow instance "${t}" cannot be restarted — the visulima engine has no restart equivalent`)),resume:async()=>{if((await o.load(t))?.definitionId===v)throw new l("BAD_REQUEST",`@lunora/platform-node: workflow instance "${t}" was terminated and cannot be resumed`);await w.resume(t)},sendEvent:async e=>{const a=await w.getRun(t);if(a?.status!=="waiting"||a.pending?.kind!=="event"||a.pending.eventName!==e.type)throw new l("BAD_REQUEST",`@lunora/platform-node: workflow instance "${t}" is not waiting for event "${e.type}"`);await w.signal(t,e.type,e.payload)},status:async()=>{const e=await o.load(t);if(e===void 0)return{status:"unknown"};if(e.definitionId===v)return{status:"terminated"};const a=await w.getRun(t);return a===void 0?{status:"unknown"}:{error:a.error===void 0?void 0:{message:a.error.message,name:a.error.name},output:a.output,status:V(a.status)}},terminate:async()=>{await o.load(t)!==void 0&&(c.add(t),await o.delete(t),await o.save({definitionId:v,runId:t,snapshot:void 0,status:"failed",updatedAt:Date.now()}))}}),I=async t=>{const e=await o.load(t);return e?.definitionId===R?e.snapshot:t},h=async(t,e)=>{if(e?.id===void 0){const d=await w.trigger(t,e?.params);return m(d.runId)}const a=await o.load(e.id);if(a?.definitionId===R)return m(a.snapshot);if(a!==void 0)throw new l("BAD_REQUEST",`@lunora/platform-node: workflow create({ id: "${e.id}" }) names an existing run — pass the id a previous create returned, or a fresh one`);const u=await w.trigger(t,e.params);return await o.save({definitionId:R,runId:e.id,snapshot:u.runId,status:"failed",updatedAt:Date.now()}),m(u.runId)},f={};for(const{exportName:t,id:e}of i){const a={create:async u=>h(e,u),createBatch:async u=>{const d=[];for(const p of u)d.push(await h(e,p));return d},get:async u=>m(await I(u))};f[t]=a,r[_(t)]=a}return{bindings:f,env:r,runtime:w}};export{j as createNodeWorkflowHost};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/platform-node",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.68",
|
|
4
4
|
"description": "Node implementation of the Lunora platform contracts: ShardHost, SocketHost, ShardDirectory, ShardKvStore, SchedulerHost over better-sqlite3 and an in-process socket registry (dev/test target)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"better-sqlite3",
|
|
@@ -46,12 +46,12 @@
|
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@lunora/d1": "1.0.0-alpha.
|
|
50
|
-
"@lunora/errors": "1.0.0-alpha.
|
|
51
|
-
"@lunora/platform": "1.0.0-alpha.
|
|
52
|
-
"@lunora/queue": "1.0.0-alpha.
|
|
53
|
-
"@lunora/sql-store": "1.0.0-alpha.
|
|
54
|
-
"@lunora/workflow": "1.0.0-alpha.
|
|
49
|
+
"@lunora/d1": "1.0.0-alpha.117",
|
|
50
|
+
"@lunora/errors": "1.0.0-alpha.36",
|
|
51
|
+
"@lunora/platform": "1.0.0-alpha.31",
|
|
52
|
+
"@lunora/queue": "1.0.0-alpha.55",
|
|
53
|
+
"@lunora/sql-store": "1.0.0-alpha.118",
|
|
54
|
+
"@lunora/workflow": "1.0.0-alpha.52",
|
|
55
55
|
"@visulima/workflow": "3.0.0",
|
|
56
56
|
"better-sqlite3": "^13.0.3",
|
|
57
57
|
"cron-parser": "5.10.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{AsyncLocalStorage as y}from"node:async_hooks";import{LunoraError as v}from"@lunora/errors";import L from"better-sqlite3";const S=2147483647,R=6,O=100,I=e=>e===void 0?null:e,M=(e,t)=>({get databaseSize(){const c=e.pragma("page_count",{simple:!0}),r=e.pragma("page_size",{simple:!0});return c*r},exec:(c,...r)=>{t("run SQL");const a=e.prepare(c),s=r.map(d=>I(d)),o=a.reader?a.all(...s):(a.run(...s),[]);return{[Symbol.iterator]:()=>o[Symbol.iterator](),one:()=>{if(o.length!==1)throw new Error(`expected exactly one row, got ${String(o.length)}`);return o[0]},toArray:()=>[...o]}}}),N=(e,t,c)=>{let r,a,s=0,o;e.exec("CREATE TABLE IF NOT EXISTS _lunora_alarm (id INTEGER PRIMARY KEY CHECK (id = 0), scheduled_for INTEGER NOT NULL)");const d=n=>{n===void 0?e.prepare("DELETE FROM _lunora_alarm WHERE id = 0").run():e.prepare("INSERT INTO _lunora_alarm (id, scheduled_for) VALUES (0, ?) ON CONFLICT (id) DO UPDATE SET scheduled_for = excluded.scheduled_for").run(n)},p=()=>{a!==void 0&&(clearTimeout(a),a=void 0)},m=n=>{p();const l=Math.max(0,n-Date.now());if(l>S){a=setTimeout(()=>{m(n)},S);return}a=setTimeout(()=>{r=void 0,a=void 0,e.open&&(d(void 0),(async()=>{await c?.(),s=0})().catch(()=>{if(!e.open||r!==void 0)return;if(s+=1,s>R){s=0;return}const h=Date.now()+O*2**(s-1);r=h,d(h),m(h)}))},l)},f={delete:()=>{if(!e.open)throw new Error("platform closed: cannot delete an alarm");if(t.assertOwnTurn("delete an alarm"),s=0,d(void 0),t.inside()){o={at:void 0};return}r=void 0,p()},get:()=>(o===void 0?r:o.at)??null,set:n=>{if(!e.open)throw new Error("platform closed: cannot set an alarm");t.assertOwnTurn("set an alarm");const l=typeof n=="number"?n:n.getTime();if(s=0,d(l),t.inside()){o={at:l};return}r=l,m(l)}},w=()=>{if(o===void 0)return;const{at:n}=o;if(o=void 0,n===void 0){r=void 0,p();return}r=n,m(n)},T=()=>{o=void 0},E=e.prepare("SELECT scheduled_for FROM _lunora_alarm WHERE id = 0").get();return E!==void 0&&(r=E.scheduled_for,m(E.scheduled_for)),{alarms:f,commit:w,dispose:p,rollback:T}},k=(e={})=>{const t=new L(e.path??":memory:");t.pragma("journal_mode = WAL");const c=new y;let r=!1;const a=i=>{if(r&&c.getStore()!==!0)throw new v("SHARD_UNAVAILABLE",`shard busy: cannot ${i} while another task holds this shard's transaction`)},s=M(t,a),{alarms:o,commit:d,dispose:p,rollback:m}=N(t,{assertOwnTurn:a,inside:()=>c.getStore()===!0},e.onAlarm),f=new Set,w=new y;let T=Promise.resolve();const E=async i=>{if(w.getStore()===!0)return await i();const u=T;let A=()=>{};T=new Promise(g=>{A=g}),await u;try{return await w.run(!0,i)}finally{A()}},n=i=>E(i),l=async i=>{t.exec("BEGIN"),r=!0;try{const u=await c.run(!0,i);return t.exec("COMMIT"),r=!1,d(),u}catch(u){r=!1,m();try{t.exec("ROLLBACK")}catch{}throw u}},h=i=>E(async()=>l(i)),_={alarms:o,runSerialized:n,shardKey:e.shardKey,sql:s,transaction:h,waitUntil:i=>{const u=i.catch(()=>{}).finally(()=>{f.delete(u)});f.add(u)}};return{database:t,dispose:()=>{p(),t.open&&t.close()},drain:async()=>{for(;f.size>0;)await Promise.all(f)},host:_}};export{k as createNodeShardHost};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{LunoraError as u}from"@lunora/errors";import{isWorkflowDefinition as E,workflowDefaultName as k,createWorkflowRunContext as A,workflowBindingName as N}from"@lunora/workflow";import{defineWorkflow as D,createRuntime as T}from"@visulima/workflow";const m="@lunora/platform-node:terminated",_={d:864e5,day:864e5,days:864e5,h:36e5,hour:36e5,hours:36e5,m:6e4,millisecond:1,milliseconds:1,minute:6e4,minutes:6e4,ms:1,s:1e3,second:1e3,seconds:1e3,w:6048e5,week:6048e5,weeks:6048e5,month:2592e6,months:2592e6},O=/^(\d+(?:\.\d+)?)\s*([a-z]+)$/i,v=o=>{if(typeof o=="number"){if(!Number.isFinite(o))throw new u("VALIDATION_ERROR",`@lunora/platform-node: workflow duration must be finite, got ${String(o)}`);return Math.max(0,o)}const r=O.exec(o.trim());if(r===null)throw new u("VALIDATION_ERROR",`@lunora/platform-node: unsupported workflow duration "${o}"`);const n=Number(r[1]),s=(r[2]??"").toLowerCase(),d=_[s];if(d===void 0)throw new u("VALIDATION_ERROR",`@lunora/platform-node: unsupported workflow duration "${o}"`);const l=n*d;if(!Number.isFinite(l))throw new u("VALIDATION_ERROR",`@lunora/platform-node: workflow duration "${o}" overflows`);return Math.max(0,l)},p="@lunora/platform-node:alias",b=o=>({attempt:1,config:{retries:{limit:1}},step:{count:1,name:o}}),$=o=>{switch(o){case"completed":return"complete";case"failed":return"errored";default:return"waiting"}},L=o=>({do:(async(r,n,s,d)=>{const l=typeof n=="function"?n:s;if(typeof l!="function")throw new u("VALIDATION_ERROR",`@lunora/platform-node: step.do("${r}") requires a callback`);return o.step(r,async()=>l(b(r)))}),sleep:async(r,n)=>{const s=v(n);s!==0&&await o.sleep(r,s)},sleepUntil:async(r,n)=>{const s=typeof n=="number"?n:n.getTime();if(!Number.isFinite(s))throw new u("VALIDATION_ERROR",`@lunora/platform-node: step.sleepUntil("${r}") needs a valid timestamp`);const d=Math.max(0,s-Date.now());d!==0&&await o.sleep(r,d)},waitForEvent:(async(r,n)=>({payload:await o.waitForEvent(r,n.type,{timeout:n.timeout===void 0?void 0:v(n.timeout)}),type:n.type}))}),U=o=>{const r=Object.entries(o.workflows).map(([e,t])=>{if(!E(t))throw new u("VALIDATION_ERROR",`@lunora/platform-node: "${e}" is not a defineWorkflow result`);return{definition:t,exportName:e,id:t.name??k(e)}}),{store:n}=o,s={...o.env},d=r.map(({definition:e,exportName:t,id:a})=>D({id:a,tags:[t],run:async i=>{const w=L(i),I=A({env:s,event:{instanceId:i.runId,payload:i.payload,timestamp:new Date,workflowName:a},exportName:t,step:w});return await e.handler(I)}})),l=new Set,R={acquire:n.acquire===void 0?void 0:async(e,t,a)=>n.acquire?.(e,t,a)??!1,delete:async e=>n.delete(e),due:async(e,t)=>n.due(e,t),load:async e=>{const t=await n.load(e);return t===void 0||t.definitionId===m||t.definitionId===p?void 0:t},release:n.release===void 0?void 0:async(e,t)=>n.release?.(e,t),save:async e=>{l.has(e.runId)||await n.save(e)}},c=T({leaseTtlMs:o.leaseTtlMs,store:R,workflows:d}),f=e=>({id:e,pause:()=>Promise.reject(new u("NOT_IMPLEMENTED",`@lunora/platform-node: workflow instance "${e}" cannot be paused — the visulima engine has no pause equivalent`)),restart:()=>Promise.reject(new u("NOT_IMPLEMENTED",`@lunora/platform-node: workflow instance "${e}" cannot be restarted — the visulima engine has no restart equivalent`)),resume:async()=>{if((await n.load(e))?.definitionId===m)throw new u("BAD_REQUEST",`@lunora/platform-node: workflow instance "${e}" was terminated and cannot be resumed`);await c.resume(e)},sendEvent:async t=>{const a=await c.getRun(e);if(a?.status!=="waiting"||a.pending?.kind!=="event"||a.pending.eventName!==t.type)throw new u("BAD_REQUEST",`@lunora/platform-node: workflow instance "${e}" is not waiting for event "${t.type}"`);await c.signal(e,t.type,t.payload)},status:async()=>{const t=await n.load(e);if(t===void 0)return{status:"unknown"};if(t.definitionId===m)return{status:"terminated"};const a=await c.getRun(e);return a===void 0?{status:"unknown"}:{error:a.error===void 0?void 0:{message:a.error.message,name:a.error.name},output:a.output,status:$(a.status)}},terminate:async()=>{await n.load(e)!==void 0&&(l.add(e),await n.delete(e),await n.save({definitionId:m,runId:e,snapshot:void 0,status:"failed",updatedAt:Date.now()}))}}),g=async e=>{const t=await n.load(e);return t?.definitionId===p?t.snapshot:e},y=async(e,t)=>{if(t?.id===void 0){const w=await c.trigger(e,t?.params);return f(w.runId)}const a=await n.load(t.id);if(a?.definitionId===p)return f(a.snapshot);if(a!==void 0)throw new u("BAD_REQUEST",`@lunora/platform-node: workflow create({ id: "${t.id}" }) names an existing run — pass the id a previous create returned, or a fresh one`);const i=await c.trigger(e,t.params);return await n.save({definitionId:p,runId:t.id,snapshot:i.runId,status:"failed",updatedAt:Date.now()}),f(i.runId)},h={};for(const{exportName:e,id:t}of r){const a={create:async i=>y(t,i),createBatch:async i=>{const w=[];for(const I of i)w.push(await y(t,I));return w},get:async i=>f(await g(i))};h[e]=a,s[N(e)]=a}return{bindings:h,env:s,runtime:c}};export{U as createNodeWorkflowHost};
|