@@ -47,6 +47,62 @@ runner
4747
4848 const status = await pool . checkFreshness ( 'missing.txt' ) ;
4949 expect . toEqual ( status . isFresh , false ) ;
50+ } )
51+
52+ . test ( '并发 recordEdit 不会创建重复 watcher' , async ( ) => {
53+ const dir = createTempDir ( 'concurrent' ) ;
54+ const filePath = path . join ( dir , 'test.txt' ) ;
55+ fs . writeFileSync ( filePath , 'content' ) ;
56+
57+ const sandbox = new LocalSandbox ( { workDir : dir , enforceBoundary : true , watchFiles : false } ) ;
58+
59+ // 追踪 watchFiles 调用次数
60+ const watchCalls : string [ ] = [ ] ;
61+ ( sandbox as any ) . watchFiles = async ( paths : string [ ] ) => {
62+ watchCalls . push ( paths [ 0 ] ) ;
63+ await new Promise ( r => setTimeout ( r , 50 ) ) ; // 模拟异步延迟
64+ return `watch-${ watchCalls . length } ` ;
65+ } ;
66+
67+ const pool = new FilePool ( sandbox , { watch : true } ) ;
68+
69+ // 并发调用 3 次 recordEdit
70+ await Promise . all ( [
71+ pool . recordEdit ( 'test.txt' ) ,
72+ pool . recordEdit ( 'test.txt' ) ,
73+ pool . recordEdit ( 'test.txt' ) ,
74+ ] ) ;
75+
76+ // 验证只创建了 1 个 watcher(per-path 锁生效)
77+ expect . toEqual ( watchCalls . length , 1 ) ;
78+ } )
79+
80+ . test ( '不同文件的并发 recordEdit 各自创建 watcher' , async ( ) => {
81+ const dir = createTempDir ( 'concurrent-multi' ) ;
82+ fs . writeFileSync ( path . join ( dir , 'a.txt' ) , 'a' ) ;
83+ fs . writeFileSync ( path . join ( dir , 'b.txt' ) , 'b' ) ;
84+ fs . writeFileSync ( path . join ( dir , 'c.txt' ) , 'c' ) ;
85+
86+ const sandbox = new LocalSandbox ( { workDir : dir , enforceBoundary : true , watchFiles : false } ) ;
87+
88+ const watchCalls : string [ ] = [ ] ;
89+ ( sandbox as any ) . watchFiles = async ( paths : string [ ] ) => {
90+ watchCalls . push ( paths [ 0 ] ) ;
91+ await new Promise ( r => setTimeout ( r , 30 ) ) ;
92+ return `watch-${ watchCalls . length } ` ;
93+ } ;
94+
95+ const pool = new FilePool ( sandbox , { watch : true } ) ;
96+
97+ // 并发操作 3 个不同文件
98+ await Promise . all ( [
99+ pool . recordEdit ( 'a.txt' ) ,
100+ pool . recordEdit ( 'b.txt' ) ,
101+ pool . recordEdit ( 'c.txt' ) ,
102+ ] ) ;
103+
104+ // 每个文件各创建 1 个 watcher
105+ expect . toEqual ( watchCalls . length , 3 ) ;
50106 } ) ;
51107
52108export async function run ( ) {
0 commit comments