feat: initialize project structure with essential files and configurations

- Add .gitignore to exclude unnecessary files and directories
- Create .npmrc for npm authentication
- Add AGENTS.md for project documentation
- Initialize package.json with project metadata and dependencies
- Implement app.ts to set up the application and project manager
- Create file-search module for searching files in a directory
- Set up project manager and listener for managing project files
- Implement project search functionality with MeiliSearch integration
- Add routes for authentication and project management
- Create scheduler for task management
- Add tests for file searching and project management functionalities
This commit is contained in:
xiongxiao
2026-03-13 17:22:14 +08:00
committed by cnb
commit 1b131b3961
27 changed files with 1336 additions and 0 deletions

56
src/scheduler/index.ts Normal file
View File

@@ -0,0 +1,56 @@
/**
* 任务调度器
* - FIFO 先进先出队列
* - 单线程执行(一次只执行一个任务)
* - 去重:同一个 key 的任务如果已在队列中等待(未执行),则不重复添加
*/
type Task = {
key: string;
execute: () => Promise<void>;
};
export class Scheduler {
private queue: Task[] = [];
private running = false;
/** 当前在队列中等待执行的任务 key 集合(不含正在执行的) */
private pendingKeys = new Set<string>();
/**
* 添加任务
* @param key 任务唯一标识(如文件路径)
* @param execute 任务执行函数
* @returns true 表示已加入队列false 表示该 key 已存在,跳过
*/
add(key: string, execute: () => Promise<void>): boolean {
if (this.pendingKeys.has(key)) {
// 同一任务已在队列中,跳过
return false;
}
this.pendingKeys.add(key);
this.queue.push({ key, execute });
// 触发执行(如果没有在跑的话)
this._run();
return true;
}
private async _run() {
if (this.running) return;
this.running = true;
while (this.queue.length > 0) {
const task = this.queue.shift()!;
// 任务开始执行前,从 pendingKeys 移除,允许后续同 key 任务重新入队
this.pendingKeys.delete(task.key);
try {
await task.execute();
} catch (err) {
console.error(`[Scheduler] Task "${task.key}" failed:`, err);
}
}
this.running = false;
}
/** 队列中等待执行的任务数量(不含正在执行的) */
get pendingCount(): number {
return this.queue.length;
}
}