0.1.4Updated 6 months ago
import type { Entity } from "@infinity-beyond/infinity.ts";


const tasks: I_Task[] = []
let queue_is_running: boolean = false;

export const TaskQueue = {
  Entities: new Map<string, typeof Entity | Entity>(),

  add(socket: WebSocket, request: I_ProcessorRequest) {
    tasks.push({
      socket,
      request,
      has_run: false
    });

    if(!queue_is_running) TaskQueue.process_queue();
  },

  async process_queue() {
    if(queue_is_running) return false;

    queue_is_running = true;
    while(tasks.length) {
      await this.run_next_queue_item();
    }

    queue_is_running = false;
  },

  async run_next_queue_item(): Promise<boolean> {
    if(!tasks.length) return false;

    let task: I_Task | undefined;
    while(!task || task.has_run) {
      task = tasks.shift();
    }
    if(!task) return false;

    task.has_run = true;

    const entity = TaskQueue.Entities.get(task.request.entity_name);
    if(!entity) return failResponse(task, `Could not find [${task.request.entity_name}]!`);

    const method = (entity as any)[task.request.method] as VagueFunction;
    if(!method) return failResponse(task, `Could not find [${task.request.entity_name}::${task.request.method}()]!`);

    try {
      const response = await method.apply(entity, task.request.args) as Record<string, any>;
      return succeedResponse(task, response);
    } catch(e: any) {
      return failResponse(task, `An error ocurred when trying to execute [${task.request.entity_name}::${task.request.method}()]`, e);
    }
  }
}

const succeedResponse = (task: I_Task, data: Record<string, any>) => {
  task.socket.send(JSON.stringify({
    id: task.request.id,
    success: true,
    data
  }));

  return true;
}

const failResponse = (task: I_Task, message: string, error?: Error) => {
  task.socket.send(JSON.stringify({
    id: task.request.id,
    success: false,
    message,
    error: error && { name: error.name, message: error.message, cause: error.cause }
  }));

  return false;
}