c3d9cc273f
The global receiveTimeout is 30s but quick capture runs LLM inference that can take much longer. receiveTimeout fired, fell through to the NetworkException fallback in dioToApp, and the work queue queued it as an offline item. - quick_capture_api.dart: override receiveTimeout to 120s for the /api/quick-capture request - api_client.dart: handle receiveTimeout/sendTimeout explicitly in the error interceptor, converting them to AppException (not NetworkException) so slow responses are never mistaken for being offline Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
68 lines
2.2 KiB
Dart
68 lines
2.2 KiB
Dart
import 'package:cookie_jar/cookie_jar.dart';
|
|
import 'package:dio/dio.dart';
|
|
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
|
|
|
|
import '../../core/exceptions.dart';
|
|
|
|
PersistCookieJar buildCookieJar(String cookiesPath) =>
|
|
PersistCookieJar(storage: FileStorage('$cookiesPath/.cookies/'));
|
|
|
|
Dio buildDio(String baseUrl, PersistCookieJar cookieJar) {
|
|
|
|
final dio = Dio(BaseOptions(
|
|
baseUrl: baseUrl,
|
|
connectTimeout: const Duration(seconds: 10),
|
|
receiveTimeout: const Duration(seconds: 30),
|
|
headers: {'Content-Type': 'application/json'},
|
|
));
|
|
|
|
dio.interceptors.add(CookieManager(cookieJar));
|
|
dio.interceptors.add(_ErrorInterceptor());
|
|
|
|
return dio;
|
|
}
|
|
|
|
class _ErrorInterceptor extends Interceptor {
|
|
@override
|
|
void onError(DioException err, ErrorInterceptorHandler handler) {
|
|
if (err.response?.statusCode == 401) {
|
|
handler.reject(DioException(
|
|
requestOptions: err.requestOptions,
|
|
error: const AuthException('Session expired. Please log in again.'),
|
|
type: err.type,
|
|
response: err.response,
|
|
));
|
|
return;
|
|
}
|
|
if (err.type == DioExceptionType.connectionTimeout ||
|
|
err.type == DioExceptionType.connectionError) {
|
|
handler.reject(DioException(
|
|
requestOptions: err.requestOptions,
|
|
error: const NetworkException('Cannot reach server. Check your connection.'),
|
|
type: err.type,
|
|
response: err.response,
|
|
));
|
|
return;
|
|
}
|
|
if (err.type == DioExceptionType.receiveTimeout ||
|
|
err.type == DioExceptionType.sendTimeout) {
|
|
handler.reject(DioException(
|
|
requestOptions: err.requestOptions,
|
|
error: const AppException('Request timed out. The server is taking too long to respond.'),
|
|
type: err.type,
|
|
response: err.response,
|
|
));
|
|
return;
|
|
}
|
|
handler.next(err);
|
|
}
|
|
}
|
|
|
|
AppException dioToApp(DioException e) {
|
|
if (e.error is AppException) return e.error as AppException;
|
|
final status = e.response?.statusCode;
|
|
if (status == 401) return const AuthException('Not authenticated.');
|
|
if (status == 404) return const NotFoundException('Resource not found.');
|
|
return NetworkException(e.message ?? 'Unknown network error.');
|
|
}
|