# All files / services memory-queue.ts

0% Statements 0/80
100% Branches 1/1
100% Functions 1/1
0% Lines 0/80

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119

     /**
     * 内存队列 - 当 Redis 不可用时的 fallback
     * 使用内存 Map 存储任务，支持基本的队列功能
     */

    type JobData = Record<string, any>;
    type JobCallback = (job: any) => Promise<any>;

    interface MemoryJob {
      id: string;
      data: JobData;
      status: 'waiting' | 'active' | 'completed' | 'failed';
      result?: any;
      error?: string;
    }

    class MemoryQueue {
      private jobs: Map<string, MemoryJob> = new Map();
      private waitingJobs: string[] = [];
      private processing: Set<string> = new Set();
      private idCounter: number = 0;
      private concurrency: number = 3;
      private handler: JobCallback | null = null;
      private started: boolean = false;

      async add(name: string, data: JobData): Promise<string> {
        const id = `${name}_${++this.idCounter}_${Date.now()}`;
        const job: MemoryJob = {
          id,
          data,
          status: 'waiting',
        };
        this.jobs.set(id, job);
        this.waitingJobs.push(id);
        console.log(`[MemoryQueue] 任务添加: ${name}#${id}`);

        // 如果已经有 handler，开始处理
        if (this.handler && !this.started) {
          this.startProcessing();
        } else if (this.started && this.processing.size < this.concurrency) {
          // 已经在运行且有空闲槽位，立即处理
          setImmediate(() => this.processLoop());
        }

        return id;
      }

      process(concurrency: number, handler: JobCallback): void {
        this.concurrency = concurrency;
        this.handler = handler;
        this.startProcessing();
      }

      private startProcessing() {
        if (this.started || !this.handler) return;
        this.started = true;

        // 异步处理队列
        setImmediate(() => this.processLoop());
      }

      private async processLoop() {
        while (this.waitingJobs.length > 0 && this.processing.size < this.concurrency) {
          const jobId = this.waitingJobs.shift();
          if (!jobId) break;

          const job = this.jobs.get(jobId);
          if (!job || job.status !== 'waiting') continue;

          this.processing.add(jobId);
          job.status = 'active';

          try {
            console.log(`[MemoryQueue] 开始处理任务: ${jobId}`);
            const mockJob = {
              id: jobId,
              data: job.data,
              progress: (p: number) => { /* 进度回调 */ }
            };
            const result = await this.handler(mockJob);
            job.status = 'completed';
            job.result = result;
            console.log(`[MemoryQueue] 任务完成: ${jobId}`);
          } catch (error: any) {
            job.status = 'failed';
            job.error = error.message;
            console.error(`[MemoryQueue] 任务失败: ${jobId}`, error.message);
          } finally {
            this.processing.delete(jobId);
            // 继续处理下一个
            setImmediate(() => this.processLoop());
          }
        }

        // 如果还有任务没处理完，继续循环
        if (this.waitingJobs.length > 0 || this.processing.size > 0) {
          setTimeout(() => this.processLoop(), 100);
        }
      }

      on(event: string, callback: any): void {
        // 事件处理
      }

      async close(): Promise<void> {
        this.jobs.clear();
        this.waitingJobs = [];
        this.processing.clear();
        this.started = false;
      }

      // 检查是否有待处理任务
      hasPendingJobs(): boolean {
        return this.waitingJobs.length > 0 || this.processing.size > 0;
      }
    }

    // 导出单例
    export const memoryQueue = new MemoryQueue();