fix: timeout when sending large files
fixes https://gitlab.com/famedly/company/frontend/famedly-web/-/issues/540
This commit is contained in:
parent
61369c4b1d
commit
ab73047e51
|
|
@ -189,8 +189,8 @@ class Client extends MatrixApi {
|
|||
? NativeImplementationsIsolate(compute)
|
||||
: nativeImplementations,
|
||||
super(
|
||||
httpClient:
|
||||
VariableTimeoutHttpClient(httpClient ?? http.Client())) {
|
||||
httpClient: FixedTimeoutHttpClient(
|
||||
httpClient ?? http.Client(), Duration(seconds: 35))) {
|
||||
if (logLevel != null) Logs().level = logLevel;
|
||||
importantStateEvents.addAll([
|
||||
EventTypes.RoomName,
|
||||
|
|
|
|||
|
|
@ -20,19 +20,6 @@ import 'dart:async';
|
|||
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import 'package:matrix/matrix.dart';
|
||||
|
||||
/// Stream.timeout fails if no progress is made in timeLimit.
|
||||
/// In contrast, streamTotalTimeout fails if the stream isn't completed
|
||||
/// until timeoutFuture.
|
||||
Stream<T> streamTotalTimeout<T>(
|
||||
Stream<T> stream, Future<Never> timeoutFuture) async* {
|
||||
final si = StreamIterator(stream);
|
||||
while (await Future.any([si.moveNext(), timeoutFuture])) {
|
||||
yield si.current;
|
||||
}
|
||||
}
|
||||
|
||||
http.StreamedResponse replaceStream(
|
||||
http.StreamedResponse base, Stream<List<int>> stream) =>
|
||||
http.StreamedResponse(
|
||||
|
|
@ -57,10 +44,8 @@ abstract class TimeoutHttpClient extends http.BaseClient {
|
|||
|
||||
@override
|
||||
Future<http.StreamedResponse> send(http.BaseRequest request) async {
|
||||
final timeoutFuture = Completer<Never>().future.timeout(timeout);
|
||||
final response = await Future.any([inner.send(request), timeoutFuture]);
|
||||
return replaceStream(
|
||||
response, streamTotalTimeout(response.stream, timeoutFuture));
|
||||
final response = await inner.send(request);
|
||||
return replaceStream(response, response.stream.timeout(timeout));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -69,43 +54,3 @@ class FixedTimeoutHttpClient extends TimeoutHttpClient {
|
|||
@override
|
||||
Duration timeout;
|
||||
}
|
||||
|
||||
class VariableTimeoutHttpClient extends TimeoutHttpClient {
|
||||
/// Matrix synchronisation is done with https long polling. This needs a
|
||||
/// timeout which is usually 30 seconds.
|
||||
int syncTimeoutSec;
|
||||
|
||||
int _timeoutFactor = 1;
|
||||
|
||||
@override
|
||||
Duration get timeout =>
|
||||
Duration(seconds: _timeoutFactor * syncTimeoutSec + 5);
|
||||
|
||||
VariableTimeoutHttpClient(http.Client inner, [this.syncTimeoutSec = 30])
|
||||
: super(inner);
|
||||
|
||||
@override
|
||||
Future<http.StreamedResponse> send(http.BaseRequest request) async {
|
||||
try {
|
||||
final response = await super.send(request);
|
||||
return replaceStream(response, (() async* {
|
||||
try {
|
||||
await for (final chunk in response.stream) {
|
||||
yield chunk;
|
||||
}
|
||||
_timeoutFactor = 1;
|
||||
} on TimeoutException catch (e, s) {
|
||||
_timeoutFactor *= 2;
|
||||
throw MatrixConnectionException(e, s);
|
||||
} catch (e, s) {
|
||||
throw MatrixConnectionException(e, s);
|
||||
}
|
||||
})());
|
||||
} on TimeoutException catch (e, s) {
|
||||
_timeoutFactor *= 2;
|
||||
throw MatrixConnectionException(e, s);
|
||||
} catch (e, s) {
|
||||
throw MatrixConnectionException(e, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue