Search in sources :

Example 1 with FinalizableResultFuture

use of com.microsoft.identity.common.internal.result.FinalizableResultFuture in project microsoft-authentication-library-common-for-android by AzureAD.

the class CommandDispatcher method submitSilentReturningFuture.

/**
 * submitSilent - Run a command using the silent thread pool, and return the future governing it.
 *
 * @param command
 */
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
public static FinalizableResultFuture<CommandResult> submitSilentReturningFuture(@SuppressWarnings(WarningType.rawtype_warning) @NonNull final BaseCommand command) {
    final String methodName = ":submitSilent";
    final CommandParameters commandParameters = command.getParameters();
    final String correlationId = initializeDiagnosticContext(commandParameters.getCorrelationId(), commandParameters.getSdkType() == null ? SdkType.UNKNOWN.getProductName() : commandParameters.getSdkType().getProductName(), commandParameters.getSdkVersion());
    // set correlation id on parameters as it may not already be set
    commandParameters.setCorrelationId(correlationId);
    logParameters(TAG + methodName, correlationId, commandParameters, command.getPublicApiId());
    final Handler handler = new Handler(Looper.getMainLooper());
    synchronized (mapAccessLock) {
        final FinalizableResultFuture<CommandResult> finalFuture;
        if (command.isEligibleForCaching()) {
            FinalizableResultFuture<CommandResult> future = sExecutingCommandMap.get(command);
            if (null == future) {
                future = new FinalizableResultFuture<>();
                final FinalizableResultFuture<CommandResult> putValue = sExecutingCommandMap.putIfAbsent(command, future);
                if (null == putValue) {
                    // our value was inserted.
                    future.whenComplete(getCommandResultConsumer(command, handler));
                } else {
                    // Our value was not inserted, grab the one that was and hang a new listener off it
                    putValue.whenComplete(getCommandResultConsumer(command, handler));
                    return putValue;
                }
            } else {
                future.whenComplete(getCommandResultConsumer(command, handler));
                return future;
            }
            finalFuture = future;
        } else {
            finalFuture = new FinalizableResultFuture<>();
            finalFuture.whenComplete(getCommandResultConsumer(command, handler));
        }
        sSilentExecutor.execute(new Runnable() {

            @Override
            public void run() {
                try {
                    // initializing again since the request is transferred to a different thread pool
                    initializeDiagnosticContext(correlationId, commandParameters.getSdkType() == null ? SdkType.UNKNOWN.getProductName() : commandParameters.getSdkType().getProductName(), commandParameters.getSdkVersion());
                    EstsTelemetry.getInstance().initTelemetryForCommand(command);
                    EstsTelemetry.getInstance().emitApiId(command.getPublicApiId());
                    CommandResult commandResult = null;
                    // Log operation parameters
                    if (command.getParameters() instanceof SilentTokenCommandParameters) {
                        EstsTelemetry.getInstance().emitForceRefresh(((SilentTokenCommandParameters) command.getParameters()).isForceRefresh());
                    }
                    // If nothing in cache, execute the command and cache the result
                    if (commandResult == null) {
                        commandResult = executeCommand(command);
                        // Disabling throttling ADO:1383033
                        // cacheCommandResult(command, commandResult);
                        Logger.info(TAG + methodName, "Completed silent request as owner for correlation id : **" + correlationId + ", with the status : " + commandResult.getStatus().getLogStatus() + " is cacheable : " + command.isEligibleForCaching());
                    } else {
                        Logger.info(TAG + methodName, "Silent command result returned from cache for correlation id : " + correlationId + " having status : " + commandResult.getStatus().getLogStatus());
                        // Added to keep the original correlation id intact, and to not let it mutate with the cascading requests hitting the cache.
                        commandResult = new CommandResult(commandResult.getStatus(), commandResult.getResult(), commandResult.getCorrelationId());
                    }
                    // TODO 1309671 : change required to stop the LocalAuthenticationResult object from mutating in cases of cached command.
                    // set correlation id on Local Authentication Result
                    setCorrelationIdOnResult(commandResult, correlationId);
                    Telemetry.getInstance().flush(correlationId);
                    EstsTelemetry.getInstance().flush(command, commandResult);
                    finalFuture.setResult(commandResult);
                } catch (final Throwable t) {
                    Logger.info(TAG + methodName, "Request encountered an exception with correlation id : **" + correlationId);
                    finalFuture.setException(new ExecutionException(t));
                } finally {
                    synchronized (mapAccessLock) {
                        if (command.isEligibleForCaching()) {
                            final FinalizableResultFuture mapFuture = sExecutingCommandMap.remove(command);
                            if (mapFuture == null) {
                                // If this has happened, the command that we started with has mutated.  We will
                                // examine every entry in the map, find the one with the same object identity
                                // and remove it.
                                // ADO:TODO:1153495 - Rekey this map with stable string keys.
                                Logger.error(TAG, "The command in the map has mutated " + command.getClass().getCanonicalName() + " the calling application was " + command.getParameters().getApplicationName(), null);
                                cleanMap(command);
                            }
                        }
                        finalFuture.setCleanedUp();
                    }
                    DiagnosticContext.clear();
                }
            }
        });
        return finalFuture;
    }
}
Also used : SilentTokenCommandParameters(com.microsoft.identity.common.internal.commands.parameters.SilentTokenCommandParameters) Handler(android.os.Handler) FinalizableResultFuture(com.microsoft.identity.common.internal.result.FinalizableResultFuture) CommandParameters(com.microsoft.identity.common.internal.commands.parameters.CommandParameters) BrokerInteractiveTokenCommandParameters(com.microsoft.identity.common.internal.commands.parameters.BrokerInteractiveTokenCommandParameters) SilentTokenCommandParameters(com.microsoft.identity.common.internal.commands.parameters.SilentTokenCommandParameters) ExecutionException(java.util.concurrent.ExecutionException) VisibleForTesting(androidx.annotation.VisibleForTesting)

Aggregations

Handler (android.os.Handler)1 VisibleForTesting (androidx.annotation.VisibleForTesting)1 BrokerInteractiveTokenCommandParameters (com.microsoft.identity.common.internal.commands.parameters.BrokerInteractiveTokenCommandParameters)1 CommandParameters (com.microsoft.identity.common.internal.commands.parameters.CommandParameters)1 SilentTokenCommandParameters (com.microsoft.identity.common.internal.commands.parameters.SilentTokenCommandParameters)1 FinalizableResultFuture (com.microsoft.identity.common.internal.result.FinalizableResultFuture)1 ExecutionException (java.util.concurrent.ExecutionException)1