11import type FileSystem from "./filesystem" ;
22import type { FileInfo , FileReader , FileWriter } from "./filesystem" ;
33
4+ const RETRYABLE_429_OPS = new Set ( [ "verify" , "open" , "read" , "openDir" , "list" , "getDirUrl" ] ) ;
5+
46/**
57 * 速率限制器
68 * 控制并发操作数量,防止过多并发请求
@@ -21,7 +23,7 @@ export class RateLimiter {
2123 * @param fn 要执行的操作函数
2224 * @returns 操作结果
2325 */
24- async execute < T > ( fn : ( ) => Promise < T > ) : Promise < T > {
26+ async execute < T > ( fn : ( ) => Promise < T > , op = "unknown" ) : Promise < T > {
2527 // 如果当前运行的操作数已达到上限,则等待
2628 while ( this . running >= this . maxConcurrent ) {
2729 await new Promise < void > ( ( resolve ) => {
@@ -31,7 +33,7 @@ export class RateLimiter {
3133
3234 this . running ++ ;
3335 try {
34- return await this . executeWithRetry ( fn ) ;
36+ return await this . executeWithRetry ( fn , op ) ;
3537 } finally {
3638 this . running -- ;
3739 // 执行完成后,从队列中取出下一个等待的操作
@@ -47,15 +49,15 @@ export class RateLimiter {
4749 * @param fn 要执行的操作函数
4850 * @returns 操作结果
4951 */
50- private async executeWithRetry < T > ( fn : ( ) => Promise < T > ) : Promise < T > {
52+ private async executeWithRetry < T > ( fn : ( ) => Promise < T > , op : string ) : Promise < T > {
5153 // 最多重试 10 次
5254 for ( let i = 0 ; i <= 10 ; i ++ ) {
5355 try {
5456 return await fn ( ) ;
5557 } catch ( error ) {
5658 // 检查错误字符串中是否包含 429
5759 const errorStr = String ( error ) ;
58- if ( errorStr . includes ( "429" ) && i < 10 ) {
60+ if ( this . shouldRetry429 ( op , errorStr ) && i < 10 ) {
5961 // 遇到 429 错误且未达到重试上限,采用指数退避策略延迟后继续重试
6062 const delay = Math . min ( 2000 * Math . pow ( 2 , i ) , 60000 ) ;
6163 await new Promise ( ( resolve ) => setTimeout ( resolve , delay ) ) ;
@@ -68,6 +70,10 @@ export class RateLimiter {
6870 }
6971 throw new Error ( "Max retries exceeded" ) ;
7072 }
73+
74+ private shouldRetry429 ( op : string , errorStr : string ) : boolean {
75+ return errorStr . includes ( "429" ) && RETRYABLE_429_OPS . has ( op ) ;
76+ }
7177}
7278
7379// 文件系统限速器,防止并发请求过多达到服务器限制
@@ -83,47 +89,47 @@ export default class LimiterFileSystem implements FileSystem {
8389 }
8490
8591 verify ( ) : Promise < void > {
86- return this . limiter . execute ( ( ) => this . fs . verify ( ) ) ;
92+ return this . limiter . execute ( ( ) => this . fs . verify ( ) , "verify" ) ;
8793 }
8894
8995 async open ( file : FileInfo ) : Promise < FileReader > {
9096 return this . limiter . execute ( async ( ) => {
9197 const reader = await this . fs . open ( file ) ;
9298 return {
93- read : ( type ) => this . limiter . execute ( ( ) => reader . read ( type ) ) ,
99+ read : ( type ) => this . limiter . execute ( ( ) => reader . read ( type ) , "read" ) ,
94100 } ;
95- } ) ;
101+ } , "open" ) ;
96102 }
97103
98104 async openDir ( path : string ) : Promise < FileSystem > {
99105 return this . limiter . execute ( async ( ) => {
100106 const fs = await this . fs . openDir ( path ) ;
101107 return new LimiterFileSystem ( fs , this . limiter ) ;
102- } ) ;
108+ } , "openDir" ) ;
103109 }
104110
105111 async create ( path : string ) : Promise < FileWriter > {
106112 return this . limiter . execute ( async ( ) => {
107113 const writer = await this . fs . create ( path ) ;
108114 return {
109- write : ( content ) => this . limiter . execute ( ( ) => writer . write ( content ) ) ,
115+ write : ( content ) => this . limiter . execute ( ( ) => writer . write ( content ) , "write" ) ,
110116 } ;
111- } ) ;
117+ } , "create" ) ;
112118 }
113119
114120 createDir ( dir : string ) : Promise < void > {
115- return this . limiter . execute ( ( ) => this . fs . createDir ( dir ) ) ;
121+ return this . limiter . execute ( ( ) => this . fs . createDir ( dir ) , "createDir" ) ;
116122 }
117123
118124 delete ( path : string ) : Promise < void > {
119- return this . limiter . execute ( ( ) => this . fs . delete ( path ) ) ;
125+ return this . limiter . execute ( ( ) => this . fs . delete ( path ) , "delete" ) ;
120126 }
121127
122128 list ( ) : Promise < FileInfo [ ] > {
123- return this . limiter . execute ( ( ) => this . fs . list ( ) ) ;
129+ return this . limiter . execute ( ( ) => this . fs . list ( ) , "list" ) ;
124130 }
125131
126132 getDirUrl ( ) : Promise < string > {
127- return this . limiter . execute ( ( ) => this . fs . getDirUrl ( ) ) ;
133+ return this . limiter . execute ( ( ) => this . fs . getDirUrl ( ) , "getDirUrl" ) ;
128134 }
129135}
0 commit comments