@@ -21,11 +21,9 @@ class RemoteConfigService {
2121 required Dio dio,
2222 required RemoteConfigStore store,
2323 DateTime Function ()? now,
24- RuntimeEndpointRouter ? endpointRouter,
2524 }) : _dio = dio,
2625 _store = store,
27- _now = now ?? DateTime .now,
28- _endpointRouter = endpointRouter;
26+ _now = now ?? DateTime .now;
2927
3028 RemoteConfigService .create ({
3129 required SharedPreferences prefs,
@@ -40,13 +38,11 @@ class RemoteConfigService {
4038 apiLogTag: 'REMOTE-CONFIG' ,
4139 ),
4240 store: RemoteConfigStore (prefs),
43- endpointRouter: endpointRouter,
4441 );
4542
4643 final Dio _dio;
4744 final RemoteConfigStore _store;
4845 final DateTime Function () _now;
49- final RuntimeEndpointRouter ? _endpointRouter;
5046
5147 /// 最近一次成功获取远程配置的时间,用于统一刷新节流。
5248 DateTime ? get lastFetchedAt => _store.readFetchedAt ();
@@ -116,7 +112,10 @@ class RemoteConfigService {
116112 /// 运行期刷新使用本方法,避免 [load] 的缓存优先逻辑让过期检查后的刷新
117113 /// 再次命中本地缓存。调用方负责决定失败时是否保留旧内存配置。
118114 Future <RemoteConfig > fetchRemote () async {
119- final response = await _fetchRemoteConfigResponse ();
115+ final response = await _dio.get <Object ?>(
116+ '/api/v1/client/config' ,
117+ queryParameters: {'platform' : clientPlatformName ()},
118+ );
120119 final config = RemoteConfig .fromRemoteJson (response.data);
121120 await _store.write (config, now: _now ());
122121 AppLogger .log (
@@ -127,114 +126,4 @@ class RemoteConfigService {
127126 );
128127 return config;
129128 }
130-
131- /// 请求当前首选区域的 Client Config;网络错误或 5xx 时最多尝试备用区域一次。
132- ///
133- /// 4xx、取消请求或没有备用端点时保留原错误,成功响应会更新当前 API 区域。
134- Future <Response <Object ?>> _fetchRemoteConfigResponse () async {
135- const path = '/api/v1/client/config' ;
136- final router = _endpointRouter;
137- if (router == null ) return _getConfig (path);
138-
139- final preferredRegion = router.preferredApiRegion;
140- final preferredUri = router.apiUriForRegion (preferredRegion, path);
141- if (preferredUri == null ) {
142- AppLogger .log (
143- _logTag,
144- 'preferred config API is not configured; using Dio base URL' ,
145- );
146- return _getConfig (path);
147- }
148-
149- AppLogger .log (
150- _logTag,
151- 'request client config preferred=${preferredRegion .name } '
152- 'endpoint=${_endpointLabel (preferredUri )}' ,
153- );
154-
155- try {
156- final response = await _getConfig (preferredUri.toString ());
157- router.markApiRegionAvailable (preferredRegion);
158- return response;
159- } on DioException catch (preferredError) {
160- if (! _shouldTryAlternate (preferredError)) {
161- AppLogger .log (
162- _logTag,
163- 'preferred config API fallback skipped '
164- 'type=${preferredError .type .name } '
165- 'status=${preferredError .response ?.statusCode ?? "none" }' ,
166- );
167- rethrow ;
168- }
169-
170- final alternateRegion = router.alternateApiRegion;
171- if (alternateRegion == null ) {
172- AppLogger .log (
173- _logTag,
174- 'config API fallback unavailable: no alternate endpoint configured' ,
175- );
176- rethrow ;
177- }
178- final alternateUri = router.apiUriForRegion (alternateRegion, path);
179- if (alternateUri == null ) {
180- AppLogger .log (
181- _logTag,
182- 'config API fallback unavailable: '
183- 'alternate=${alternateRegion .name } endpoint is not configured' ,
184- );
185- rethrow ;
186- }
187-
188- AppLogger .log (
189- _logTag,
190- 'preferred config endpoint failed; trying alternate '
191- 'preferred=${preferredRegion .name }('
192- '${_endpointLabel (preferredUri )}) '
193- 'alternate=${alternateRegion .name }('
194- '${_endpointLabel (alternateUri )}) '
195- 'type=${preferredError .type .name } '
196- 'status=${preferredError .response ?.statusCode ?? "none" }' ,
197- );
198- try {
199- final response = await _getConfig (alternateUri.toString ());
200- router.markApiRegionAvailable (alternateRegion);
201- return response;
202- } catch (alternateError, stackTrace) {
203- final errorType = alternateError is DioException
204- ? alternateError.type.name
205- : alternateError.runtimeType.toString ();
206- final statusCode = alternateError is DioException
207- ? alternateError.response? .statusCode
208- : null ;
209- AppLogger .log (
210- _logTag,
211- 'alternate config endpoint failed '
212- 'region=${alternateRegion .name } '
213- 'endpoint=${_endpointLabel (alternateUri )} '
214- 'type=$errorType status=${statusCode ?? "none" }' ,
215- );
216- Error .throwWithStackTrace (alternateError, stackTrace);
217- }
218- }
219- }
220-
221- Future <Response <Object ?>> _getConfig (String pathOrUri) => _dio.get <Object ?>(
222- pathOrUri,
223- queryParameters: {'platform' : clientPlatformName ()},
224- );
225-
226- bool _shouldTryAlternate (DioException error) {
227- if (error.type == DioExceptionType .cancel) return false ;
228- final statusCode = error.response? .statusCode;
229- return statusCode == null || statusCode >= 500 ;
230- }
231-
232- String _endpointLabel (Uri uri) {
233- return Uri (
234- scheme: uri.scheme,
235- host: uri.host,
236- port: uri.hasPort ? uri.port : null ,
237- path: uri.path,
238- ).toString ();
239- }
240129}
0 commit comments