runOperationInServer method

Future<InternalAsklessResponseEntity> runOperationInServer({
  1. required AbstractRequestCli data,
  2. bool neverTimeout = false,
  3. bool ifRequiresAuthenticationWaitForIt = true,
  4. required bool isPersevere(),
})

Does NOT wait for connection

Implementation

Future<InternalAsklessResponseEntity> runOperationInServer({required AbstractRequestCli data, bool neverTimeout = false, bool ifRequiresAuthenticationWaitForIt = true, required bool Function() isPersevere}) async {
  bool isAfterAuthentication = getIt.get<AuthenticateService>().authStatus == AuthStatus.authenticated;
  final completer = Completer<InternalAsklessResponseEntity>();
  data.clientRequestId ??= '${REQUEST_PREFIX}_${randomAlphaNumeric(28)}';

  // ignore: prefer_function_declarations_over_variables
  final sendWhenConnected = (ConnectionDetails connection) async {
    if (connection.status == ConnectionStatus.connected) {
      if (isAfterAuthentication) {
        await getIt.get<AuthenticateService>().waitForAuthentication(neverTimeout: false, isPersevere: () => false);
      }
      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){
      completer.complete(response);
    }
  });

  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);
      }
    });
    // });
  }


  // await _lockPendingRequestsList.synchronized(() async {
  if (ws.isReady == true){
    await _addAsPending(request);
  } 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')
      )
      );
    }
  }

  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) {
    logger("${request.data.getRoute() ?? ''}: requires authentication, waiting for it, OLD clientRequestId WAS ${request.data.clientRequestId}");
    request.data.clientRequestId = '${REQUEST_PREFIX}_${randomAlphaNumeric(28)}';
    logger("${request.data.getRoute() ?? ''}: NEW clientRequestId IS ${request.data.clientRequestId}, now it will wait for the authentication to finished...");
    isAfterAuthentication = true;
    if (getIt.get<AuthenticateService>().authStatus == AuthStatus.authenticated) {
      logger("(waitForAuthentication, request_service.dart) Ops, this shouldn't happen, the App says it is authenticated but the server says is not authenticated", level: Level.error);
    }
    final authenticated = await getIt.get<AuthenticateService>().waitForAuthentication(
        neverTimeout: neverTimeout,
        isPersevere: isPersevere,
        requestType: request.data.requestType,
        route: request.data.getRoute()
    );
    logger("...${request.data.getRoute() ?? ''}: finished waiting for authentication");

    if (authenticated) {
      logger("${request.data.getRoute() ?? ''}: performing operation AGAIN after authenticated");
      return runOperationInServer(data: data, neverTimeout: neverTimeout, isPersevere: isPersevere);
    } else {
      logger("${request.data.getRoute() ?? ''}: authentication failed, so the request failed as well");
    }
  }

  final remove = _pendingRequestsList.firstWhereOrNull((p) => p.data.clientRequestId == request.data.clientRequestId,);
  if (remove != null) {
    _pendingRequestsList.remove(remove);
  }

  return response;
}