Skip to content

Commit

Permalink
Fix: "Ops, it should perform configure connection first"
Browse files Browse the repository at this point in the history
  • Loading branch information
RodrigoBertotti committed Sep 17, 2023
1 parent 8e93b52 commit 9902cdd
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 73 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pubspec.yaml:
sdk: flutter
# Add this line:
askless: ^3.0.0
askless: ^3.0.1

**5 -** Import the package

Expand Down
6 changes: 3 additions & 3 deletions lib/constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ const REQUEST_PREFIX = 'REQ-';
const LISTEN_PREFIX = 'LIS-';

// TODO onupdate:
const CLIENT_LIBRARY_VERSION_NAME = '3.0.0';
const CLIENT_LIBRARY_VERSION_CODE = 4;
const CLIENT_LIBRARY_VERSION_NAME = '3.0.1';
const CLIENT_LIBRARY_VERSION_CODE = 5;

// TODO onupdate: CHECK README (# Add this line: askless: ^3.0.0)
// TODO onupdate: CHECK README (# Add this line: askless: ^3.0.1)

// TODO onupdate: add changelog
9 changes: 6 additions & 3 deletions lib/domain/services/connection_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class ConnectionService {
getIt.get<SendPingTask>().changeInterval(connectionConfiguration.intervalInMsClientPing);
getIt.get<ReconnectWhenDidNotReceivePongFromServerTask>().changeInterval(connectionConfiguration.reconnectClientAfterMillisecondsWithoutServerPong);

print ("------------------- _configureConnection ------------------");
logger ("configureConnection ok");
notifyConnectionChanged(ConnectionStatus.connected);

Future.delayed(const Duration(seconds: 1), (){
Expand Down Expand Up @@ -172,7 +172,7 @@ class ConnectionService {
}

Stream<ConnectionDetails> streamConnectionChanges({bool immediately = false}) {
if (immediately) {
if (immediately) {
Future.delayed(const Duration(milliseconds: 50), () {
_connectionWithServerChangesStreamController.add(
ConnectionDetails(_connectionStatus, disconnectionReason));
Expand All @@ -183,6 +183,9 @@ class ConnectionService {

//Não pode ser acessado de fora do package:
void notifyConnectionChanged(ConnectionStatus conn, {DisconnectionReason ? disconnectionReason}) async {
logger("notifyConnectionChanged: ${conn.toString()}");

assert(conn != ConnectionStatus.connected || connectionConfiguration.isFromServer, "\"connect\" status is only when connectionConfiguration is received from server");
if (conn == _connectionStatus) {
return;
}
Expand Down Expand Up @@ -218,4 +221,4 @@ class ConnectionService {
_onConnectionWithServerChangeListenersBeforeOthersListeners.remove(listener);
}

}
}
134 changes: 69 additions & 65 deletions lib/domain/services/requests_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class RequestsService {
List.from(_pendingRequestsList.where((req) => whereRequestType?.toString().isNotEmpty != true || req.data.requestType == whereRequestType))
.forEach((req) {
// _lockPendingRequestsList.synchronized(() async {
_pendingRequestsList.remove(req);
_pendingRequestsList.remove(req);
// });
});
}
Expand All @@ -46,22 +46,22 @@ class RequestsService {

void notifyThatHasBeenReceivedServerResponse(InternalAsklessResponseEntity response) {
// _lockPendingRequestsList.synchronized(() async {
final req = _pendingRequestsList.firstWhereOrNull((p) => p.data.clientRequestId == response.clientRequestId,);
if (req != null) {
logger("${req.data.getRoute() ?? ''}: response received!: ${response.success} ${response.error?.code}");
req.onResponse(response);
_pendingRequestsList.remove(req);
} else {
logger(response.clientRequestId.toString());
logger("Response received, but did nothing, probably because the request timed out before. clientRequestId: ${response.clientRequestId}", level: Level.debug);
}
final req = _pendingRequestsList.firstWhereOrNull((p) => p.data.clientRequestId == response.clientRequestId,);
if (req != null) {
logger("${req.data.getRoute() ?? ''}: response received!: ${response.success} ${response.error?.code}");
req.onResponse(response);
_pendingRequestsList.remove(req);
} else {
logger(response.clientRequestId.toString());
logger("Response received, but did nothing, probably because the request timed out before. clientRequestId: ${response.clientRequestId}", level: Level.debug);
}
// });
}

void setAsReceivedPendingMessageThatServerShouldReceive(String clientRequestId) {
// _lockPendingRequestsList.synchronized(() async {
final pending = _pendingRequestsList.firstWhereOrNull((p) => p.data.clientRequestId == clientRequestId,);
pending?.serverReceived = true;
final pending = _pendingRequestsList.firstWhereOrNull((p) => p.data.clientRequestId == clientRequestId,);
pending?.serverReceived = true;
// });
}

Expand All @@ -85,62 +85,63 @@ class RequestsService {
data.clientRequestId ??= '${REQUEST_PREFIX}_${randomAlphaNumeric(28)}';

// ignore: prefer_function_declarations_over_variables
final sendAgainWhenConnected = (ConnectionDetails connection) async {
final sendWhenConnected = (ConnectionDetails connection) async {
if (connection.status == ConnectionStatus.connected) {
if (isAfterAuthentication) {
await getIt.get<AuthenticateService>().waitForAuthentication(neverTimeout: false, isPersevere: () => false);
}
logger("sending AGAIN because is connected");
logger('Sending data to server...', level: Level.debug,);
ws.sinkAdd(map: data);
}
};

final _Request request = _Request(data, (response) {
getIt.get<ConnectionService>().removeOnConnectionChange(sendWhenConnected);
if (!completer.isCompleted){
getIt.get<ConnectionService>().removeOnConnectionChange(sendAgainWhenConnected);
completer.complete(response);
}
});

getIt.get<ConnectionService>().addOnConnectionChangeListener(sendAgainWhenConnected, immediately: false);
getIt.get<ConnectionService>().addOnConnectionChangeListener(sendWhenConnected, immediately: request.data.requestType != RequestType.CONFIGURE_CONNECTION, beforeOthersListeners: data.requestType == RequestType.CONFIGURE_CONNECTION || data.requestType == RequestType.AUTHENTICATE);

if (neverTimeout == false && connectionConfiguration.requestTimeoutInMs > 0) {
Future.delayed(Duration(milliseconds: connectionConfiguration.requestTimeoutInMs), () {
// _lockPendingRequestsList.synchronized(() async {
final remove = _pendingRequestsList.firstWhereOrNull((p) => p.data.clientRequestId == request.data.clientRequestId,);
if (remove != null) {
_pendingRequestsList.remove(remove);
request.onResponse(InternalAsklessResponseEntity(
clientRequestId: data.clientRequestId!,
error: AsklessError(code: AsklessErrorCode.noConnection, description: 'Request timed out')
));
logger('Your request (${data.requestType}) \"${data.getRoute() ?? ''}\" timed out, check if: \n\t1) Your server configuration is serving on ${serverUrl}\n\t2) Your device has connection with internet\n\t3) Your API route implementation calls context.success or context.error methods', level: Level.error);
}
});
final remove = _pendingRequestsList.firstWhereOrNull((p) => p.data.clientRequestId == request.data.clientRequestId,);
if (remove != null) {
_pendingRequestsList.remove(remove);
request.onResponse(InternalAsklessResponseEntity(
clientRequestId: data.clientRequestId!,
error: AsklessError(code: AsklessErrorCode.noConnection, description: 'Request timed out')
));
logger('Your request (${data.requestType}) \"${data.getRoute() ?? ''}\" timed out, check if: \n\t1) Your server configuration is serving on ${serverUrl}\n\t2) Your device has connection with internet\n\t3) Your API route implementation calls context.success or context.error methods', level: Level.error);
}
});
// });
}


// await _lockPendingRequestsList.synchronized(() async {
if (ws.isReady == true){
if (ws.isReady == true){
await _addAsPending(request);
} else {
if (data.waitUntilGetServerConnection) {
await _addAsPending(request);
logger('Waiting connection to send message', level: Level.debug);
} else {
if (data.waitUntilGetServerConnection) {
await _addAsPending(request);
logger('Waiting connection to send message', level: Level.debug);
} else {
logger('You can\'t send this message while not connected', level: Level.debug);
request.onResponse(InternalAsklessResponseEntity(
clientRequestId: data.clientRequestId!,
error: AsklessError(description: 'Maybe de device has no internet or the server is offline', code: 'AsklessErrorCode.noConnection')
)
);
}
logger('You can\'t send this message while not connected', level: Level.debug);
request.onResponse(InternalAsklessResponseEntity(
clientRequestId: data.clientRequestId!,
error: AsklessError(description: 'Maybe de device has no internet or the server is offline', code: 'AsklessErrorCode.noConnection')
)
);
}
// });
//In the end:
logger('Sending data to server...', level: Level.debug,);
ws.sinkAdd(map: data);
}

if (request.data.requestType == RequestType.CONFIGURE_CONNECTION) {
logger('Sending data to server...', level: Level.debug,);
ws.sinkAdd(map: data);
}

final response = await completer.future;
if (ifRequiresAuthenticationWaitForIt && response.error?.code == AsklessErrorCode.pendingAuthentication) {
Expand Down Expand Up @@ -172,28 +173,31 @@ class RequestsService {
return response;
}

//A RESPOSTA ESTÁ VINDO ANTES DO addAsPending

Future<void> _addAsPending (_Request request) async {
//Se for um listening, deve ficar no final, do contrário
//corre o risco de receber 2 dados iguais por conta do método onClientListen na Server
// await _lockPendingRequestsList.synchronized(() {
_pendingRequestsList.add(request);
_pendingRequestsList.sort((a,b) {
if (a.data.requestType == RequestType.CONFIGURE_CONNECTION) {
return -2;
}
if (b.data.requestType == RequestType.CONFIGURE_CONNECTION) {
return 2;
}
if (a.data.requestType == RequestType.AUTHENTICATE) {
return -1;
}
if (b.data.requestType == RequestType.AUTHENTICATE) {
return 1;
}
return 0;
});
// });
_pendingRequestsList.add(request);
_pendingRequestsList.sort((a,b) {
// Listen should always be in the END!
if (a.data.requestType == RequestType.LISTEN) {
return 3;
}
if (b.data.requestType == RequestType.LISTEN) {
return -3;
}

if (a.data.requestType == RequestType.CONFIGURE_CONNECTION) {
return -2;
}
if (b.data.requestType == RequestType.CONFIGURE_CONNECTION) {
return 2;
}
if (a.data.requestType == RequestType.AUTHENTICATE) {
return -1;
}
if (b.data.requestType == RequestType.AUTHENTICATE) {
return 1;
}

return 0;
});
}
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: askless
description: Build Flutter Apps with PostgreSQL, MySQL, or any database, stream data changes through websockets effortlessly, handle websocket authentication like a pro and elevate your Flutter Chat App with video and audio calls!

version: 3.0.0 # TODO onupdate:
version: 3.0.1 # TODO onupdate:

environment:
sdk: '>=3.1.1 <4.0.0'
Expand Down

0 comments on commit 9902cdd

Please sign in to comment.