@rango-dev/queue-manager-core 0.14.0 → 0.15.1-next.0

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.js CHANGED
@@ -1,2 +1,2 @@
1
- var x=Object.defineProperty;var r=(c,t)=>x(c,"name",{value:t,configurable:!0});var f="queues-manager",o="queues",E=1,d=class{constructor(){this.db=import("idb").then(t=>t.openDB(f,E,{upgrade(e){e.createObjectStore(o,{keyPath:"id"})}})).catch(()=>{throw new Error("Couldn't load idb.")})}async insertQueue(t){let e=await this.db;await e.get(o,t.id)||await e.add(o,t)}async updateQueue(t,e){let s=await this.db,a=await s.get(o,t);if(!a)return;let n={...a,...e};await s.put(o,n)}async getAll(){return await(await this.db).getAll(o)}};r(d,"Persistor");var l=d;import{v4 as Q}from"uuid";var p=(i=>(i.PENDING="PENDING",i.RUNNING="RUNNING",i.FAILED="FAILED",i.SUCCESS="SUCCESS",i.CANCELED="CANCELED",i.BLOCKED="BLOCKED",i))(p||{}),S=5e3;var h=class{constructor(t){this.state={status:"PENDING",activeTaskIndex:0,tasks:{}};this.tasks=[];this.storage={};this.id=t.id,this.events=t.events,this.actions=t.actions}updateQueueStatus(t){this.state.status=t,this.events.onUpdateListStatus(t)}updateActiveTaskIndex(t){this.state.activeTaskIndex=t}updateTaskState(t,e){e.status&&(this.state.tasks[t].status=e.status),e.blockedFor&&(this.state.tasks[t].blockedFor=e.blockedFor);let s={id:t,task:this.get(t),action:this.tasks.find(a=>a.id===t).action};this.events.onUpdate(s)}createTask(t){let e=Q();this.tasks.push({action:t,id:e}),this.state.tasks[e]={status:"PENDING",blockedFor:null};let s=this.get(e);this.events.onCreate({id:e,task:s,action:t})}initTasks(t){this.state=t.state,this.storage=t.storage,t.tasks.forEach(e=>{this.tasks.push(e);let s=this.tasks.find(a=>a.id===e.id).action;this.events.onCreate({id:e.id,task:this.get(e.id),action:s})})}checkBlock(){let t=this.getActiveTask();if(!t)return;let{task:e,state:s}=t;s.status==="BLOCKED"&&this.events.onBlock({action:e.action,id:e.id,reason:s.blockedFor})}get(t){let e=this.state.tasks[t];return e||null}lastTaskIsSuccessful(){let t=this.tasks[this.tasks.length-1];if(t){let e=this.state.tasks[t.id];if(e&&e.status==="SUCCESS")return!0}return!1}firstTaskIsStarted(){let t=this.tasks[0];if(t){let e=this.state.tasks[t.id];if(e&&e.status!=="PENDING")return!0}return!1}getActiveTask(){let t=this.state.activeTaskIndex,e=this.tasks[t];if(!e)return null;let s=this.state.tasks[e.id];return{task:e,state:s,index:t}}check(){let t=this.state.status,e=this.firstTaskIsStarted()?"RUNNING":"PENDING";if(this.lastTaskIsSuccessful())e="SUCCESS";else for(let s of this.tasks)if(this.state.tasks[s.id].status==="FAILED"){e="FAILED";break}e!==t&&this.updateQueueStatus(e)}next(t){this.check();let e=this.getActiveTask();if(!e)return;let{index:s,task:a,state:n}=e;if(n.status==="SUCCESS"){this.updateActiveTaskIndex(s+1),this.next(t);return}if(!["FAILED","CANCELED","RUNNING"].includes(n.status)&&(n.status==="PENDING"||n.status==="BLOCKED")){this.updateTaskState(a.id,{status:"RUNNING"}),this.updateQueueStatus("RUNNING");let i=this.actions[a.action];i({context:this.getContext(t),next:()=>{this.markCurrentTaskAsFinished(t)},retry:()=>{this.resume(t)},failed:()=>{this.updateTaskState(a.id,{status:"FAILED"}),this.check()},schedule:u=>{this.createTask(u),this.check()},getStorage:this.getStorage.bind(this),setStorage:this.setStorage.bind(this),block:u=>{this.block({reason:u})},unblock:()=>{this.unblock()}})}}block({reason:t,silent:e=!1}){let s=this.getActiveTask();if(!s)throw new Error("Task isn't exist.");this.updateTaskState(s.task.id,{status:"BLOCKED",blockedFor:t}),this.updateQueueStatus("BLOCKED"),e||this.events.onBlock({action:s.task.action,id:s.task.id,reason:t})}unblock(){let t=this.getActiveTask();if(!t||t.state.status!=="BLOCKED")throw new Error("Task is not blocked.");this.updateTaskState(t.task.id,{status:"PENDING"}),this.updateQueueStatus("RUNNING"),this.events.onUnblock({id:t.task.id})}forceRun(t){let e=this.getActiveTask();if(!e||e.state.status!=="BLOCKED")throw new Error("Task is not blocked.");let s=this.actions[e.task.action];s({context:this.getContext(t),next:()=>{this.updateTaskState(e.task.id,{status:"RUNNING"}),this.updateQueueStatus("RUNNING"),this.markCurrentTaskAsFinished(t)},retry:()=>{this.resume(t)},failed:()=>{this.updateTaskState(e.task.id,{status:"FAILED"}),this.check()},schedule:a=>{this.createTask(a),this.check()},getStorage:this.getStorage.bind(this),setStorage:this.setStorage.bind(this),block:a=>{this.block({reason:a})},unblock:()=>{this.unblock()}})}markCurrentTaskAsFinished(t){this.check();let e=this.state.activeTaskIndex,s=this.tasks[e];if(!s)return;if(this.state.tasks[s.id].status==="RUNNING"){this.updateTaskState(s.id,{status:"SUCCESS"}),this.updateActiveTaskIndex(e+1);let n={id:s.id,task:this.get(s.id),action:this.tasks.find(i=>i.id===s.id).action};this.events.onUpdate(n),this.next(t)}}resume(t){let e=this.state.activeTaskIndex,s=this.tasks[e];if(!s)return;this.state.tasks[s.id].status==="RUNNING"?(this.updateTaskState(s.id,{status:"PENDING"}),this.next(t)):(this.resetState(),this.next(t))}cancel(){let t=this.getActiveTask();if(!t||["FAILED","CANCELED","SUCCESS"].includes(t.state.status))return;let{task:e}=t;this.updateTaskState(e.id,{status:"CANCELED"});let s={id:e.id,task:this.get(e.id),action:this.tasks.find(a=>a.id===e.id).action};this.events.onUpdate(s),this.updateQueueStatus("CANCELED")}resetState(){this.state.activeTaskIndex=0,this.state.status="PENDING",Object.keys(this.state.tasks).forEach(t=>{this.state.tasks[t].status="PENDING"})}getStorage(){return this.storage}setStorage(t){return this.storage=t,this.events.onStorageUpdate(t),this.storage}getContext(t){return{...t.context,_queue:{id:this.id}}}};r(h,"Queue");var T=h;import{v4 as I}from"uuid";var g=class{constructor(t){this.queuesDefs=new Map;this.queues=new Map;this.isPaused=!1;this.syncInterval=null;let e={onCreateQueue:()=>{},onCreateTask:()=>{},onUpdateQueue:()=>{},onUpdateTask:()=>{},onStorageUpdate:()=>{},onTaskBlock:()=>{},onPersistedDataLoaded:()=>{}};t.events?this.events={...e,...t.events}:this.events=e,t.queuesDefs.map(s=>{this.queuesDefs.set(s.name,s)}),this.context=t.context||{},this.persistor=new l,this.sync(),t.isPaused&&this.pause()}async sync(){try{let t=await this.persistor.getAll();this.queues=new Map,t.forEach(e=>{let s=this.createQueue({queue_id:e.id,queue_name:e.name});this.add(e.id,{list:s,createdAt:e.createdAt,name:e.name,status:e.status,actions:{run:()=>{s.next({context:this.getContext()})},cancel:()=>{s.cancel()},setStorage:(...a)=>{s.setStorage(...a)},getStorage:()=>s.getStorage()}}),s.initTasks({state:e.state,tasks:e.tasks,storage:e.storage||{}}),e.status==="RUNNING"&&this.shouldExecute()&&s.resume({context:this.getContext()})})}catch(t){console.log(`IndexDB Error: ${t}`)}this.events.onPersistedDataLoaded(this)}createQueue({queue_id:t,queue_name:e}){let s=this,a=this.queuesDefs.get(e),n=new T({id:t,events:{onCreate:i=>{this.events.onCreateTask(t,i),this.handleUpdate(t),a.events?.onCreate&&a.events.onCreate(i)},onUpdate:i=>{this.events.onUpdateTask(t,i),this.handleUpdate(t),a.events?.onUpdate&&a.events.onUpdate(i)},onUpdateListStatus:i=>{this.queues.set(t,{...this.get(t),status:i}),this.events.onUpdateQueue(t,this.get(t)),this.handleUpdate(t),this.execute(),a.events?.onUpdateListStatus&&a.events.onUpdateListStatus(i)},onStorageUpdate:i=>{this.events.onStorageUpdate(t,i),a.events?.onStorageUpdate&&a.events.onStorageUpdate(i),this.handleUpdate(t)},onBlock:i=>{this.queues.set(t,{...this.get(t),status:"BLOCKED"}),this.events.onTaskBlock(t),a.whenTaskBlocked&&a.whenTaskBlocked(i,{queue_id:t,queue:n,context:this.getContext(),getBlockedTasks:this.getBlockedTasks.bind(this),forceExecute:this.forceExecute.bind(this),retry:this.retry.bind(this),manager:s}),this.handleUpdate(t)},onUnblock:()=>{this.queues.set(t,{...this.get(t),status:"PENDING"}),this.handleUpdate(t),this.execute()}},actions:a.actions});return n}getBlockedTasks(){let t=this.getAll(),e=[];return t.forEach((s,a)=>{s.list.tasks.forEach(n=>{let i=s.list.state.tasks[n.id];i.status==="BLOCKED"&&e.push({task_id:n.id,queue_id:a,action:n.action,reason:i.blockedFor,storage:{get:()=>s.list.getStorage(),set:u=>s.list.setStorage(u)}})})}),e}add(t,e){this.queues.set(t,e);let s=this.get(t);return this.events.onCreateQueue({...s,id:t}),s}async create(t,e,s){if(!this.queuesDefs.has(t))throw new Error("You need to add a queue definition first.");try{let a=this.queuesDefs.get(t),n=s?.id||I(),i=Date.now(),u=this.createQueue({queue_id:n,queue_name:t});u.setStorage(e);let v=this.add(n,{list:u,createdAt:i,name:t,status:"PENDING",actions:{run:()=>{u.next({context:this.getContext()})},cancel:()=>{u.cancel()},setStorage:(...k)=>{u.setStorage(...k)},getStorage:()=>u.getStorage()}});return await this.persistor.insertQueue({id:n,createdAt:i,name:v.name,status:v.status,tasks:u.tasks,state:u.state,storage:u.getStorage()}),a.run.forEach(k=>{u.createTask(k)}),this.execute(),n}catch(a){throw new Error(a?.message)}}get(t){return this.queues.get(t)}getAll(){return this.queues}execute(){if(this.shouldExecute())for(let[,t]of Array.from(this.queues))t.status==="PENDING"&&t.actions.run()}resume(){if(this.shouldExecute()){for(let[,t]of Array.from(this.queues))if(t.status==="RUNNING"){t.list.resume({context:this.getContext()});return}this.execute()}}retry(){if(this.shouldExecute()){for(let[,t]of Array.from(this.queues))t.status==="BLOCKED"&&t.list.checkBlock();this.execute()}}forceExecute(t,e){let s=this.get(t),a=this.getContext();e&&(a={...a,...e}),s?.list.forceRun({context:a})}handleUpdate(t){let e=this.get(t);if(e){let s=e.status,a=e.list.state,n=e.list.tasks;this.persistor.updateQueue(t,{status:s,state:a,tasks:n,storage:e.list.getStorage()})}}pause(){this.isPaused||(this.isPaused=!0,this.syncInterval=setInterval(()=>{this.sync()},S))}run(){this.isPaused&&(this.isPaused=!1,this.syncInterval&&(clearInterval(this.syncInterval),this.syncInterval=null),this.sync())}getContext(){return this.context?.current||{}}shouldExecute(){return!this.isPaused}};r(g,"Manager");export{f as DB_NAME,g as Manager,l as Persistor,S as SYNC_POLLING_INTERVAL,p as Status};
1
+ var x=Object.defineProperty;var o=(c,t)=>x(c,"name",{value:t,configurable:!0});import{v4 as E}from"uuid";var f="queues-manager",r="queues";var d=class{constructor(){this.db=import("idb").then(async t=>t.openDB(f,1,{upgrade(e){e.createObjectStore(r,{keyPath:"id"})}})).catch(()=>{throw new Error("Couldn't load idb.")})}async insertQueue(t){let e=await this.db;await e.get(r,t.id)||await e.add(r,t)}async updateQueue(t,e){let s=await this.db,a=await s.get(r,t);if(!a)return;let i={...a,...e};await s.put(r,i)}async getAll(){return await(await this.db).getAll(r)}async deleteQueue(t){let e=await this.db;await e.get(r,t)&&await e.delete(r,t)}};o(d,"Persistor");var l=d;import{v4 as Q}from"uuid";var p=(n=>(n.PENDING="PENDING",n.RUNNING="RUNNING",n.FAILED="FAILED",n.SUCCESS="SUCCESS",n.CANCELED="CANCELED",n.BLOCKED="BLOCKED",n))(p||{}),S=5e3;var h=class{constructor(t){this.state={status:"PENDING",activeTaskIndex:0,tasks:{}};this.tasks=[];this.storage={};this.id=t.id,this.events=t.events,this.actions=t.actions}updateQueueStatus(t){this.state.status=t,this.events.onUpdateListStatus(t)}updateActiveTaskIndex(t){this.state.activeTaskIndex=t}updateTaskState(t,e){e.status&&(this.state.tasks[t].status=e.status),e.blockedFor&&(this.state.tasks[t].blockedFor=e.blockedFor);let s={id:t,task:this.get(t),action:this.tasks.find(a=>a.id===t).action};this.events.onUpdate(s)}createTask(t){let e=Q();this.tasks.push({action:t,id:e}),this.state.tasks[e]={status:"PENDING",blockedFor:null};let s=this.get(e);this.events.onCreate({id:e,task:s,action:t})}initTasks(t){this.state=t.state,this.storage=t.storage,t.tasks.forEach(e=>{this.tasks.push(e);let s=this.tasks.find(a=>a.id===e.id).action;this.events.onCreate({id:e.id,task:this.get(e.id),action:s})})}checkBlock(){let t=this.getActiveTask();if(!t)return;let{task:e,state:s}=t;s.status==="BLOCKED"&&this.events.onBlock({action:e.action,id:e.id,reason:s.blockedFor})}get(t){let e=this.state.tasks[t];return e||null}lastTaskIsSuccessful(){let t=this.tasks[this.tasks.length-1];if(t){let e=this.state.tasks[t.id];if(e&&e.status==="SUCCESS")return!0}return!1}firstTaskIsStarted(){let t=this.tasks[0];if(t){let e=this.state.tasks[t.id];if(e&&e.status!=="PENDING")return!0}return!1}getActiveTask(){let t=this.state.activeTaskIndex,e=this.tasks[t];if(!e)return null;let s=this.state.tasks[e.id];return{task:e,state:s,index:t}}check(){let t=this.state.status,e=this.firstTaskIsStarted()?"RUNNING":"PENDING";if(this.lastTaskIsSuccessful())e="SUCCESS";else for(let s of this.tasks)if(this.state.tasks[s.id].status==="FAILED"){e="FAILED";break}e!==t&&this.updateQueueStatus(e)}next(t){this.check();let e=this.getActiveTask();if(!e)return;let{index:s,task:a,state:i}=e;if(i.status==="SUCCESS"){this.updateActiveTaskIndex(s+1),this.next(t);return}if(!["FAILED","CANCELED","RUNNING"].includes(i.status)&&(i.status==="PENDING"||i.status==="BLOCKED")){this.updateTaskState(a.id,{status:"RUNNING"}),this.updateQueueStatus("RUNNING");let n=this.actions[a.action];n({context:this.getContext(t),next:()=>{this.markCurrentTaskAsFinished(t)},retry:()=>{this.resume(t)},failed:()=>{this.updateTaskState(a.id,{status:"FAILED"}),this.check()},schedule:u=>{this.createTask(u),this.check()},getStorage:this.getStorage.bind(this),setStorage:this.setStorage.bind(this),block:u=>{this.block({reason:u})},unblock:()=>{this.unblock()}})}}block({reason:t,silent:e=!1}){let s=this.getActiveTask();if(!s)throw new Error("Task isn't exist.");this.updateTaskState(s.task.id,{status:"BLOCKED",blockedFor:t}),this.updateQueueStatus("BLOCKED"),e||this.events.onBlock({action:s.task.action,id:s.task.id,reason:t})}unblock(){let t=this.getActiveTask();if(!t||t.state.status!=="BLOCKED")throw new Error("Task is not blocked.");this.updateTaskState(t.task.id,{status:"PENDING"}),this.updateQueueStatus("RUNNING"),this.events.onUnblock({id:t.task.id})}forceRun(t){let e=this.getActiveTask();if(!e||e.state.status!=="BLOCKED")throw new Error("Task is not blocked.");let s=this.actions[e.task.action];s({context:this.getContext(t),next:()=>{this.updateTaskState(e.task.id,{status:"RUNNING"}),this.updateQueueStatus("RUNNING"),this.markCurrentTaskAsFinished(t)},retry:()=>{this.resume(t)},failed:()=>{this.updateTaskState(e.task.id,{status:"FAILED"}),this.check()},schedule:a=>{this.createTask(a),this.check()},getStorage:this.getStorage.bind(this),setStorage:this.setStorage.bind(this),block:a=>{this.block({reason:a})},unblock:()=>{this.unblock()}})}markCurrentTaskAsFinished(t){this.check();let e=this.state.activeTaskIndex,s=this.tasks[e];if(!s)return;if(this.state.tasks[s.id].status==="RUNNING"){this.updateTaskState(s.id,{status:"SUCCESS"}),this.updateActiveTaskIndex(e+1);let i={id:s.id,task:this.get(s.id),action:this.tasks.find(n=>n.id===s.id).action};this.events.onUpdate(i),this.next(t)}}resume(t){let e=this.state.activeTaskIndex,s=this.tasks[e];if(!s)return;this.state.tasks[s.id].status==="RUNNING"?(this.updateTaskState(s.id,{status:"PENDING"}),this.next(t)):(this.resetState(),this.next(t))}cancel(){let t=this.getActiveTask();if(!t||["FAILED","CANCELED","SUCCESS"].includes(t.state.status))return;let{task:e}=t;this.updateTaskState(e.id,{status:"CANCELED"});let s={id:e.id,task:this.get(e.id),action:this.tasks.find(a=>a.id===e.id).action};this.events.onUpdate(s),this.updateQueueStatus("CANCELED")}resetState(){this.state.activeTaskIndex=0,this.state.status="PENDING",Object.keys(this.state.tasks).forEach(t=>{this.state.tasks[t].status="PENDING"})}getStorage(){return this.storage}setStorage(t){return this.storage=t,this.events.onStorageUpdate(t),this.storage}getContext(t){return{...t.context,_queue:{id:this.id}}}};o(h,"Queue");var T=h;var g=class{constructor(t){this.queuesDefs=new Map;this.queues=new Map;this.isPaused=!1;this.syncInterval=null;let e={onCreateQueue:()=>{},onCreateTask:()=>{},onUpdateQueue:()=>{},onUpdateTask:()=>{},onStorageUpdate:()=>{},onTaskBlock:()=>{},onPersistedDataLoaded:()=>{},onDeleteQueue:()=>{}};t.events?this.events={...e,...t.events}:this.events=e,t.queuesDefs.map(s=>{this.queuesDefs.set(s.name,s)}),this.context=t.context||{},this.persistor=new l,this.sync(),t.isPaused&&this.pause()}async create(t,e,s){if(!this.queuesDefs.has(t))throw new Error("You need to add a queue definition first.");try{let a=this.queuesDefs.get(t),i=s?.id||E(),n=Date.now(),u=this.createQueue({queue_id:i,queue_name:t});u.setStorage(e);let v=this.add(i,{list:u,createdAt:n,name:t,status:"PENDING",actions:{run:()=>{u.next({context:this.getContext()})},cancel:()=>{u.cancel()},setStorage:(...k)=>{u.setStorage(...k)},getStorage:()=>u.getStorage()}});return await this.persistor.insertQueue({id:i,createdAt:n,name:v.name,status:v.status,tasks:u.tasks,state:u.state,storage:u.getStorage()}),a.run.forEach(k=>{u.createTask(k)}),this.execute(),i}catch(a){throw new Error(a?.message)}}get(t){return this.queues.get(t)}getAll(){return this.queues}deleteQueue(t){this.queues.delete(t),this.persistor.deleteQueue(t)}execute(){if(this.shouldExecute())for(let[,t]of Array.from(this.queues))t.status==="PENDING"&&t.actions.run()}resume(){if(this.shouldExecute()){for(let[,t]of Array.from(this.queues))if(t.status==="RUNNING"){t.list.resume({context:this.getContext()});return}this.execute()}}retry(){if(this.shouldExecute()){for(let[,t]of Array.from(this.queues))t.status==="BLOCKED"&&t.list.checkBlock();this.execute()}}forceExecute(t,e){let s=this.get(t),a=this.getContext();e&&(a={...a,...e}),s?.list.forceRun({context:a})}pause(){this.isPaused||(this.isPaused=!0,this.syncInterval=setInterval(()=>{this.sync()},S))}run(){this.isPaused&&(this.isPaused=!1,this.syncInterval&&(clearInterval(this.syncInterval),this.syncInterval=null),this.sync())}async sync(){try{let t=await this.persistor.getAll();this.queues=new Map,t.forEach(e=>{let s=this.createQueue({queue_id:e.id,queue_name:e.name});this.add(e.id,{list:s,createdAt:e.createdAt,name:e.name,status:e.status,actions:{run:()=>{s.next({context:this.getContext()})},cancel:()=>{s.cancel()},setStorage:(...a)=>{s.setStorage(...a)},getStorage:()=>s.getStorage()}}),s.initTasks({state:e.state,tasks:e.tasks,storage:e.storage||{}}),e.status==="RUNNING"&&this.shouldExecute()&&s.resume({context:this.getContext()})})}catch(t){console.log(`IndexDB Error: ${t}`)}this.events.onPersistedDataLoaded(this)}createQueue(t){let{queue_id:e,queue_name:s}=t,a=this,i=this.queuesDefs.get(s),n=new T({id:e,events:{onCreate:u=>{this.events.onCreateTask(e,u),this.handleUpdate(e),i.events?.onCreate&&i.events.onCreate(u)},onUpdate:u=>{this.events.onUpdateTask(e,u),this.handleUpdate(e),i.events?.onUpdate&&i.events.onUpdate(u)},onUpdateListStatus:u=>{this.queues.set(e,{...this.get(e),status:u}),this.events.onUpdateQueue(e,this.get(e)),this.handleUpdate(e),this.execute(),i.events?.onUpdateListStatus&&i.events.onUpdateListStatus(u)},onStorageUpdate:u=>{this.events.onStorageUpdate(e,u),i.events?.onStorageUpdate&&i.events.onStorageUpdate(u),this.handleUpdate(e)},onBlock:u=>{this.queues.set(e,{...this.get(e),status:"BLOCKED"}),this.events.onTaskBlock(e),i.whenTaskBlocked&&i.whenTaskBlocked(u,{queue_id:e,queue:n,context:this.getContext(),getBlockedTasks:this.getBlockedTasks.bind(this),forceExecute:this.forceExecute.bind(this),retry:this.retry.bind(this),manager:a}),this.handleUpdate(e)},onUnblock:()=>{this.queues.set(e,{...this.get(e),status:"PENDING"}),this.handleUpdate(e),this.execute()}},actions:i.actions});return n}getBlockedTasks(){let t=this.getAll(),e=[];return t.forEach((s,a)=>{s.list.tasks.forEach(i=>{let n=s.list.state.tasks[i.id];n.status==="BLOCKED"&&e.push({task_id:i.id,queue_id:a,action:i.action,reason:n.blockedFor,storage:{get:()=>s.list.getStorage(),set:u=>s.list.setStorage(u)}})})}),e}add(t,e){this.queues.set(t,e);let s=this.get(t);return this.events.onCreateQueue({...s,id:t}),s}handleUpdate(t){let e=this.get(t);if(e){let s=e.status,a=e.list.state,i=e.list.tasks;this.persistor.updateQueue(t,{status:s,state:a,tasks:i,storage:e.list.getStorage()})}}getContext(){return this.context?.current||{}}shouldExecute(){return!this.isPaused}};o(g,"Manager");export{f as DB_NAME,g as Manager,l as Persistor,S as SYNC_POLLING_INTERVAL,p as Status};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/persistor.ts", "../src/queue.ts", "../src/types.ts", "../src/manager.ts"],
4
- "sourcesContent": ["import type { DBSchema, IDBPDatabase } from 'idb';\n\nimport { QueueID } from './manager';\nimport { PersistedQueue } from './types';\n\nexport const DB_NAME = 'queues-manager';\nconst OBJECT_STORE_NAME = 'queues';\nconst VERSION = 1;\n\ntype UpdatePersistedQueue = Partial<\n Pick<PersistedQueue, 'status' | 'state' | 'tasks' | 'storage'>\n>;\n\ninterface Database extends DBSchema {\n queues: {\n value: PersistedQueue;\n key: string;\n };\n}\n\nclass Persistor {\n db: Promise<IDBPDatabase<Database>>;\n constructor() {\n this.db = import('idb')\n .then((idb) => {\n return idb.openDB<Database>(DB_NAME, VERSION, {\n upgrade(db) {\n db.createObjectStore(OBJECT_STORE_NAME, { keyPath: 'id' });\n },\n });\n })\n .catch(() => {\n throw new Error(\"Couldn't load idb.\");\n });\n }\n\n async insertQueue(queue: PersistedQueue) {\n const db = await this.db;\n const queueRecord = await db.get(OBJECT_STORE_NAME, queue.id);\n if (queueRecord) {\n // Queue already exists inside persistor.\n } else {\n await db.add(OBJECT_STORE_NAME, queue);\n }\n }\n async updateQueue(id: QueueID, queue: UpdatePersistedQueue) {\n const db = await this.db;\n const currentRecord = await db.get(OBJECT_STORE_NAME, id);\n\n if (!currentRecord) return;\n\n const updatedRecord = {\n ...currentRecord,\n ...queue,\n };\n await db.put(OBJECT_STORE_NAME, updatedRecord);\n }\n async getAll() {\n const db = await this.db;\n const results = await db.getAll(OBJECT_STORE_NAME);\n\n return results;\n }\n}\n\nexport default Persistor;\n", "import { v4 as uuidv4 } from 'uuid';\nimport { ManagerContext, QueueDef, QueueID } from './manager';\nimport { QueueStorage, Status } from './types';\n\ntype TaskId = string;\nexport type TaskState = {\n status: Status;\n blockedFor: any;\n};\n\nexport interface QueueContext {\n _queue?: {\n id: string;\n };\n}\nexport type NextParams = {\n context: ManagerContext;\n};\n\nexport interface QueueState {\n status: Status;\n activeTaskIndex: number;\n tasks: {\n [key in TaskId]: TaskState;\n };\n}\n\nexport interface Task {\n id: TaskId;\n action: string;\n}\n\nexport type InitTasks = {\n tasks: Task[];\n state: QueueState;\n storage: QueueStorage;\n};\n\nexport interface TaskEvent {\n id: TaskId;\n task: TaskState;\n action: string;\n}\n\nexport interface QueueEventHandlers {\n // all tasks\n onUpdateListStatus: (status: Status) => void;\n // single task\n onCreate: (event: TaskEvent) => void;\n onUpdate: (event: TaskEvent) => void;\n onStorageUpdate: (data: QueueStorage) => void;\n onBlock: (\n data: Omit<TaskEvent, 'task'> & { reason: Record<string, unknown> }\n ) => void;\n onUnblock: (data: { id: string }) => void;\n}\n\ninterface QueueOptions {\n id: QueueID;\n events: QueueEventHandlers;\n actions: QueueDef['actions'];\n}\n\n/**\n *\n * Notes on statuses:\n * - Success: last task has success status\n * - Failed: any of task has been failed\n * - Running: first task is not on pending\n * - Pending: default state. not started\n *\n */\nclass Queue {\n public id: string;\n public state: QueueState = {\n status: Status.PENDING,\n activeTaskIndex: 0,\n tasks: {},\n };\n public tasks: Task[] = [];\n private events: QueueOptions['events'];\n private actions: QueueOptions['actions'];\n private storage: QueueStorage = {};\n\n constructor(options: QueueOptions) {\n this.id = options.id;\n this.events = options.events;\n this.actions = options.actions;\n }\n\n /**\n * Update queue status and trigger an event\n *\n */\n private updateQueueStatus(status: Status) {\n this.state.status = status;\n this.events.onUpdateListStatus(status);\n }\n\n private updateActiveTaskIndex(index: number) {\n this.state.activeTaskIndex = index;\n }\n\n /**\n *\n * Update task state (`status`, `blockedFor`) and trigger an event.\n * @param id\n * @param nextState\n */\n private updateTaskState(id: TaskId, nextState: Partial<TaskState>) {\n if (nextState.status) {\n this.state.tasks[id].status = nextState.status;\n }\n if (nextState.blockedFor) {\n this.state.tasks[id].blockedFor = nextState.blockedFor;\n }\n\n const updatedTaskEvent = {\n id: id,\n task: this.get(id)!,\n action: this.tasks.find((task) => task.id === id)!.action,\n };\n this.events.onUpdate(updatedTaskEvent);\n }\n\n /**\n * Create a task by providing an `action` name.\n *\n * this method creating the task, push it to the queue's tasks and trigger an event.\n * @param action\n */\n createTask(action: string) {\n const id = uuidv4();\n this.tasks.push({\n action,\n id,\n });\n this.state.tasks[id] = {\n status: Status.PENDING,\n blockedFor: null,\n };\n\n const createdTask = this.get(id);\n this.events.onCreate({\n id,\n task: createdTask!,\n action,\n });\n }\n\n /**\n * Initilize a queue with some tasks, instead of an empty queue.\n *\n * Using it for recover the queue state from persistor.\n *\n */\n public initTasks(info: InitTasks) {\n this.state = info.state;\n this.storage = info.storage;\n\n info.tasks.forEach((task) => {\n this.tasks.push(task);\n const action = this.tasks.find((t) => t.id === task.id)!.action;\n this.events.onCreate({\n id: task.id,\n task: this.get(task.id)!,\n action,\n });\n });\n }\n\n public checkBlock() {\n const currentActiveTask = this.getActiveTask();\n\n if (!currentActiveTask) {\n return;\n }\n const { task, state } = currentActiveTask;\n\n if (state.status === Status.BLOCKED) {\n this.events.onBlock({\n action: task.action,\n id: task.id,\n reason: state.blockedFor,\n });\n }\n }\n\n /**\n * Getting task state by ID\n */\n public get(id: string): TaskState | null {\n const task = this.state.tasks[id];\n\n if (!task) return null;\n\n return task;\n }\n\n /**\n *\n * Checking if status of the last is `SUCCESS` or not\n *\n */\n private lastTaskIsSuccessful() {\n const lastTask = this.tasks[this.tasks.length - 1];\n\n // checking for empty lists.\n if (lastTask) {\n const lastTaskState = this.state.tasks[lastTask.id];\n\n // Maybe we didn't create the state yet. It should has success status as well.\n if (!!lastTaskState && lastTaskState.status === Status.SUCCESS) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * If the first task started (it's not PENDING),\n * it means the queue has been ran.\n *\n * @returns\n */\n private firstTaskIsStarted() {\n const firstTask = this.tasks[0];\n\n // checking for empty lists.\n if (firstTask) {\n const firstTaskState = this.state.tasks[firstTask.id];\n\n // Maybe we didn't create the state yet.\n if (!!firstTaskState) {\n if (firstTaskState.status !== Status.PENDING) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Getting active task index from state and\n * returns the task and its state.\n *\n */\n private getActiveTask() {\n // First try to get task with `activeTask`\n const index = this.state.activeTaskIndex;\n const task = this.tasks[index];\n\n // Consider all the tasks has been executed.\n if (!task) {\n return null;\n }\n\n const state = this.state.tasks[task.id];\n\n return { task, state, index };\n }\n\n /**\n * Update and find the queue status by checking state of each tasks in the queue.\n */\n public check() {\n const currentListStatus = this.state.status;\n let nextListStatus = this.firstTaskIsStarted()\n ? Status.RUNNING\n : Status.PENDING;\n\n if (this.lastTaskIsSuccessful()) {\n nextListStatus = Status.SUCCESS;\n } else {\n // Is there any failed task?\n for (const task of this.tasks) {\n const state = this.state.tasks[task.id];\n\n // If one item fails, we stop to work on the list.\n if (state.status === Status.FAILED) {\n nextListStatus = Status.FAILED;\n break;\n }\n }\n }\n\n // We only update and trigger an event when there is a new value\n if (nextListStatus !== currentListStatus) {\n this.updateQueueStatus(nextListStatus);\n }\n }\n\n /**\n * Execute active task.\n * Based on the state of active task, the behaviour is different. If status is:\n * - Success -> we need to go to next task by updating the active index and try `next` on more time.\n * - Failed, Running, or no active task -> doesn't do anything.\n * - Pending or Blocked -> update the task and queue status to running, and execute the provided `action` for the task.\n *\n * The queue is a linked list somehow, active task means the pointer to where we are in the queue right now.\n *\n */\n public next(params: NextParams) {\n this.check();\n\n const currentActiveTask = this.getActiveTask();\n\n if (!currentActiveTask) {\n return;\n }\n\n const {\n index: activeTaskIndex,\n task: activeTask,\n state: activeTaskState,\n } = currentActiveTask;\n\n // if `activeTask` is already done, we will go for next one.\n if (activeTaskState.status === Status.SUCCESS) {\n this.updateActiveTaskIndex(activeTaskIndex + 1);\n this.next(params);\n return;\n }\n\n if (\n [Status.FAILED, Status.CANCELED, Status.RUNNING].includes(\n activeTaskState.status\n )\n ) {\n return;\n }\n\n if (\n activeTaskState.status === Status.PENDING ||\n activeTaskState.status === Status.BLOCKED\n ) {\n // Update task status to `running`\n this.updateTaskState(activeTask.id, {\n status: Status.RUNNING,\n });\n this.updateQueueStatus(Status.RUNNING);\n\n // Try to execute task.\n const execute = this.actions[activeTask.action];\n execute({\n context: this.getContext(params),\n next: () => {\n this.markCurrentTaskAsFinished(params);\n },\n retry: () => {\n this.resume(params);\n },\n failed: () => {\n this.updateTaskState(activeTask.id, {\n status: Status.FAILED,\n });\n this.check();\n },\n schedule: (action) => {\n this.createTask(action);\n this.check();\n },\n getStorage: this.getStorage.bind(this),\n setStorage: this.setStorage.bind(this),\n block: (reason: Record<string, unknown>) => {\n this.block({ reason });\n },\n unblock: () => {\n this.unblock();\n },\n });\n }\n }\n\n /**\n * Change the `status` of active task and queue to BLOCKED, then trigger an event.\n */\n public block({\n reason,\n silent = false,\n }: {\n reason: Record<string, unknown>;\n silent?: boolean;\n }) {\n const currentActiveTask = this.getActiveTask();\n\n if (!currentActiveTask) {\n throw new Error(\"Task isn't exist.\");\n }\n\n this.updateTaskState(currentActiveTask.task.id, {\n status: Status.BLOCKED,\n blockedFor: reason,\n });\n this.updateQueueStatus(Status.BLOCKED);\n\n if (!silent) {\n this.events.onBlock({\n action: currentActiveTask.task.action,\n id: currentActiveTask.task.id,\n reason,\n });\n }\n }\n\n /**\n * If the active task is `BLOCKED`, update the task status to `PENDING`, queue status to `RUNNING`\n * then trigger an event.\n */\n public unblock() {\n const currentActiveTask = this.getActiveTask();\n\n if (\n !currentActiveTask ||\n currentActiveTask.state.status !== Status.BLOCKED\n ) {\n throw new Error('Task is not blocked.');\n }\n\n this.updateTaskState(currentActiveTask.task.id, {\n status: Status.PENDING,\n });\n this.updateQueueStatus(Status.RUNNING);\n this.events.onUnblock({ id: currentActiveTask.task.id });\n }\n\n /**\n * If the active task is `BLOCKED` then execute the `action` for the task.\n *\n * It is useful for when we need to run a blocked task without changing the status of task at the first place.\n * For scenarios like we have some conditions in `action` and needs to run the `action` again\n * to check the conditions are met or not, if yes, so we can proceed the `action`.\n *\n */\n public forceRun(params: NextParams) {\n const currentTask = this.getActiveTask();\n\n if (!currentTask || currentTask.state.status !== Status.BLOCKED) {\n throw new Error('Task is not blocked.');\n }\n\n // Try to execute task.\n const execute = this.actions[currentTask.task.action];\n execute({\n context: this.getContext(params),\n next: () => {\n /*\n NOTE:\n When running `forceRun`, the status of task can be `BLOCKED`\n So we need to change to `Running` first. \n */\n // Update task status to `running`\n this.updateTaskState(currentTask.task.id, {\n status: Status.RUNNING,\n });\n this.updateQueueStatus(Status.RUNNING);\n\n this.markCurrentTaskAsFinished(params);\n },\n retry: () => {\n this.resume(params);\n },\n failed: () => {\n this.updateTaskState(currentTask.task.id, {\n status: Status.FAILED,\n });\n this.check();\n },\n schedule: (action) => {\n this.createTask(action);\n this.check();\n },\n getStorage: this.getStorage.bind(this),\n setStorage: this.setStorage.bind(this),\n block: (reason: Record<string, unknown>) => {\n this.block({ reason });\n },\n unblock: () => {\n this.unblock();\n },\n });\n }\n private markCurrentTaskAsFinished(params: NextParams) {\n this.check();\n const activeTaskIndex = this.state.activeTaskIndex;\n const activeTask = this.tasks[activeTaskIndex];\n\n if (!activeTask) return;\n\n const activeTaskState = this.state.tasks[activeTask.id];\n if (activeTaskState.status === Status.RUNNING) {\n this.updateTaskState(activeTask.id, {\n status: Status.SUCCESS,\n });\n this.updateActiveTaskIndex(activeTaskIndex + 1);\n\n const updatedTaskEvent = {\n id: activeTask.id,\n task: this.get(activeTask.id)!,\n action: this.tasks.find((task) => task.id === activeTask.id)!.action,\n };\n this.events.onUpdate(updatedTaskEvent);\n this.next(params);\n }\n }\n\n /**\n * If the active task is `RUNNING`, change it to `PENING` the try to run the task by calling `next`.\n * If it's other than `RUNNING` we reset the queue state and run the queue from the beggining.\n *\n * @param params\n * @returns\n */\n public resume(params: NextParams) {\n const activeTaskIndex = this.state.activeTaskIndex;\n const activeTask = this.tasks[activeTaskIndex];\n if (!activeTask) return;\n\n const activeTaskState = this.state.tasks[activeTask.id];\n if (activeTaskState.status === Status.RUNNING) {\n this.updateTaskState(activeTask.id, {\n status: Status.PENDING,\n });\n this.next(params);\n } else {\n this.resetState();\n this.next(params);\n }\n }\n\n /**\n *\n * Cancel the queue by changing active task and queue status to `CANCELED`.\n *\n */\n public cancel() {\n const currentActiveTask = this.getActiveTask();\n\n if (\n !currentActiveTask ||\n [Status.FAILED, Status.CANCELED, Status.SUCCESS].includes(\n currentActiveTask.state.status\n )\n ) {\n return;\n }\n\n const { task } = currentActiveTask;\n\n // Update task status to `canceled`\n this.updateTaskState(task.id, {\n status: Status.CANCELED,\n });\n const updatedTaskEvent = {\n id: task.id,\n task: this.get(task.id)!,\n action: this.tasks.find((t) => t.id === task.id)!.action,\n };\n this.events.onUpdate(updatedTaskEvent);\n\n // Update queue status to `canceled`\n this.updateQueueStatus(Status.CANCELED);\n }\n\n /**\n * Update queue status, and all the tasks inside queue to `PENDING`.\n */\n private resetState() {\n this.state.activeTaskIndex = 0;\n this.state.status = Status.PENDING;\n Object.keys(this.state.tasks).forEach((id) => {\n this.state.tasks[id].status = Status.PENDING;\n });\n }\n\n public getStorage() {\n return this.storage;\n }\n public setStorage(data: QueueStorage) {\n this.storage = data;\n this.events.onStorageUpdate(data);\n return this.storage;\n }\n\n private getContext(params: NextParams): QueueContext & ManagerContext {\n return {\n ...params.context,\n _queue: {\n id: this.id,\n },\n };\n }\n}\n\nexport default Queue;\n", "import { QueueID, QueueName } from './manager';\nimport Queue, { QueueState, Task } from './queue';\n\nexport enum Status {\n PENDING = 'PENDING',\n RUNNING = 'RUNNING',\n FAILED = 'FAILED',\n SUCCESS = 'SUCCESS',\n CANCELED = 'CANCELED',\n BLOCKED = 'BLOCKED',\n}\n\nexport const SYNC_POLLING_INTERVAL = 5_000\n\nexport type QueueStorage = Record<string, unknown>;\n\nexport type QueueType = Queue;\n\nexport interface PersistedQueue {\n id: QueueID;\n createdAt: number;\n name: QueueName;\n status: Status;\n state: QueueState;\n tasks: Task[];\n storage: QueueStorage;\n}\n", "import Persistor from './persistor';\nimport Queue, { QueueEventHandlers, TaskEvent } from './queue';\nimport { QueueStorage, SYNC_POLLING_INTERVAL, Status } from './types';\nimport { v4 as uuidv4 } from 'uuid';\n\nexport type ManagerContext = object;\nexport type QueueName = string;\nexport type QueueID = string;\nexport type BlockedTask = {\n queue_id: string;\n task_id: string;\n action: string;\n reason: Record<string, unknown>;\n storage: {\n get: () => QueueStorage;\n set: (data: QueueStorage) => QueueStorage;\n };\n};\n\nexport type SetStorage<T> = (nextStorage: T) => T;\n\nexport interface ExecuterActions<\n T extends QueueStorage = QueueStorage,\n V extends string = string,\n C = ManagerContext\n> {\n next: () => void;\n retry: () => void;\n failed: () => void;\n schedule: (actionName: V) => void;\n setStorage: SetStorage<T>;\n getStorage: () => T;\n block: (reason: Record<string, unknown>) => void;\n unblock: () => void;\n context: C;\n}\n\nexport interface QueueDef<\n T extends QueueStorage = QueueStorage,\n V extends string = string,\n C = ManagerContext\n> {\n name: QueueName;\n actions: {\n [K in V]: (actions: ExecuterActions<T, V, C>) => void | Promise<void>;\n };\n events?: Partial<QueueEventHandlers>;\n run: V[];\n whenTaskBlocked?: (\n event: any,\n params: {\n queue_id: string;\n queue: Queue;\n context: C;\n getBlockedTasks: () => BlockedTask[];\n forceExecute: (queue_id: string, data?: object) => void;\n retry: () => void;\n manager: Manager;\n }\n ) => void;\n}\n\nexport interface Events {\n onCreateQueue: (queue: QueueInfo & { id: QueueID }) => void;\n onUpdateQueue: (queue_id: QueueID, queue: QueueInfo) => void;\n onCreateTask: (queue_id: QueueID, event: TaskEvent) => void;\n onUpdateTask: (queue_id: QueueID, event: TaskEvent) => void;\n onStorageUpdate: (queue_id: QueueID, data: QueueStorage) => void;\n onTaskBlock: (queue_id: QueueID) => void;\n onPersistedDataLoaded: (manager: Manager) => void;\n}\n\ninterface ManagerOptions {\n events?: Partial<Events>;\n queuesDefs: QueueDef[];\n context?: ManagerContext;\n isPaused?: boolean;\n}\n\nexport interface QueueInfo {\n name: QueueName;\n createdAt: number;\n status: Status;\n list: Queue;\n actions: {\n run: () => void;\n cancel: () => void;\n setStorage: SetStorage<any>;\n getStorage: () => any;\n };\n}\n\nclass Manager {\n private queuesDefs = new Map<QueueName, QueueDef>();\n private queues = new Map<QueueID, QueueInfo>();\n private events: Events;\n private persistor: Persistor;\n private context: ManagerContext;\n private isPaused: boolean = false;\n // The client won't get any update on pause, We are using a polling mode to fix this issue for now.\n private syncInterval: NodeJS.Timer | null = null;\n\n /**\n *\n * Making an instance, initilize events, setup a persistor and try to recover the last state of the manager.\n *\n * */\n constructor(options: ManagerOptions) {\n const defaultEventHandlers: Events = {\n onCreateQueue: () => {\n // ...\n },\n onCreateTask: () => {\n // ...\n },\n onUpdateQueue: () => {\n // ...\n },\n onUpdateTask: () => {\n // ...\n },\n onStorageUpdate: () => {\n // ...\n },\n onTaskBlock: () => {\n // ...\n },\n onPersistedDataLoaded: () => {\n // ..\n },\n };\n\n if (options.events) {\n this.events = {\n ...defaultEventHandlers,\n ...options.events,\n };\n } else {\n this.events = defaultEventHandlers;\n }\n\n options.queuesDefs.map((qDef) => {\n this.queuesDefs.set(qDef.name, qDef);\n });\n\n this.context = options.context || {};\n this.persistor = new Persistor();\n this.sync();\n\n if (options.isPaused) {\n this.pause();\n }\n }\n\n /**\n *\n * Reading persisted data from storage then brings into memory.\n *\n * Notes:\n * - Reset the memory, so we can call this method whenever we want and not only on the initialize process.\n * - All the events will be tirggered (like onCreateQueue, onCreateTask, onBlock, ....)\n * - Try to `resume` if the status is `running`.\n * - Trigger `onPersistedDataLoaded` event when queues recovered from storage.\n *\n */\n private async sync() {\n try {\n // Reading queues from storage\n const queues = await this.persistor.getAll();\n\n // Reset queues, if anything is exist in memory.\n this.queues = new Map();\n\n // Brings them into memory\n queues.forEach((q) => {\n const list = this.createQueue({\n queue_id: q.id,\n queue_name: q.name,\n });\n this.add(q.id, {\n list,\n createdAt: q.createdAt,\n name: q.name,\n status: q.status,\n actions: {\n run: () => {\n list.next({\n context: this.getContext(),\n });\n },\n cancel: () => {\n list.cancel();\n },\n setStorage: (...args) => {\n list.setStorage(...args);\n },\n getStorage: () => {\n return list.getStorage();\n },\n },\n });\n\n list.initTasks({\n state: q.state,\n tasks: q.tasks,\n storage: q.storage || {},\n });\n\n if (q.status === Status.RUNNING && this.shouldExecute()) {\n list.resume({\n context: this.getContext(),\n });\n }\n });\n } catch (e) {\n console.log(`IndexDB Error: ${e}`);\n }\n\n // Trigger an event to let the subscribers we are done here.\n this.events.onPersistedDataLoaded(this);\n }\n\n /**\n *\n * Making a new instance from `Queue` and adds Manager's event handlers to it.\n *\n * @returns An instance of `Queue` with wrapped event handlers from Manager.\n *\n */\n private createQueue({\n queue_id,\n queue_name,\n }: {\n queue_id: QueueID;\n queue_name: QueueName;\n }) {\n const manager = this;\n const def = this.queuesDefs.get(queue_name)!;\n const list = new Queue({\n id: queue_id,\n events: {\n onCreate: (task) => {\n this.events.onCreateTask(queue_id, task);\n this.handleUpdate(queue_id);\n\n if (def.events?.onCreate) def.events.onCreate(task);\n },\n onUpdate: (task) => {\n this.events.onUpdateTask(queue_id, task);\n this.handleUpdate(queue_id);\n\n if (def.events?.onUpdate) def.events.onUpdate(task);\n },\n onUpdateListStatus: (status) => {\n this.queues.set(queue_id, {\n ...this.get(queue_id)!,\n status,\n });\n this.events.onUpdateQueue(queue_id, this.get(queue_id)!);\n\n this.handleUpdate(queue_id);\n\n // After finishing a queue, try to run other queues.\n this.execute();\n if (def.events?.onUpdateListStatus)\n def.events.onUpdateListStatus(status);\n },\n onStorageUpdate: (data) => {\n this.events.onStorageUpdate(queue_id, data);\n if (def.events?.onStorageUpdate) def.events.onStorageUpdate(data);\n this.handleUpdate(queue_id);\n },\n onBlock: (event) => {\n // Update queue status\n this.queues.set(queue_id, {\n ...this.get(queue_id)!,\n status: Status.BLOCKED,\n });\n\n // Trigger event\n this.events.onTaskBlock(queue_id);\n if (def.whenTaskBlocked) {\n def.whenTaskBlocked(event, {\n queue_id: queue_id,\n queue: list,\n context: this.getContext(),\n getBlockedTasks: this.getBlockedTasks.bind(this),\n forceExecute: this.forceExecute.bind(this),\n retry: this.retry.bind(this),\n manager,\n });\n }\n\n // Sync\n this.handleUpdate(queue_id);\n },\n onUnblock: () => {\n // Update queue status\n this.queues.set(queue_id, {\n ...this.get(queue_id)!,\n status: Status.PENDING,\n });\n\n // Sync\n this.handleUpdate(queue_id);\n\n this.execute();\n },\n },\n actions: def.actions,\n });\n return list;\n }\n\n /**\n * Go through all tasks (from all queues) and return a list of blocked tasks\n *\n * @returns a list of blocked tasks including enough information to get the queue and mutate the storage.\n *\n */\n private getBlockedTasks() {\n const queues = this.getAll();\n const blockedTasks: BlockedTask[] = [];\n queues.forEach((q, queue_id) => {\n q.list.tasks.forEach((task) => {\n const state = q.list.state.tasks[task.id];\n if (state.status === Status.BLOCKED) {\n blockedTasks.push({\n task_id: task.id,\n queue_id: queue_id,\n action: task.action,\n reason: state.blockedFor,\n storage: {\n get: () => {\n return q.list.getStorage();\n },\n set: (data) => {\n return q.list.setStorage(data);\n },\n },\n });\n }\n });\n });\n\n return blockedTasks;\n }\n\n /**\n *\n * Add a queue to the manager to keep track of the queue and its state.\n *\n * @param id\n * @param queue\n * @returns\n */\n private add(id: QueueID, queue: QueueInfo) {\n this.queues.set(id, queue);\n const createdQueue = this.get(id)!;\n this.events.onCreateQueue({ ...createdQueue, id });\n\n return createdQueue;\n }\n\n // Create a new queue\n /**\n *\n * Create a new queue by client.\n *\n * It will do the internal things to make a queue from definitions, and running using Manager.\n *\n * Notes:\n * - After creating the queue, it will be run automatically.\n *\n * @returns an ID for queue so it can be used to get the created queue later by client.\n *\n */\n public async create(\n name: QueueName,\n storage: QueueStorage,\n options?: { id?: QueueID }\n ) {\n if (!this.queuesDefs.has(name)) {\n throw new Error('You need to add a queue definition first.');\n }\n\n try {\n const def = this.queuesDefs.get(name)!;\n const queue_id: QueueID = options?.id || uuidv4();\n const createdAt = Date.now();\n const list = this.createQueue({\n queue_id: queue_id,\n queue_name: name,\n });\n list.setStorage(storage);\n\n const createdQueue = this.add(queue_id, {\n list,\n createdAt,\n name,\n status: Status.PENDING,\n actions: {\n run: () => {\n list.next({\n context: this.getContext(),\n });\n },\n cancel: () => {\n list.cancel();\n },\n setStorage: (...args) => {\n list.setStorage(...args);\n },\n getStorage: () => {\n return list.getStorage();\n },\n },\n });\n\n // Persist initial queue\n // Note: we need to first insert the queue, and then it can be updated by internal events.\n await this.persistor.insertQueue({\n id: queue_id,\n createdAt,\n name: createdQueue.name,\n status: createdQueue.status,\n tasks: list.tasks,\n state: list.state,\n storage: list.getStorage(),\n });\n\n // adding initial tasks\n def.run.forEach((action) => {\n list.createTask(action);\n });\n\n // After creating a new queue, try to run.\n this.execute();\n return queue_id;\n } catch (e) {\n throw new Error((e as any)?.message);\n }\n }\n\n /**\n * Get a queue by its ID.\n *\n * @returns An object includes queue and its state in `Manager`.\n */\n public get(queue_id: QueueID) {\n return this.queues.get(queue_id);\n }\n\n /**\n * Get all queues from `Manager`\n *\n * @returns a list of queues includes all the queues and their states.\n */\n public getAll() {\n return this.queues;\n }\n\n /**\n *\n * Ask from manager to run pending queues.\n *\n * It only try to run queues with `PENDING` status and ignore all the other statuses.\n *\n */\n public execute() {\n if (!this.shouldExecute()) return;\n\n for (const [, q] of Array.from(this.queues)) {\n if (q.status === Status.PENDING) {\n q.actions.run();\n }\n }\n }\n\n /**\n *\n * Try to find queues with `RUNNING` status to run them again.\n *\n * It's useful for recovering the queue at some certain points\n * like running a currepted task (reloaded when it was running) or needs manual trigger from UI.\n *\n * @returns\n */\n public resume() {\n if (!this.shouldExecute()) return;\n\n for (const [, q] of Array.from(this.queues)) {\n if (q.status === Status.RUNNING) {\n q.list.resume({\n context: this.getContext(),\n });\n return;\n }\n }\n\n // If there is no running queue, try to run a new queue.\n this.execute();\n }\n\n /**\n *\n * Run all `BLOCKED` queues once again.\n *\n * If a queue has `BLOCKED` status and the last task is `BLOCKED` as well,\n * The task will be run one more time.\n *\n * Useful for scenarios like we are blocking the queue under some conditions in task,\n * We can use this method to ask the queue to run the blocked task one more time and\n * maybe this time condtions are met and the queue can be proceed.\n *\n * @returns\n */\n public retry() {\n if (!this.shouldExecute()) return;\n\n for (const [, q] of Array.from(this.queues)) {\n if (q.status === Status.BLOCKED) {\n q.list.checkBlock();\n }\n }\n\n // If there is no running queue, try to run a new queue.\n this.execute();\n }\n\n /**\n *\n * Run a blocked task on a specific queue with the ability to pass more data.\n *\n * Useful when we have a custom logic for running queue and needs to pass some specific data\n * to the task and try to run it manually with the provided data.\n *\n */\n public forceExecute(queue_id: string, data?: object) {\n const queue = this.get(queue_id);\n let context = this.getContext();\n if (data) {\n context = {\n ...context,\n ...data,\n };\n }\n\n queue?.list.forceRun({\n context,\n });\n }\n\n /**\n *\n * Sync in-memory state (of `Manager`) with storage (persist).\n *\n * Usually we call this method after a change detected in the state of manager.\n *\n */\n private handleUpdate(queue_id: QueueID) {\n const queue = this.get(queue_id);\n\n if (queue) {\n const status = queue.status;\n const state = queue.list.state;\n const tasks = queue.list.tasks;\n this.persistor.updateQueue(queue_id, {\n status,\n state,\n tasks,\n storage: queue.list.getStorage(),\n });\n }\n }\n\n /**\n * Active readonly mode for manager, it means it doesn't run anythin,\n * And only can be used to read the data.\n */\n public pause() {\n if (this.isPaused) return;\n this.isPaused = true;\n this.syncInterval = setInterval(() => {\n this.sync();\n }, SYNC_POLLING_INTERVAL);\n }\n\n /**\n * Activate normal mode which means it will be able to run the queuese as well.\n */\n public run() {\n // If call this method multiple times, it should be run for once.\n if (this.isPaused) {\n this.isPaused = false;\n if (!!this.syncInterval) {\n clearInterval(this.syncInterval);\n this.syncInterval = null;\n }\n this.sync();\n }\n }\n\n private getContext() {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n //@ts-ignore\n return this.context?.current || {};\n }\n\n private shouldExecute() {\n return !this.isPaused;\n }\n}\n\nexport { Manager };\n"],
5
- "mappings": "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",
6
- "names": ["DB_NAME", "OBJECT_STORE_NAME", "VERSION", "Persistor", "idb", "db", "queue", "id", "currentRecord", "updatedRecord", "__name", "persistor_default", "uuidv4", "Status", "SYNC_POLLING_INTERVAL", "Queue", "options", "status", "index", "id", "nextState", "updatedTaskEvent", "task", "action", "uuidv4", "createdTask", "info", "t", "currentActiveTask", "state", "lastTask", "lastTaskState", "firstTask", "firstTaskState", "currentListStatus", "nextListStatus", "params", "activeTaskIndex", "activeTask", "activeTaskState", "execute", "reason", "silent", "currentTask", "data", "__name", "queue_default", "uuidv4", "Manager", "options", "defaultEventHandlers", "qDef", "persistor_default", "queues", "q", "list", "args", "e", "queue_id", "queue_name", "manager", "def", "queue_default", "task", "status", "data", "event", "blockedTasks", "state", "id", "queue", "createdQueue", "name", "storage", "uuidv4", "createdAt", "action", "context", "tasks", "SYNC_POLLING_INTERVAL", "__name"]
3
+ "sources": ["../src/manager.ts", "../src/persistor.ts", "../src/queue.ts", "../src/types.ts"],
4
+ "sourcesContent": ["import type { QueueEventHandlers, TaskEvent } from './queue';\nimport type { QueueStorage } from './types';\n\nimport { v4 as uuidv4 } from 'uuid';\n\nimport Persistor from './persistor';\nimport Queue from './queue';\nimport { Status, SYNC_POLLING_INTERVAL } from './types';\n\nexport type ManagerContext = object;\nexport type QueueName = string;\nexport type QueueID = string;\nexport type BlockedTask = {\n queue_id: string;\n task_id: string;\n action: string;\n reason: Record<string, unknown>;\n storage: {\n get: () => QueueStorage;\n set: (data: QueueStorage) => QueueStorage;\n };\n};\n\nexport type SetStorage<T> = (nextStorage: T) => T;\n\nexport interface ExecuterActions<\n T extends QueueStorage = QueueStorage,\n V extends string = string,\n C = ManagerContext\n> {\n next: () => void;\n retry: () => void;\n failed: () => void;\n schedule: (actionName: V) => void;\n setStorage: SetStorage<T>;\n getStorage: () => T;\n block: (reason: Record<string, unknown>) => void;\n unblock: () => void;\n context: C;\n}\n\nexport interface QueueDef<\n T extends QueueStorage = QueueStorage,\n V extends string = string,\n C = ManagerContext\n> {\n name: QueueName;\n actions: {\n [K in V]: (actions: ExecuterActions<T, V, C>) => void | Promise<void>;\n };\n events?: Partial<QueueEventHandlers>;\n run: V[];\n whenTaskBlocked?: (\n event: any,\n params: {\n queue_id: string;\n queue: Queue;\n context: C;\n getBlockedTasks: () => BlockedTask[];\n forceExecute: (queue_id: string, data?: object) => void;\n retry: () => void;\n manager: Manager;\n }\n ) => void;\n}\n\nexport interface Events {\n onCreateQueue: (queue: QueueInfo & { id: QueueID }) => void;\n onUpdateQueue: (queue_id: QueueID, queue: QueueInfo) => void;\n onCreateTask: (queue_id: QueueID, event: TaskEvent) => void;\n onUpdateTask: (queue_id: QueueID, event: TaskEvent) => void;\n onStorageUpdate: (queue_id: QueueID, data: QueueStorage) => void;\n onTaskBlock: (queue_id: QueueID) => void;\n onDeleteQueue: (queue_id: QueueID) => void;\n onPersistedDataLoaded: (manager: Manager) => void;\n}\n\ninterface ManagerOptions {\n events?: Partial<Events>;\n queuesDefs: QueueDef[];\n context?: ManagerContext;\n isPaused?: boolean;\n}\n\nexport interface QueueInfo {\n name: QueueName;\n createdAt: number;\n status: Status;\n list: Queue;\n actions: {\n run: () => void;\n cancel: () => void;\n setStorage: SetStorage<any>;\n getStorage: () => any;\n };\n}\n\nclass Manager {\n private queuesDefs = new Map<QueueName, QueueDef>();\n private queues = new Map<QueueID, QueueInfo>();\n private events: Events;\n private persistor: Persistor;\n private context: ManagerContext;\n private isPaused = false;\n // The client won't get any update on pause, We are using a polling mode to fix this issue for now.\n private syncInterval: NodeJS.Timer | null = null;\n\n /**\n *\n * Making an instance, initilize events, setup a persistor and try to recover the last state of the manager.\n *\n *\n */\n constructor(options: ManagerOptions) {\n const defaultEventHandlers: Events = {\n onCreateQueue: () => {\n // ...\n },\n onCreateTask: () => {\n // ...\n },\n onUpdateQueue: () => {\n // ...\n },\n onUpdateTask: () => {\n // ...\n },\n onStorageUpdate: () => {\n // ...\n },\n onTaskBlock: () => {\n // ...\n },\n onPersistedDataLoaded: () => {\n // ..\n },\n onDeleteQueue: () => {\n // ...\n },\n };\n\n if (options.events) {\n this.events = {\n ...defaultEventHandlers,\n ...options.events,\n };\n } else {\n this.events = defaultEventHandlers;\n }\n\n options.queuesDefs.map((qDef) => {\n this.queuesDefs.set(qDef.name, qDef);\n });\n\n this.context = options.context || {};\n this.persistor = new Persistor();\n\n void this.sync();\n\n if (options.isPaused) {\n this.pause();\n }\n }\n\n // Create a new queue\n /**\n *\n * Create a new queue by client.\n *\n * It will do the internal things to make a queue from definitions, and running using Manager.\n *\n * Notes:\n * - After creating the queue, it will be run automatically.\n *\n * @returns an ID for queue so it can be used to get the created queue later by client.\n *\n */\n public async create(\n name: QueueName,\n storage: QueueStorage,\n options?: { id?: QueueID }\n ) {\n if (!this.queuesDefs.has(name)) {\n throw new Error('You need to add a queue definition first.');\n }\n\n try {\n const def = this.queuesDefs.get(name)!;\n const queue_id: QueueID = options?.id || uuidv4();\n const createdAt = Date.now();\n const list = this.createQueue({\n queue_id: queue_id,\n queue_name: name,\n });\n list.setStorage(storage);\n\n const createdQueue = this.add(queue_id, {\n list,\n createdAt,\n name,\n status: Status.PENDING,\n actions: {\n run: () => {\n list.next({\n context: this.getContext(),\n });\n },\n cancel: () => {\n list.cancel();\n },\n setStorage: (...args) => {\n list.setStorage(...args);\n },\n getStorage: () => {\n return list.getStorage();\n },\n },\n });\n\n /*\n * Persist initial queue\n * Note: we need to first insert the queue, and then it can be updated by internal events.\n */\n await this.persistor.insertQueue({\n id: queue_id,\n createdAt,\n name: createdQueue.name,\n status: createdQueue.status,\n tasks: list.tasks,\n state: list.state,\n storage: list.getStorage(),\n });\n\n // adding initial tasks\n def.run.forEach((action) => {\n list.createTask(action);\n });\n\n // After creating a new queue, try to run.\n this.execute();\n return queue_id;\n } catch (e) {\n throw new Error((e as any)?.message);\n }\n }\n /**\n *\n * Reading persisted data from storage then brings into memory.\n *\n * Notes:\n * - Reset the memory, so we can call this method whenever we want and not only on the initialize process.\n * - All the events will be tirggered (like onCreateQueue, onCreateTask, onBlock, ....)\n * - Try to `resume` if the status is `running`.\n * - Trigger `onPersistedDataLoaded` event when queues recovered from storage.\n *\n */\n\n /**\n * Get a queue by its ID.\n *\n * @returns An object includes queue and its state in `Manager`.\n */\n public get(queue_id: QueueID) {\n return this.queues.get(queue_id);\n }\n\n /**\n * Get all queues from `Manager`\n *\n * @returns a list of queues includes all the queues and their states.\n */\n public getAll() {\n return this.queues;\n }\n\n public deleteQueue(queue_id: QueueID) {\n this.queues.delete(queue_id);\n void this.persistor.deleteQueue(queue_id);\n }\n /**\n *\n * Ask from manager to run pending queues.\n *\n * It only try to run queues with `PENDING` status and ignore all the other statuses.\n *\n */\n public execute() {\n if (!this.shouldExecute()) {\n return;\n }\n\n for (const [, q] of Array.from(this.queues)) {\n if (q.status === Status.PENDING) {\n q.actions.run();\n }\n }\n }\n\n /**\n *\n * Try to find queues with `RUNNING` status to run them again.\n *\n * It's useful for recovering the queue at some certain points\n * like running a currepted task (reloaded when it was running) or needs manual trigger from UI.\n *\n * @returns\n */\n public resume() {\n if (!this.shouldExecute()) {\n return;\n }\n\n for (const [, q] of Array.from(this.queues)) {\n if (q.status === Status.RUNNING) {\n q.list.resume({\n context: this.getContext(),\n });\n return;\n }\n }\n\n // If there is no running queue, try to run a new queue.\n this.execute();\n }\n\n /**\n *\n * Run all `BLOCKED` queues once again.\n *\n * If a queue has `BLOCKED` status and the last task is `BLOCKED` as well,\n * The task will be run one more time.\n *\n * Useful for scenarios like we are blocking the queue under some conditions in task,\n * We can use this method to ask the queue to run the blocked task one more time and\n * maybe this time condtions are met and the queue can be proceed.\n *\n * @returns\n */\n public retry() {\n if (!this.shouldExecute()) {\n return;\n }\n\n for (const [, q] of Array.from(this.queues)) {\n if (q.status === Status.BLOCKED) {\n q.list.checkBlock();\n }\n }\n\n // If there is no running queue, try to run a new queue.\n this.execute();\n }\n\n /**\n *\n * Run a blocked task on a specific queue with the ability to pass more data.\n *\n * Useful when we have a custom logic for running queue and needs to pass some specific data\n * to the task and try to run it manually with the provided data.\n *\n */\n public forceExecute(queue_id: string, data?: object) {\n const queue = this.get(queue_id);\n let context = this.getContext();\n if (data) {\n context = {\n ...context,\n ...data,\n };\n }\n\n queue?.list.forceRun({\n context,\n });\n }\n\n /**\n * Active readonly mode for manager, it means it doesn't run anythin,\n * And only can be used to read the data.\n */\n public pause() {\n if (this.isPaused) {\n return;\n }\n this.isPaused = true;\n this.syncInterval = setInterval(() => {\n void this.sync();\n }, SYNC_POLLING_INTERVAL);\n }\n\n /**\n * Activate normal mode which means it will be able to run the queuese as well.\n */\n public run() {\n // If call this method multiple times, it should be run for once.\n if (this.isPaused) {\n this.isPaused = false;\n if (!!this.syncInterval) {\n clearInterval(this.syncInterval);\n this.syncInterval = null;\n }\n void this.sync();\n }\n }\n\n private async sync() {\n try {\n // Reading queues from storage\n const queues = await this.persistor.getAll();\n\n // Reset queues, if anything is exist in memory.\n this.queues = new Map();\n\n // Brings them into memory\n queues.forEach((q) => {\n const list = this.createQueue({\n queue_id: q.id,\n queue_name: q.name,\n });\n this.add(q.id, {\n list,\n createdAt: q.createdAt,\n name: q.name,\n status: q.status,\n actions: {\n run: () => {\n list.next({\n context: this.getContext(),\n });\n },\n cancel: () => {\n list.cancel();\n },\n setStorage: (...args) => {\n list.setStorage(...args);\n },\n getStorage: () => {\n return list.getStorage();\n },\n },\n });\n\n list.initTasks({\n state: q.state,\n tasks: q.tasks,\n storage: q.storage || {},\n });\n\n if (q.status === Status.RUNNING && this.shouldExecute()) {\n list.resume({\n context: this.getContext(),\n });\n }\n });\n } catch (e) {\n console.log(`IndexDB Error: ${e}`);\n }\n\n // Trigger an event to let the subscribers we are done here.\n this.events.onPersistedDataLoaded(this);\n }\n\n /**\n *\n * Making a new instance from `Queue` and adds Manager's event handlers to it.\n *\n * @returns An instance of `Queue` with wrapped event handlers from Manager.\n *\n */\n private createQueue(info: { queue_id: QueueID; queue_name: QueueName }) {\n const { queue_id, queue_name } = info;\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const manager = this;\n const def = this.queuesDefs.get(queue_name)!;\n const list = new Queue({\n id: queue_id,\n events: {\n onCreate: (task) => {\n this.events.onCreateTask(queue_id, task);\n this.handleUpdate(queue_id);\n\n if (def.events?.onCreate) {\n def.events.onCreate(task);\n }\n },\n onUpdate: (task) => {\n this.events.onUpdateTask(queue_id, task);\n this.handleUpdate(queue_id);\n\n if (def.events?.onUpdate) {\n def.events.onUpdate(task);\n }\n },\n onUpdateListStatus: (status) => {\n this.queues.set(queue_id, {\n ...this.get(queue_id)!,\n status,\n });\n this.events.onUpdateQueue(queue_id, this.get(queue_id)!);\n\n this.handleUpdate(queue_id);\n\n // After finishing a queue, try to run other queues.\n this.execute();\n if (def.events?.onUpdateListStatus) {\n def.events.onUpdateListStatus(status);\n }\n },\n onStorageUpdate: (data) => {\n this.events.onStorageUpdate(queue_id, data);\n if (def.events?.onStorageUpdate) {\n def.events.onStorageUpdate(data);\n }\n this.handleUpdate(queue_id);\n },\n onBlock: (event) => {\n // Update queue status\n this.queues.set(queue_id, {\n ...this.get(queue_id)!,\n status: Status.BLOCKED,\n });\n\n // Trigger event\n this.events.onTaskBlock(queue_id);\n if (def.whenTaskBlocked) {\n def.whenTaskBlocked(event, {\n queue_id: queue_id,\n queue: list,\n context: this.getContext(),\n getBlockedTasks: this.getBlockedTasks.bind(this),\n forceExecute: this.forceExecute.bind(this),\n retry: this.retry.bind(this),\n manager,\n });\n }\n\n // Sync\n this.handleUpdate(queue_id);\n },\n onUnblock: () => {\n // Update queue status\n this.queues.set(queue_id, {\n ...this.get(queue_id)!,\n status: Status.PENDING,\n });\n\n // Sync\n this.handleUpdate(queue_id);\n\n this.execute();\n },\n },\n actions: def.actions,\n });\n return list;\n }\n\n /**\n * Go through all tasks (from all queues) and return a list of blocked tasks\n *\n * @returns a list of blocked tasks including enough information to get the queue and mutate the storage.\n *\n */\n private getBlockedTasks() {\n const queues = this.getAll();\n const blockedTasks: BlockedTask[] = [];\n queues.forEach((q, queue_id) => {\n q.list.tasks.forEach((task) => {\n const state = q.list.state.tasks[task.id];\n if (state.status === Status.BLOCKED) {\n blockedTasks.push({\n task_id: task.id,\n queue_id: queue_id,\n action: task.action,\n reason: state.blockedFor,\n storage: {\n get: () => {\n return q.list.getStorage();\n },\n set: (data) => {\n return q.list.setStorage(data);\n },\n },\n });\n }\n });\n });\n\n return blockedTasks;\n }\n\n /**\n *\n * Add a queue to the manager to keep track of the queue and its state.\n *\n * @param id\n * @param queue\n * @returns\n */\n private add(id: QueueID, queue: QueueInfo) {\n this.queues.set(id, queue);\n const createdQueue = this.get(id)!;\n this.events.onCreateQueue({ ...createdQueue, id });\n\n return createdQueue;\n }\n\n /**\n *\n * Sync in-memory state (of `Manager`) with storage (persist).\n *\n * Usually we call this method after a change detected in the state of manager.\n *\n */\n private handleUpdate(queue_id: QueueID) {\n const queue = this.get(queue_id);\n\n if (queue) {\n const status = queue.status;\n const state = queue.list.state;\n const tasks = queue.list.tasks;\n void this.persistor.updateQueue(queue_id, {\n status,\n state,\n tasks,\n storage: queue.list.getStorage(),\n });\n }\n }\n\n private getContext() {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-ts-comment\n //@ts-ignore\n return this.context?.current || {};\n }\n\n private shouldExecute() {\n return !this.isPaused;\n }\n}\n\nexport { Manager };\n", "import type { QueueID } from './manager';\nimport type { PersistedQueue } from './types';\nimport type { DBSchema, IDBPDatabase } from 'idb';\n\nexport const DB_NAME = 'queues-manager';\nconst OBJECT_STORE_NAME = 'queues';\nconst VERSION = 1;\n\ntype UpdatePersistedQueue = Partial<\n Pick<PersistedQueue, 'status' | 'state' | 'tasks' | 'storage'>\n>;\n\ninterface Database extends DBSchema {\n queues: {\n value: PersistedQueue;\n key: string;\n };\n}\n\nclass Persistor {\n db: Promise<IDBPDatabase<Database>>;\n constructor() {\n this.db = import('idb')\n .then(async (idb) => {\n return idb.openDB<Database>(DB_NAME, VERSION, {\n upgrade(db) {\n db.createObjectStore(OBJECT_STORE_NAME, { keyPath: 'id' });\n },\n });\n })\n .catch(() => {\n throw new Error(\"Couldn't load idb.\");\n });\n }\n\n async insertQueue(queue: PersistedQueue) {\n const db = await this.db;\n const queueRecord = await db.get(OBJECT_STORE_NAME, queue.id);\n if (queueRecord) {\n // Queue already exists inside persistor.\n } else {\n await db.add(OBJECT_STORE_NAME, queue);\n }\n }\n async updateQueue(id: QueueID, queue: UpdatePersistedQueue) {\n const db = await this.db;\n const currentRecord = await db.get(OBJECT_STORE_NAME, id);\n\n if (!currentRecord) {\n return;\n }\n\n const updatedRecord = {\n ...currentRecord,\n ...queue,\n };\n await db.put(OBJECT_STORE_NAME, updatedRecord);\n }\n async getAll() {\n const db = await this.db;\n const results = await db.getAll(OBJECT_STORE_NAME);\n\n return results;\n }\n async deleteQueue(id: QueueID) {\n const db = await this.db;\n const currentRecord = await db.get(OBJECT_STORE_NAME, id);\n\n if (currentRecord) {\n await db.delete(OBJECT_STORE_NAME, id);\n }\n }\n}\n\nexport default Persistor;\n", "import { v4 as uuidv4 } from 'uuid';\nimport { ManagerContext, QueueDef, QueueID } from './manager';\nimport { QueueStorage, Status } from './types';\n\ntype TaskId = string;\nexport type TaskState = {\n status: Status;\n blockedFor: any;\n};\n\nexport interface QueueContext {\n _queue?: {\n id: string;\n };\n}\nexport type NextParams = {\n context: ManagerContext;\n};\n\nexport interface QueueState {\n status: Status;\n activeTaskIndex: number;\n tasks: {\n [key in TaskId]: TaskState;\n };\n}\n\nexport interface Task {\n id: TaskId;\n action: string;\n}\n\nexport type InitTasks = {\n tasks: Task[];\n state: QueueState;\n storage: QueueStorage;\n};\n\nexport interface TaskEvent {\n id: TaskId;\n task: TaskState;\n action: string;\n}\n\nexport interface QueueEventHandlers {\n // all tasks\n onUpdateListStatus: (status: Status) => void;\n // single task\n onCreate: (event: TaskEvent) => void;\n onUpdate: (event: TaskEvent) => void;\n onStorageUpdate: (data: QueueStorage) => void;\n onBlock: (\n data: Omit<TaskEvent, 'task'> & { reason: Record<string, unknown> }\n ) => void;\n onUnblock: (data: { id: string }) => void;\n}\n\ninterface QueueOptions {\n id: QueueID;\n events: QueueEventHandlers;\n actions: QueueDef['actions'];\n}\n\n/**\n *\n * Notes on statuses:\n * - Success: last task has success status\n * - Failed: any of task has been failed\n * - Running: first task is not on pending\n * - Pending: default state. not started\n *\n */\nclass Queue {\n public id: string;\n public state: QueueState = {\n status: Status.PENDING,\n activeTaskIndex: 0,\n tasks: {},\n };\n public tasks: Task[] = [];\n private events: QueueOptions['events'];\n private actions: QueueOptions['actions'];\n private storage: QueueStorage = {};\n\n constructor(options: QueueOptions) {\n this.id = options.id;\n this.events = options.events;\n this.actions = options.actions;\n }\n\n /**\n * Update queue status and trigger an event\n *\n */\n private updateQueueStatus(status: Status) {\n this.state.status = status;\n this.events.onUpdateListStatus(status);\n }\n\n private updateActiveTaskIndex(index: number) {\n this.state.activeTaskIndex = index;\n }\n\n /**\n *\n * Update task state (`status`, `blockedFor`) and trigger an event.\n * @param id\n * @param nextState\n */\n private updateTaskState(id: TaskId, nextState: Partial<TaskState>) {\n if (nextState.status) {\n this.state.tasks[id].status = nextState.status;\n }\n if (nextState.blockedFor) {\n this.state.tasks[id].blockedFor = nextState.blockedFor;\n }\n\n const updatedTaskEvent = {\n id: id,\n task: this.get(id)!,\n action: this.tasks.find((task) => task.id === id)!.action,\n };\n this.events.onUpdate(updatedTaskEvent);\n }\n\n /**\n * Create a task by providing an `action` name.\n *\n * this method creating the task, push it to the queue's tasks and trigger an event.\n * @param action\n */\n createTask(action: string) {\n const id = uuidv4();\n this.tasks.push({\n action,\n id,\n });\n this.state.tasks[id] = {\n status: Status.PENDING,\n blockedFor: null,\n };\n\n const createdTask = this.get(id);\n this.events.onCreate({\n id,\n task: createdTask!,\n action,\n });\n }\n\n /**\n * Initilize a queue with some tasks, instead of an empty queue.\n *\n * Using it for recover the queue state from persistor.\n *\n */\n public initTasks(info: InitTasks) {\n this.state = info.state;\n this.storage = info.storage;\n\n info.tasks.forEach((task) => {\n this.tasks.push(task);\n const action = this.tasks.find((t) => t.id === task.id)!.action;\n this.events.onCreate({\n id: task.id,\n task: this.get(task.id)!,\n action,\n });\n });\n }\n\n public checkBlock() {\n const currentActiveTask = this.getActiveTask();\n\n if (!currentActiveTask) {\n return;\n }\n const { task, state } = currentActiveTask;\n\n if (state.status === Status.BLOCKED) {\n this.events.onBlock({\n action: task.action,\n id: task.id,\n reason: state.blockedFor,\n });\n }\n }\n\n /**\n * Getting task state by ID\n */\n public get(id: string): TaskState | null {\n const task = this.state.tasks[id];\n\n if (!task) return null;\n\n return task;\n }\n\n /**\n *\n * Checking if status of the last is `SUCCESS` or not\n *\n */\n private lastTaskIsSuccessful() {\n const lastTask = this.tasks[this.tasks.length - 1];\n\n // checking for empty lists.\n if (lastTask) {\n const lastTaskState = this.state.tasks[lastTask.id];\n\n // Maybe we didn't create the state yet. It should has success status as well.\n if (!!lastTaskState && lastTaskState.status === Status.SUCCESS) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * If the first task started (it's not PENDING),\n * it means the queue has been ran.\n *\n * @returns\n */\n private firstTaskIsStarted() {\n const firstTask = this.tasks[0];\n\n // checking for empty lists.\n if (firstTask) {\n const firstTaskState = this.state.tasks[firstTask.id];\n\n // Maybe we didn't create the state yet.\n if (!!firstTaskState) {\n if (firstTaskState.status !== Status.PENDING) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Getting active task index from state and\n * returns the task and its state.\n *\n */\n private getActiveTask() {\n // First try to get task with `activeTask`\n const index = this.state.activeTaskIndex;\n const task = this.tasks[index];\n\n // Consider all the tasks has been executed.\n if (!task) {\n return null;\n }\n\n const state = this.state.tasks[task.id];\n\n return { task, state, index };\n }\n\n /**\n * Update and find the queue status by checking state of each tasks in the queue.\n */\n public check() {\n const currentListStatus = this.state.status;\n let nextListStatus = this.firstTaskIsStarted()\n ? Status.RUNNING\n : Status.PENDING;\n\n if (this.lastTaskIsSuccessful()) {\n nextListStatus = Status.SUCCESS;\n } else {\n // Is there any failed task?\n for (const task of this.tasks) {\n const state = this.state.tasks[task.id];\n\n // If one item fails, we stop to work on the list.\n if (state.status === Status.FAILED) {\n nextListStatus = Status.FAILED;\n break;\n }\n }\n }\n\n // We only update and trigger an event when there is a new value\n if (nextListStatus !== currentListStatus) {\n this.updateQueueStatus(nextListStatus);\n }\n }\n\n /**\n * Execute active task.\n * Based on the state of active task, the behaviour is different. If status is:\n * - Success -> we need to go to next task by updating the active index and try `next` on more time.\n * - Failed, Running, or no active task -> doesn't do anything.\n * - Pending or Blocked -> update the task and queue status to running, and execute the provided `action` for the task.\n *\n * The queue is a linked list somehow, active task means the pointer to where we are in the queue right now.\n *\n */\n public next(params: NextParams) {\n this.check();\n\n const currentActiveTask = this.getActiveTask();\n\n if (!currentActiveTask) {\n return;\n }\n\n const {\n index: activeTaskIndex,\n task: activeTask,\n state: activeTaskState,\n } = currentActiveTask;\n\n // if `activeTask` is already done, we will go for next one.\n if (activeTaskState.status === Status.SUCCESS) {\n this.updateActiveTaskIndex(activeTaskIndex + 1);\n this.next(params);\n return;\n }\n\n if (\n [Status.FAILED, Status.CANCELED, Status.RUNNING].includes(\n activeTaskState.status\n )\n ) {\n return;\n }\n\n if (\n activeTaskState.status === Status.PENDING ||\n activeTaskState.status === Status.BLOCKED\n ) {\n // Update task status to `running`\n this.updateTaskState(activeTask.id, {\n status: Status.RUNNING,\n });\n this.updateQueueStatus(Status.RUNNING);\n\n // Try to execute task.\n const execute = this.actions[activeTask.action];\n execute({\n context: this.getContext(params),\n next: () => {\n this.markCurrentTaskAsFinished(params);\n },\n retry: () => {\n this.resume(params);\n },\n failed: () => {\n this.updateTaskState(activeTask.id, {\n status: Status.FAILED,\n });\n this.check();\n },\n schedule: (action) => {\n this.createTask(action);\n this.check();\n },\n getStorage: this.getStorage.bind(this),\n setStorage: this.setStorage.bind(this),\n block: (reason: Record<string, unknown>) => {\n this.block({ reason });\n },\n unblock: () => {\n this.unblock();\n },\n });\n }\n }\n\n /**\n * Change the `status` of active task and queue to BLOCKED, then trigger an event.\n */\n public block({\n reason,\n silent = false,\n }: {\n reason: Record<string, unknown>;\n silent?: boolean;\n }) {\n const currentActiveTask = this.getActiveTask();\n\n if (!currentActiveTask) {\n throw new Error(\"Task isn't exist.\");\n }\n\n this.updateTaskState(currentActiveTask.task.id, {\n status: Status.BLOCKED,\n blockedFor: reason,\n });\n this.updateQueueStatus(Status.BLOCKED);\n\n if (!silent) {\n this.events.onBlock({\n action: currentActiveTask.task.action,\n id: currentActiveTask.task.id,\n reason,\n });\n }\n }\n\n /**\n * If the active task is `BLOCKED`, update the task status to `PENDING`, queue status to `RUNNING`\n * then trigger an event.\n */\n public unblock() {\n const currentActiveTask = this.getActiveTask();\n\n if (\n !currentActiveTask ||\n currentActiveTask.state.status !== Status.BLOCKED\n ) {\n throw new Error('Task is not blocked.');\n }\n\n this.updateTaskState(currentActiveTask.task.id, {\n status: Status.PENDING,\n });\n this.updateQueueStatus(Status.RUNNING);\n this.events.onUnblock({ id: currentActiveTask.task.id });\n }\n\n /**\n * If the active task is `BLOCKED` then execute the `action` for the task.\n *\n * It is useful for when we need to run a blocked task without changing the status of task at the first place.\n * For scenarios like we have some conditions in `action` and needs to run the `action` again\n * to check the conditions are met or not, if yes, so we can proceed the `action`.\n *\n */\n public forceRun(params: NextParams) {\n const currentTask = this.getActiveTask();\n\n if (!currentTask || currentTask.state.status !== Status.BLOCKED) {\n throw new Error('Task is not blocked.');\n }\n\n // Try to execute task.\n const execute = this.actions[currentTask.task.action];\n execute({\n context: this.getContext(params),\n next: () => {\n /*\n NOTE:\n When running `forceRun`, the status of task can be `BLOCKED`\n So we need to change to `Running` first. \n */\n // Update task status to `running`\n this.updateTaskState(currentTask.task.id, {\n status: Status.RUNNING,\n });\n this.updateQueueStatus(Status.RUNNING);\n\n this.markCurrentTaskAsFinished(params);\n },\n retry: () => {\n this.resume(params);\n },\n failed: () => {\n this.updateTaskState(currentTask.task.id, {\n status: Status.FAILED,\n });\n this.check();\n },\n schedule: (action) => {\n this.createTask(action);\n this.check();\n },\n getStorage: this.getStorage.bind(this),\n setStorage: this.setStorage.bind(this),\n block: (reason: Record<string, unknown>) => {\n this.block({ reason });\n },\n unblock: () => {\n this.unblock();\n },\n });\n }\n private markCurrentTaskAsFinished(params: NextParams) {\n this.check();\n const activeTaskIndex = this.state.activeTaskIndex;\n const activeTask = this.tasks[activeTaskIndex];\n\n if (!activeTask) return;\n\n const activeTaskState = this.state.tasks[activeTask.id];\n if (activeTaskState.status === Status.RUNNING) {\n this.updateTaskState(activeTask.id, {\n status: Status.SUCCESS,\n });\n this.updateActiveTaskIndex(activeTaskIndex + 1);\n\n const updatedTaskEvent = {\n id: activeTask.id,\n task: this.get(activeTask.id)!,\n action: this.tasks.find((task) => task.id === activeTask.id)!.action,\n };\n this.events.onUpdate(updatedTaskEvent);\n this.next(params);\n }\n }\n\n /**\n * If the active task is `RUNNING`, change it to `PENING` the try to run the task by calling `next`.\n * If it's other than `RUNNING` we reset the queue state and run the queue from the beggining.\n *\n * @param params\n * @returns\n */\n public resume(params: NextParams) {\n const activeTaskIndex = this.state.activeTaskIndex;\n const activeTask = this.tasks[activeTaskIndex];\n if (!activeTask) return;\n\n const activeTaskState = this.state.tasks[activeTask.id];\n if (activeTaskState.status === Status.RUNNING) {\n this.updateTaskState(activeTask.id, {\n status: Status.PENDING,\n });\n this.next(params);\n } else {\n this.resetState();\n this.next(params);\n }\n }\n\n /**\n *\n * Cancel the queue by changing active task and queue status to `CANCELED`.\n *\n */\n public cancel() {\n const currentActiveTask = this.getActiveTask();\n\n if (\n !currentActiveTask ||\n [Status.FAILED, Status.CANCELED, Status.SUCCESS].includes(\n currentActiveTask.state.status\n )\n ) {\n return;\n }\n\n const { task } = currentActiveTask;\n\n // Update task status to `canceled`\n this.updateTaskState(task.id, {\n status: Status.CANCELED,\n });\n const updatedTaskEvent = {\n id: task.id,\n task: this.get(task.id)!,\n action: this.tasks.find((t) => t.id === task.id)!.action,\n };\n this.events.onUpdate(updatedTaskEvent);\n\n // Update queue status to `canceled`\n this.updateQueueStatus(Status.CANCELED);\n }\n\n /**\n * Update queue status, and all the tasks inside queue to `PENDING`.\n */\n private resetState() {\n this.state.activeTaskIndex = 0;\n this.state.status = Status.PENDING;\n Object.keys(this.state.tasks).forEach((id) => {\n this.state.tasks[id].status = Status.PENDING;\n });\n }\n\n public getStorage() {\n return this.storage;\n }\n public setStorage(data: QueueStorage) {\n this.storage = data;\n this.events.onStorageUpdate(data);\n return this.storage;\n }\n\n private getContext(params: NextParams): QueueContext & ManagerContext {\n return {\n ...params.context,\n _queue: {\n id: this.id,\n },\n };\n }\n}\n\nexport default Queue;\n", "import { QueueID, QueueName } from './manager';\nimport Queue, { QueueState, Task } from './queue';\n\nexport enum Status {\n PENDING = 'PENDING',\n RUNNING = 'RUNNING',\n FAILED = 'FAILED',\n SUCCESS = 'SUCCESS',\n CANCELED = 'CANCELED',\n BLOCKED = 'BLOCKED',\n}\n\nexport const SYNC_POLLING_INTERVAL = 5_000\n\nexport type QueueStorage = Record<string, unknown>;\n\nexport type QueueType = Queue;\n\nexport interface PersistedQueue {\n id: QueueID;\n createdAt: number;\n name: QueueName;\n status: Status;\n state: QueueState;\n tasks: Task[];\n storage: QueueStorage;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["uuidv4", "DB_NAME", "OBJECT_STORE_NAME", "Persistor", "idb", "DB_NAME", "db", "OBJECT_STORE_NAME", "queue", "id", "currentRecord", "updatedRecord", "__name", "persistor_default", "uuidv4", "Status", "SYNC_POLLING_INTERVAL", "Queue", "options", "status", "index", "id", "nextState", "updatedTaskEvent", "task", "action", "uuidv4", "createdTask", "info", "t", "currentActiveTask", "state", "lastTask", "lastTaskState", "firstTask", "firstTaskState", "currentListStatus", "nextListStatus", "params", "activeTaskIndex", "activeTask", "activeTaskState", "execute", "reason", "silent", "currentTask", "data", "__name", "queue_default", "Manager", "options", "defaultEventHandlers", "qDef", "persistor_default", "name", "storage", "def", "queue_id", "uuidv4", "createdAt", "list", "createdQueue", "args", "action", "e", "q", "data", "queue", "context", "SYNC_POLLING_INTERVAL", "queues", "info", "queue_name", "manager", "queue_default", "task", "status", "event", "blockedTasks", "state", "id", "tasks", "__name"]
7
7
  }
package/dist/manager.d.ts CHANGED
@@ -1,5 +1,7 @@
1
- import Queue, { QueueEventHandlers, TaskEvent } from './queue';
2
- import { QueueStorage, Status } from './types';
1
+ import type { QueueEventHandlers, TaskEvent } from './queue';
2
+ import type { QueueStorage } from './types';
3
+ import Queue from './queue';
4
+ import { Status } from './types';
3
5
  export type ManagerContext = object;
4
6
  export type QueueName = string;
5
7
  export type QueueID = string;
@@ -51,6 +53,7 @@ export interface Events {
51
53
  onUpdateTask: (queue_id: QueueID, event: TaskEvent) => void;
52
54
  onStorageUpdate: (queue_id: QueueID, data: QueueStorage) => void;
53
55
  onTaskBlock: (queue_id: QueueID) => void;
56
+ onDeleteQueue: (queue_id: QueueID) => void;
54
57
  onPersistedDataLoaded: (manager: Manager) => void;
55
58
  }
56
59
  interface ManagerOptions {
@@ -83,44 +86,9 @@ declare class Manager {
83
86
  *
84
87
  * Making an instance, initilize events, setup a persistor and try to recover the last state of the manager.
85
88
  *
86
- * */
87
- constructor(options: ManagerOptions);
88
- /**
89
- *
90
- * Reading persisted data from storage then brings into memory.
91
- *
92
- * Notes:
93
- * - Reset the memory, so we can call this method whenever we want and not only on the initialize process.
94
- * - All the events will be tirggered (like onCreateQueue, onCreateTask, onBlock, ....)
95
- * - Try to `resume` if the status is `running`.
96
- * - Trigger `onPersistedDataLoaded` event when queues recovered from storage.
97
- *
98
- */
99
- private sync;
100
- /**
101
- *
102
- * Making a new instance from `Queue` and adds Manager's event handlers to it.
103
- *
104
- * @returns An instance of `Queue` with wrapped event handlers from Manager.
105
- *
106
- */
107
- private createQueue;
108
- /**
109
- * Go through all tasks (from all queues) and return a list of blocked tasks
110
- *
111
- * @returns a list of blocked tasks including enough information to get the queue and mutate the storage.
112
89
  *
113
90
  */
114
- private getBlockedTasks;
115
- /**
116
- *
117
- * Add a queue to the manager to keep track of the queue and its state.
118
- *
119
- * @param id
120
- * @param queue
121
- * @returns
122
- */
123
- private add;
91
+ constructor(options: ManagerOptions);
124
92
  /**
125
93
  *
126
94
  * Create a new queue by client.
@@ -136,6 +104,17 @@ declare class Manager {
136
104
  create(name: QueueName, storage: QueueStorage, options?: {
137
105
  id?: QueueID;
138
106
  }): Promise<string>;
107
+ /**
108
+ *
109
+ * Reading persisted data from storage then brings into memory.
110
+ *
111
+ * Notes:
112
+ * - Reset the memory, so we can call this method whenever we want and not only on the initialize process.
113
+ * - All the events will be tirggered (like onCreateQueue, onCreateTask, onBlock, ....)
114
+ * - Try to `resume` if the status is `running`.
115
+ * - Trigger `onPersistedDataLoaded` event when queues recovered from storage.
116
+ *
117
+ */
139
118
  /**
140
119
  * Get a queue by its ID.
141
120
  *
@@ -148,6 +127,7 @@ declare class Manager {
148
127
  * @returns a list of queues includes all the queues and their states.
149
128
  */
150
129
  getAll(): Map<string, QueueInfo>;
130
+ deleteQueue(queue_id: QueueID): void;
151
131
  /**
152
132
  *
153
133
  * Ask from manager to run pending queues.
@@ -189,14 +169,6 @@ declare class Manager {
189
169
  *
190
170
  */
191
171
  forceExecute(queue_id: string, data?: object): void;
192
- /**
193
- *
194
- * Sync in-memory state (of `Manager`) with storage (persist).
195
- *
196
- * Usually we call this method after a change detected in the state of manager.
197
- *
198
- */
199
- private handleUpdate;
200
172
  /**
201
173
  * Active readonly mode for manager, it means it doesn't run anythin,
202
174
  * And only can be used to read the data.
@@ -206,6 +178,39 @@ declare class Manager {
206
178
  * Activate normal mode which means it will be able to run the queuese as well.
207
179
  */
208
180
  run(): void;
181
+ private sync;
182
+ /**
183
+ *
184
+ * Making a new instance from `Queue` and adds Manager's event handlers to it.
185
+ *
186
+ * @returns An instance of `Queue` with wrapped event handlers from Manager.
187
+ *
188
+ */
189
+ private createQueue;
190
+ /**
191
+ * Go through all tasks (from all queues) and return a list of blocked tasks
192
+ *
193
+ * @returns a list of blocked tasks including enough information to get the queue and mutate the storage.
194
+ *
195
+ */
196
+ private getBlockedTasks;
197
+ /**
198
+ *
199
+ * Add a queue to the manager to keep track of the queue and its state.
200
+ *
201
+ * @param id
202
+ * @param queue
203
+ * @returns
204
+ */
205
+ private add;
206
+ /**
207
+ *
208
+ * Sync in-memory state (of `Manager`) with storage (persist).
209
+ *
210
+ * Usually we call this method after a change detected in the state of manager.
211
+ *
212
+ */
213
+ private handleUpdate;
209
214
  private getContext;
210
215
  private shouldExecute;
211
216
  }
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../src/manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAK5C,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,EAAE,MAAM,EAAyB,MAAM,SAAS,CAAC;AAExD,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AACpC,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC;AAC/B,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC;AAC7B,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,YAAY,CAAC;QACxB,GAAG,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC;KAC3C,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC;AAElD,MAAM,WAAW,eAAe,CAC9B,CAAC,SAAS,YAAY,GAAG,YAAY,EACrC,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,GAAG,cAAc;IAElB,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,QAAQ,EAAE,CAAC,UAAU,EAAE,CAAC,KAAK,IAAI,CAAC;IAClC,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC,CAAC;IACpB,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjD,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,MAAM,WAAW,QAAQ,CACvB,CAAC,SAAS,YAAY,GAAG,YAAY,EACrC,CAAC,SAAS,MAAM,GAAG,MAAM,EACzB,CAAC,GAAG,cAAc;IAElB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE;SACN,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;KACtE,CAAC;IACF,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACrC,GAAG,EAAE,CAAC,EAAE,CAAC;IACT,eAAe,CAAC,EAAE,CAChB,KAAK,EAAE,GAAG,EACV,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,KAAK,CAAC;QACb,OAAO,EAAE,CAAC,CAAC;QACX,eAAe,EAAE,MAAM,WAAW,EAAE,CAAC;QACrC,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QACxD,KAAK,EAAE,MAAM,IAAI,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;KAClB,KACE,IAAI,CAAC;CACX;AAED,MAAM,WAAW,MAAM;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG;QAAE,EAAE,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;IAC5D,aAAa,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC7D,YAAY,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5D,YAAY,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5D,eAAe,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IACjE,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,aAAa,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,qBAAqB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACnD;AAED,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IACzB,UAAU,EAAE,QAAQ,EAAE,CAAC;IACvB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,IAAI,CAAC;QAChB,MAAM,EAAE,MAAM,IAAI,CAAC;QACnB,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC;QAC5B,UAAU,EAAE,MAAM,GAAG,CAAC;KACvB,CAAC;CACH;AAED,cAAM,OAAO;IACX,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,YAAY,CAA6B;IAEjD;;;;;OAKG;gBACS,OAAO,EAAE,cAAc;IAoDnC;;;;;;;;;;;OAWG;IACU,MAAM,CACjB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,YAAY,EACrB,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,OAAO,CAAA;KAAE;IAiE5B;;;;;;;;;;OAUG;IAEH;;;;OAIG;IACI,GAAG,CAAC,QAAQ,EAAE,OAAO;IAI5B;;;;OAIG;IACI,MAAM;IAIN,WAAW,CAAC,QAAQ,EAAE,OAAO;IAIpC;;;;;;OAMG;IACI,OAAO;IAYd;;;;;;;;OAQG;IACI,MAAM;IAkBb;;;;;;;;;;;;OAYG;IACI,KAAK;IAeZ;;;;;;;OAOG;IACI,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;IAenD;;;OAGG;IACI,KAAK;IAUZ;;OAEG;IACI,GAAG;YAYI,IAAI;IAyDlB;;;;;;OAMG;IACH,OAAO,CAAC,WAAW;IAwFnB;;;;;OAKG;IACH,OAAO,CAAC,eAAe;IA4BvB;;;;;;;OAOG;IACH,OAAO,CAAC,GAAG;IAQX;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAgBpB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,aAAa;CAGtB;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -1,6 +1,6 @@
1
+ import type { QueueID } from './manager';
2
+ import type { PersistedQueue } from './types';
1
3
  import type { DBSchema, IDBPDatabase } from 'idb';
2
- import { QueueID } from './manager';
3
- import { PersistedQueue } from './types';
4
4
  export declare const DB_NAME = "queues-manager";
5
5
  type UpdatePersistedQueue = Partial<Pick<PersistedQueue, 'status' | 'state' | 'tasks' | 'storage'>>;
6
6
  interface Database extends DBSchema {
@@ -15,6 +15,7 @@ declare class Persistor {
15
15
  insertQueue(queue: PersistedQueue): Promise<void>;
16
16
  updateQueue(id: QueueID, queue: UpdatePersistedQueue): Promise<void>;
17
17
  getAll(): Promise<PersistedQueue[]>;
18
+ deleteQueue(id: QueueID): Promise<void>;
18
19
  }
19
20
  export default Persistor;
20
21
  //# sourceMappingURL=persistor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"persistor.d.ts","sourceRoot":"","sources":["../src/persistor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAElD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,eAAO,MAAM,OAAO,mBAAmB,CAAC;AAIxC,KAAK,oBAAoB,GAAG,OAAO,CACjC,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC,CAC/D,CAAC;AAEF,UAAU,QAAS,SAAQ,QAAQ;IACjC,MAAM,EAAE;QACN,KAAK,EAAE,cAAc,CAAC;QACtB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;CACH;AAED,cAAM,SAAS;IACb,EAAE,EAAE,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;;IAe9B,WAAW,CAAC,KAAK,EAAE,cAAc;IASjC,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB;IAYpD,MAAM;CAMb;AAED,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"persistor.d.ts","sourceRoot":"","sources":["../src/persistor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,KAAK,CAAC;AAElD,eAAO,MAAM,OAAO,mBAAmB,CAAC;AAIxC,KAAK,oBAAoB,GAAG,OAAO,CACjC,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,SAAS,CAAC,CAC/D,CAAC;AAEF,UAAU,QAAS,SAAQ,QAAQ;IACjC,MAAM,EAAE;QACN,KAAK,EAAE,cAAc,CAAC;QACtB,GAAG,EAAE,MAAM,CAAC;KACb,CAAC;CACH;AAED,cAAM,SAAS;IACb,EAAE,EAAE,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;;IAe9B,WAAW,CAAC,KAAK,EAAE,cAAc;IASjC,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,oBAAoB;IAcpD,MAAM;IAMN,WAAW,CAAC,EAAE,EAAE,OAAO;CAQ9B;AAED,eAAe,SAAS,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rango-dev/queue-manager-core",
3
- "version": "0.14.0",
3
+ "version": "0.15.1-next.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",
package/src/manager.ts CHANGED
@@ -1,8 +1,12 @@
1
- import Persistor from './persistor';
2
- import Queue, { QueueEventHandlers, TaskEvent } from './queue';
3
- import { QueueStorage, SYNC_POLLING_INTERVAL, Status } from './types';
1
+ import type { QueueEventHandlers, TaskEvent } from './queue';
2
+ import type { QueueStorage } from './types';
3
+
4
4
  import { v4 as uuidv4 } from 'uuid';
5
5
 
6
+ import Persistor from './persistor';
7
+ import Queue from './queue';
8
+ import { Status, SYNC_POLLING_INTERVAL } from './types';
9
+
6
10
  export type ManagerContext = object;
7
11
  export type QueueName = string;
8
12
  export type QueueID = string;
@@ -67,6 +71,7 @@ export interface Events {
67
71
  onUpdateTask: (queue_id: QueueID, event: TaskEvent) => void;
68
72
  onStorageUpdate: (queue_id: QueueID, data: QueueStorage) => void;
69
73
  onTaskBlock: (queue_id: QueueID) => void;
74
+ onDeleteQueue: (queue_id: QueueID) => void;
70
75
  onPersistedDataLoaded: (manager: Manager) => void;
71
76
  }
72
77
 
@@ -96,7 +101,7 @@ class Manager {
96
101
  private events: Events;
97
102
  private persistor: Persistor;
98
103
  private context: ManagerContext;
99
- private isPaused: boolean = false;
104
+ private isPaused = false;
100
105
  // The client won't get any update on pause, We are using a polling mode to fix this issue for now.
101
106
  private syncInterval: NodeJS.Timer | null = null;
102
107
 
@@ -104,7 +109,8 @@ class Manager {
104
109
  *
105
110
  * Making an instance, initilize events, setup a persistor and try to recover the last state of the manager.
106
111
  *
107
- * */
112
+ *
113
+ */
108
114
  constructor(options: ManagerOptions) {
109
115
  const defaultEventHandlers: Events = {
110
116
  onCreateQueue: () => {
@@ -128,6 +134,9 @@ class Manager {
128
134
  onPersistedDataLoaded: () => {
129
135
  // ..
130
136
  },
137
+ onDeleteQueue: () => {
138
+ // ...
139
+ },
131
140
  };
132
141
 
133
142
  if (options.events) {
@@ -145,13 +154,95 @@ class Manager {
145
154
 
146
155
  this.context = options.context || {};
147
156
  this.persistor = new Persistor();
148
- this.sync();
157
+
158
+ void this.sync();
149
159
 
150
160
  if (options.isPaused) {
151
161
  this.pause();
152
162
  }
153
163
  }
154
164
 
165
+ // Create a new queue
166
+ /**
167
+ *
168
+ * Create a new queue by client.
169
+ *
170
+ * It will do the internal things to make a queue from definitions, and running using Manager.
171
+ *
172
+ * Notes:
173
+ * - After creating the queue, it will be run automatically.
174
+ *
175
+ * @returns an ID for queue so it can be used to get the created queue later by client.
176
+ *
177
+ */
178
+ public async create(
179
+ name: QueueName,
180
+ storage: QueueStorage,
181
+ options?: { id?: QueueID }
182
+ ) {
183
+ if (!this.queuesDefs.has(name)) {
184
+ throw new Error('You need to add a queue definition first.');
185
+ }
186
+
187
+ try {
188
+ const def = this.queuesDefs.get(name)!;
189
+ const queue_id: QueueID = options?.id || uuidv4();
190
+ const createdAt = Date.now();
191
+ const list = this.createQueue({
192
+ queue_id: queue_id,
193
+ queue_name: name,
194
+ });
195
+ list.setStorage(storage);
196
+
197
+ const createdQueue = this.add(queue_id, {
198
+ list,
199
+ createdAt,
200
+ name,
201
+ status: Status.PENDING,
202
+ actions: {
203
+ run: () => {
204
+ list.next({
205
+ context: this.getContext(),
206
+ });
207
+ },
208
+ cancel: () => {
209
+ list.cancel();
210
+ },
211
+ setStorage: (...args) => {
212
+ list.setStorage(...args);
213
+ },
214
+ getStorage: () => {
215
+ return list.getStorage();
216
+ },
217
+ },
218
+ });
219
+
220
+ /*
221
+ * Persist initial queue
222
+ * Note: we need to first insert the queue, and then it can be updated by internal events.
223
+ */
224
+ await this.persistor.insertQueue({
225
+ id: queue_id,
226
+ createdAt,
227
+ name: createdQueue.name,
228
+ status: createdQueue.status,
229
+ tasks: list.tasks,
230
+ state: list.state,
231
+ storage: list.getStorage(),
232
+ });
233
+
234
+ // adding initial tasks
235
+ def.run.forEach((action) => {
236
+ list.createTask(action);
237
+ });
238
+
239
+ // After creating a new queue, try to run.
240
+ this.execute();
241
+ return queue_id;
242
+ } catch (e) {
243
+ throw new Error((e as any)?.message);
244
+ }
245
+ }
155
246
  /**
156
247
  *
157
248
  * Reading persisted data from storage then brings into memory.
@@ -163,6 +254,155 @@ class Manager {
163
254
  * - Trigger `onPersistedDataLoaded` event when queues recovered from storage.
164
255
  *
165
256
  */
257
+
258
+ /**
259
+ * Get a queue by its ID.
260
+ *
261
+ * @returns An object includes queue and its state in `Manager`.
262
+ */
263
+ public get(queue_id: QueueID) {
264
+ return this.queues.get(queue_id);
265
+ }
266
+
267
+ /**
268
+ * Get all queues from `Manager`
269
+ *
270
+ * @returns a list of queues includes all the queues and their states.
271
+ */
272
+ public getAll() {
273
+ return this.queues;
274
+ }
275
+
276
+ public deleteQueue(queue_id: QueueID) {
277
+ this.queues.delete(queue_id);
278
+ void this.persistor.deleteQueue(queue_id);
279
+ }
280
+ /**
281
+ *
282
+ * Ask from manager to run pending queues.
283
+ *
284
+ * It only try to run queues with `PENDING` status and ignore all the other statuses.
285
+ *
286
+ */
287
+ public execute() {
288
+ if (!this.shouldExecute()) {
289
+ return;
290
+ }
291
+
292
+ for (const [, q] of Array.from(this.queues)) {
293
+ if (q.status === Status.PENDING) {
294
+ q.actions.run();
295
+ }
296
+ }
297
+ }
298
+
299
+ /**
300
+ *
301
+ * Try to find queues with `RUNNING` status to run them again.
302
+ *
303
+ * It's useful for recovering the queue at some certain points
304
+ * like running a currepted task (reloaded when it was running) or needs manual trigger from UI.
305
+ *
306
+ * @returns
307
+ */
308
+ public resume() {
309
+ if (!this.shouldExecute()) {
310
+ return;
311
+ }
312
+
313
+ for (const [, q] of Array.from(this.queues)) {
314
+ if (q.status === Status.RUNNING) {
315
+ q.list.resume({
316
+ context: this.getContext(),
317
+ });
318
+ return;
319
+ }
320
+ }
321
+
322
+ // If there is no running queue, try to run a new queue.
323
+ this.execute();
324
+ }
325
+
326
+ /**
327
+ *
328
+ * Run all `BLOCKED` queues once again.
329
+ *
330
+ * If a queue has `BLOCKED` status and the last task is `BLOCKED` as well,
331
+ * The task will be run one more time.
332
+ *
333
+ * Useful for scenarios like we are blocking the queue under some conditions in task,
334
+ * We can use this method to ask the queue to run the blocked task one more time and
335
+ * maybe this time condtions are met and the queue can be proceed.
336
+ *
337
+ * @returns
338
+ */
339
+ public retry() {
340
+ if (!this.shouldExecute()) {
341
+ return;
342
+ }
343
+
344
+ for (const [, q] of Array.from(this.queues)) {
345
+ if (q.status === Status.BLOCKED) {
346
+ q.list.checkBlock();
347
+ }
348
+ }
349
+
350
+ // If there is no running queue, try to run a new queue.
351
+ this.execute();
352
+ }
353
+
354
+ /**
355
+ *
356
+ * Run a blocked task on a specific queue with the ability to pass more data.
357
+ *
358
+ * Useful when we have a custom logic for running queue and needs to pass some specific data
359
+ * to the task and try to run it manually with the provided data.
360
+ *
361
+ */
362
+ public forceExecute(queue_id: string, data?: object) {
363
+ const queue = this.get(queue_id);
364
+ let context = this.getContext();
365
+ if (data) {
366
+ context = {
367
+ ...context,
368
+ ...data,
369
+ };
370
+ }
371
+
372
+ queue?.list.forceRun({
373
+ context,
374
+ });
375
+ }
376
+
377
+ /**
378
+ * Active readonly mode for manager, it means it doesn't run anythin,
379
+ * And only can be used to read the data.
380
+ */
381
+ public pause() {
382
+ if (this.isPaused) {
383
+ return;
384
+ }
385
+ this.isPaused = true;
386
+ this.syncInterval = setInterval(() => {
387
+ void this.sync();
388
+ }, SYNC_POLLING_INTERVAL);
389
+ }
390
+
391
+ /**
392
+ * Activate normal mode which means it will be able to run the queuese as well.
393
+ */
394
+ public run() {
395
+ // If call this method multiple times, it should be run for once.
396
+ if (this.isPaused) {
397
+ this.isPaused = false;
398
+ if (!!this.syncInterval) {
399
+ clearInterval(this.syncInterval);
400
+ this.syncInterval = null;
401
+ }
402
+ void this.sync();
403
+ }
404
+ }
405
+
166
406
  private async sync() {
167
407
  try {
168
408
  // Reading queues from storage
@@ -227,13 +467,9 @@ class Manager {
227
467
  * @returns An instance of `Queue` with wrapped event handlers from Manager.
228
468
  *
229
469
  */
230
- private createQueue({
231
- queue_id,
232
- queue_name,
233
- }: {
234
- queue_id: QueueID;
235
- queue_name: QueueName;
236
- }) {
470
+ private createQueue(info: { queue_id: QueueID; queue_name: QueueName }) {
471
+ const { queue_id, queue_name } = info;
472
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
237
473
  const manager = this;
238
474
  const def = this.queuesDefs.get(queue_name)!;
239
475
  const list = new Queue({
@@ -243,13 +479,17 @@ class Manager {
243
479
  this.events.onCreateTask(queue_id, task);
244
480
  this.handleUpdate(queue_id);
245
481
 
246
- if (def.events?.onCreate) def.events.onCreate(task);
482
+ if (def.events?.onCreate) {
483
+ def.events.onCreate(task);
484
+ }
247
485
  },
248
486
  onUpdate: (task) => {
249
487
  this.events.onUpdateTask(queue_id, task);
250
488
  this.handleUpdate(queue_id);
251
489
 
252
- if (def.events?.onUpdate) def.events.onUpdate(task);
490
+ if (def.events?.onUpdate) {
491
+ def.events.onUpdate(task);
492
+ }
253
493
  },
254
494
  onUpdateListStatus: (status) => {
255
495
  this.queues.set(queue_id, {
@@ -262,12 +502,15 @@ class Manager {
262
502
 
263
503
  // After finishing a queue, try to run other queues.
264
504
  this.execute();
265
- if (def.events?.onUpdateListStatus)
505
+ if (def.events?.onUpdateListStatus) {
266
506
  def.events.onUpdateListStatus(status);
507
+ }
267
508
  },
268
509
  onStorageUpdate: (data) => {
269
510
  this.events.onStorageUpdate(queue_id, data);
270
- if (def.events?.onStorageUpdate) def.events.onStorageUpdate(data);
511
+ if (def.events?.onStorageUpdate) {
512
+ def.events.onStorageUpdate(data);
513
+ }
271
514
  this.handleUpdate(queue_id);
272
515
  },
273
516
  onBlock: (event) => {
@@ -362,195 +605,6 @@ class Manager {
362
605
  return createdQueue;
363
606
  }
364
607
 
365
- // Create a new queue
366
- /**
367
- *
368
- * Create a new queue by client.
369
- *
370
- * It will do the internal things to make a queue from definitions, and running using Manager.
371
- *
372
- * Notes:
373
- * - After creating the queue, it will be run automatically.
374
- *
375
- * @returns an ID for queue so it can be used to get the created queue later by client.
376
- *
377
- */
378
- public async create(
379
- name: QueueName,
380
- storage: QueueStorage,
381
- options?: { id?: QueueID }
382
- ) {
383
- if (!this.queuesDefs.has(name)) {
384
- throw new Error('You need to add a queue definition first.');
385
- }
386
-
387
- try {
388
- const def = this.queuesDefs.get(name)!;
389
- const queue_id: QueueID = options?.id || uuidv4();
390
- const createdAt = Date.now();
391
- const list = this.createQueue({
392
- queue_id: queue_id,
393
- queue_name: name,
394
- });
395
- list.setStorage(storage);
396
-
397
- const createdQueue = this.add(queue_id, {
398
- list,
399
- createdAt,
400
- name,
401
- status: Status.PENDING,
402
- actions: {
403
- run: () => {
404
- list.next({
405
- context: this.getContext(),
406
- });
407
- },
408
- cancel: () => {
409
- list.cancel();
410
- },
411
- setStorage: (...args) => {
412
- list.setStorage(...args);
413
- },
414
- getStorage: () => {
415
- return list.getStorage();
416
- },
417
- },
418
- });
419
-
420
- // Persist initial queue
421
- // Note: we need to first insert the queue, and then it can be updated by internal events.
422
- await this.persistor.insertQueue({
423
- id: queue_id,
424
- createdAt,
425
- name: createdQueue.name,
426
- status: createdQueue.status,
427
- tasks: list.tasks,
428
- state: list.state,
429
- storage: list.getStorage(),
430
- });
431
-
432
- // adding initial tasks
433
- def.run.forEach((action) => {
434
- list.createTask(action);
435
- });
436
-
437
- // After creating a new queue, try to run.
438
- this.execute();
439
- return queue_id;
440
- } catch (e) {
441
- throw new Error((e as any)?.message);
442
- }
443
- }
444
-
445
- /**
446
- * Get a queue by its ID.
447
- *
448
- * @returns An object includes queue and its state in `Manager`.
449
- */
450
- public get(queue_id: QueueID) {
451
- return this.queues.get(queue_id);
452
- }
453
-
454
- /**
455
- * Get all queues from `Manager`
456
- *
457
- * @returns a list of queues includes all the queues and their states.
458
- */
459
- public getAll() {
460
- return this.queues;
461
- }
462
-
463
- /**
464
- *
465
- * Ask from manager to run pending queues.
466
- *
467
- * It only try to run queues with `PENDING` status and ignore all the other statuses.
468
- *
469
- */
470
- public execute() {
471
- if (!this.shouldExecute()) return;
472
-
473
- for (const [, q] of Array.from(this.queues)) {
474
- if (q.status === Status.PENDING) {
475
- q.actions.run();
476
- }
477
- }
478
- }
479
-
480
- /**
481
- *
482
- * Try to find queues with `RUNNING` status to run them again.
483
- *
484
- * It's useful for recovering the queue at some certain points
485
- * like running a currepted task (reloaded when it was running) or needs manual trigger from UI.
486
- *
487
- * @returns
488
- */
489
- public resume() {
490
- if (!this.shouldExecute()) return;
491
-
492
- for (const [, q] of Array.from(this.queues)) {
493
- if (q.status === Status.RUNNING) {
494
- q.list.resume({
495
- context: this.getContext(),
496
- });
497
- return;
498
- }
499
- }
500
-
501
- // If there is no running queue, try to run a new queue.
502
- this.execute();
503
- }
504
-
505
- /**
506
- *
507
- * Run all `BLOCKED` queues once again.
508
- *
509
- * If a queue has `BLOCKED` status and the last task is `BLOCKED` as well,
510
- * The task will be run one more time.
511
- *
512
- * Useful for scenarios like we are blocking the queue under some conditions in task,
513
- * We can use this method to ask the queue to run the blocked task one more time and
514
- * maybe this time condtions are met and the queue can be proceed.
515
- *
516
- * @returns
517
- */
518
- public retry() {
519
- if (!this.shouldExecute()) return;
520
-
521
- for (const [, q] of Array.from(this.queues)) {
522
- if (q.status === Status.BLOCKED) {
523
- q.list.checkBlock();
524
- }
525
- }
526
-
527
- // If there is no running queue, try to run a new queue.
528
- this.execute();
529
- }
530
-
531
- /**
532
- *
533
- * Run a blocked task on a specific queue with the ability to pass more data.
534
- *
535
- * Useful when we have a custom logic for running queue and needs to pass some specific data
536
- * to the task and try to run it manually with the provided data.
537
- *
538
- */
539
- public forceExecute(queue_id: string, data?: object) {
540
- const queue = this.get(queue_id);
541
- let context = this.getContext();
542
- if (data) {
543
- context = {
544
- ...context,
545
- ...data,
546
- };
547
- }
548
-
549
- queue?.list.forceRun({
550
- context,
551
- });
552
- }
553
-
554
608
  /**
555
609
  *
556
610
  * Sync in-memory state (of `Manager`) with storage (persist).
@@ -565,7 +619,7 @@ class Manager {
565
619
  const status = queue.status;
566
620
  const state = queue.list.state;
567
621
  const tasks = queue.list.tasks;
568
- this.persistor.updateQueue(queue_id, {
622
+ void this.persistor.updateQueue(queue_id, {
569
623
  status,
570
624
  state,
571
625
  tasks,
@@ -574,35 +628,8 @@ class Manager {
574
628
  }
575
629
  }
576
630
 
577
- /**
578
- * Active readonly mode for manager, it means it doesn't run anythin,
579
- * And only can be used to read the data.
580
- */
581
- public pause() {
582
- if (this.isPaused) return;
583
- this.isPaused = true;
584
- this.syncInterval = setInterval(() => {
585
- this.sync();
586
- }, SYNC_POLLING_INTERVAL);
587
- }
588
-
589
- /**
590
- * Activate normal mode which means it will be able to run the queuese as well.
591
- */
592
- public run() {
593
- // If call this method multiple times, it should be run for once.
594
- if (this.isPaused) {
595
- this.isPaused = false;
596
- if (!!this.syncInterval) {
597
- clearInterval(this.syncInterval);
598
- this.syncInterval = null;
599
- }
600
- this.sync();
601
- }
602
- }
603
-
604
631
  private getContext() {
605
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
632
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-ts-comment
606
633
  //@ts-ignore
607
634
  return this.context?.current || {};
608
635
  }
package/src/persistor.ts CHANGED
@@ -1,8 +1,7 @@
1
+ import type { QueueID } from './manager';
2
+ import type { PersistedQueue } from './types';
1
3
  import type { DBSchema, IDBPDatabase } from 'idb';
2
4
 
3
- import { QueueID } from './manager';
4
- import { PersistedQueue } from './types';
5
-
6
5
  export const DB_NAME = 'queues-manager';
7
6
  const OBJECT_STORE_NAME = 'queues';
8
7
  const VERSION = 1;
@@ -22,7 +21,7 @@ class Persistor {
22
21
  db: Promise<IDBPDatabase<Database>>;
23
22
  constructor() {
24
23
  this.db = import('idb')
25
- .then((idb) => {
24
+ .then(async (idb) => {
26
25
  return idb.openDB<Database>(DB_NAME, VERSION, {
27
26
  upgrade(db) {
28
27
  db.createObjectStore(OBJECT_STORE_NAME, { keyPath: 'id' });
@@ -47,7 +46,9 @@ class Persistor {
47
46
  const db = await this.db;
48
47
  const currentRecord = await db.get(OBJECT_STORE_NAME, id);
49
48
 
50
- if (!currentRecord) return;
49
+ if (!currentRecord) {
50
+ return;
51
+ }
51
52
 
52
53
  const updatedRecord = {
53
54
  ...currentRecord,
@@ -61,6 +62,14 @@ class Persistor {
61
62
 
62
63
  return results;
63
64
  }
65
+ async deleteQueue(id: QueueID) {
66
+ const db = await this.db;
67
+ const currentRecord = await db.get(OBJECT_STORE_NAME, id);
68
+
69
+ if (currentRecord) {
70
+ await db.delete(OBJECT_STORE_NAME, id);
71
+ }
72
+ }
64
73
  }
65
74
 
66
75
  export default Persistor;