Skip to content

Commit

Permalink
⏳ Now users can set timeout for RawAPI requests
Browse files Browse the repository at this point in the history
  • Loading branch information
HeySreelal committed Mar 15, 2024
1 parent d5520ae commit 8ac850f
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 3 deletions.
18 changes: 17 additions & 1 deletion lib/src/televerse/bot.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ class Bot<TeleverseSession extends Session> {
/// Handler for unexpected errors.
FutureOr<void> Function(BotError error)? _onError;

/// The timeout duration for the requests.
///
/// This is used to set the timeout duration for the requests. When the timeout duration is reached, the request will be cancelled.
final Duration? timeout;

/// Get the bot instance.
///
/// This getter returns the bot instance. You can use this to access the bot instance from anywhere in your code.
Expand Down Expand Up @@ -69,13 +74,15 @@ class Bot<TeleverseSession extends Session> {
baseUrl: _baseURL,
scheme: _scheme,
loggerOptions: _loggerOptions,
timeout: timeout,
);
}
return RawAPI(
token,
baseUrl: _baseURL,
scheme: APIScheme.https,
loggerOptions: _loggerOptions,
timeout: timeout,
);
}

Expand All @@ -100,6 +107,7 @@ class Bot<TeleverseSession extends Session> {
String baseURL = RawAPI.defaultBase,
APIScheme scheme = APIScheme.https,
LoggerOptions? loggerOptions,
this.timeout,
}) : _baseURL = baseURL,
isLocal = baseURL != RawAPI.defaultBase,
_loggerOptions = loggerOptions,
Expand All @@ -110,10 +118,16 @@ class Bot<TeleverseSession extends Session> {

api.getMe().then((value) {
_me = value;
}).catchError((err, st) async {
}).catchError((Object err, StackTrace st) async {
if (_onError != null) {
final botErr = BotError(err, st);
await _onError!(botErr);
} else if (err is DioException) {
if (err.type == DioExceptionType.connectionTimeout ||
err.type == DioExceptionType.receiveTimeout ||
err.type == DioExceptionType.sendTimeout) {
throw TeleverseException.timeoutException(st, timeout!);
}
} else {
throw err;
}
Expand Down Expand Up @@ -151,6 +165,7 @@ class Bot<TeleverseSession extends Session> {
String baseURL = "localhost:8081",
APIScheme scheme = APIScheme.http,
LoggerOptions? loggerOptions,
Duration? timeout,
}) {
print('Using local Bot API server at $baseURL');
return Bot(
Expand All @@ -159,6 +174,7 @@ class Bot<TeleverseSession extends Session> {
baseURL: baseURL,
scheme: scheme,
loggerOptions: loggerOptions,
timeout: timeout,
);
}

Expand Down
14 changes: 14 additions & 0 deletions lib/src/televerse/models/televerse_exception.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,18 @@ class TeleverseException implements Exception {
description:
"You must provide the bytes of the file to upload. Use the `InputFile.fromBytes` constructor to create an InputFile.",
);

/// Exception thrown when the timeout exception occurs.
static TeleverseException timeoutException(StackTrace st, Duration timeout) {
return TeleverseException(
"Connection timeout.",
description:
"The request took too long to complete. This might be due to a slow internet connection or sometimes due to the Telegram servers. Try again later.\n\n"
"Possible solutions:\n"
" 1. Increase the timeout duration. Currently it is set to $timeout.\n"
" 2. Check your internet connection.\n"
" 3. Attach a error handler using `Bot.onError` to handle the timeout exception.",
stackTrace: st,
);
}
}
13 changes: 12 additions & 1 deletion lib/src/televerse/raw_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ part of '../../televerse.dart';

/// Raw API for the Telegram Bot API.
class RawAPI {
/// Timeout Duration for the HTTP client.
///
/// When the timeout is reached, the API request will be cancelled and the client will throw an exception.
final Duration? timeout;

/// API Scheme
final APIScheme _scheme;

Expand All @@ -23,10 +28,14 @@ class RawAPI {
String? baseUrl,
APIScheme? scheme,
LoggerOptions? loggerOptions,
this.timeout,
}) : _baseUrl = baseUrl ?? defaultBase,
_isLocal = baseUrl != defaultBase,
_scheme = scheme ?? APIScheme.https,
_httpClient = _HttpClient(loggerOptions);
_httpClient = _HttpClient(
loggerOptions,
timeout: timeout,
);

/// Creates a new RawAPI instance with the given [token] and [baseUrl].
///
Expand All @@ -36,12 +45,14 @@ class RawAPI {
String baseUrl = "localhost:8081",
APIScheme scheme = APIScheme.http,
LoggerOptions? loggerOptions,
Duration? timeout,
}) {
return RawAPI(
token,
baseUrl: baseUrl,
scheme: scheme,
loggerOptions: loggerOptions,
timeout: timeout,
);
}

Expand Down
19 changes: 18 additions & 1 deletion lib/src/utils/http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ part of '../../televerse.dart';
/// HttpClient is used to send HTTP requests to the Telegram Bot API.
class _HttpClient {
/// Construc client with optionally logging
_HttpClient(this.loggerOptions) {
_HttpClient(
this.loggerOptions, {
this.timeout,
}) {
if (loggerOptions != null) {
_dio.interceptors.add(
loggerOptions!.interceptor,
Expand All @@ -17,6 +20,18 @@ class _HttpClient {
/// Log flag
final LoggerOptions? loggerOptions;

/// Timeout for the requests
final Duration? timeout;

/// Returns the timeout duration for the given [uri]. The [timeout] will not be used for `getUpdates` requests.
Duration? _timeoutDuration(Uri uri) {
// If the URI is of getUpdates, ignore the timeout.
if (uri.pathSegments.last == APIMethod.getUpdates.name) {
return null;
}
return timeout;
}

// Throws formatted exception
void _dioCatch(Object? e) {
if (e is TelegramException) {
Expand Down Expand Up @@ -68,6 +83,8 @@ class _HttpClient {
data: bodyContent,
options: Options(
headers: {"Content-Type": "application/json"},
sendTimeout: _timeoutDuration(uri),
receiveTimeout: _timeoutDuration(uri),
),
);
final resBody = response.data;
Expand Down

0 comments on commit 8ac850f

Please sign in to comment.