Search in sources :

Example 1 with Retry

use of com.peterphi.std.guice.common.retry.annotation.Retry in project stdlib by petergeneric.

the class RetryMethodInterceptor method invoke.

@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
    Timer.Context timer = this.calls.time();
    try {
        final Retry options = invocation.getMethod().getAnnotation(Retry.class);
        final RetryManager mgr = buildRetryManager(options);
        if (log.isTraceEnabled())
            log.trace("Attempting retryable invoke of " + invocation.getMethod().toGenericString() + " on " + invocation.getThis() + " with " + Arrays.asList(invocation.getArguments()));
        return mgr.run(new InvocationRetryable(invocation, options.on(), options.exceptOn(), options.exceptOnCore(), options.exceptOnRestExceptionCodes()));
    } catch (Throwable t) {
        totalFailures.mark();
        if (log.isTraceEnabled())
            log.trace("Retrying invoke of " + invocation.getMethod().toGenericString() + " on " + invocation.getThis() + " with " + Arrays.asList(invocation.getArguments()) + " failed.", t);
        throw t;
    } finally {
        timer.stop();
    }
}
Also used : Timer(com.codahale.metrics.Timer) RetryManager(com.peterphi.std.guice.common.retry.retry.RetryManager) Retry(com.peterphi.std.guice.common.retry.annotation.Retry)

Example 2 with Retry

use of com.peterphi.std.guice.common.retry.annotation.Retry in project stdlib by petergeneric.

the class AzureLogStore method storeAsBatch.

@Retry
public void storeAsBatch(final List<LogLineTableEntity> lines) throws StorageException {
    if (lines.isEmpty())
        // nothing to do!
        return;
    TableBatchOperation operation = new TableBatchOperation();
    for (LogLineTableEntity line : lines) {
        if (log.isTraceEnabled())
            log.trace("Storing entity with partition=" + line.getPartitionKey() + ", row=" + line.getRowKey());
        operation.insertOrReplace(line);
    }
    logdata.execute(operation);
}
Also used : LogLineTableEntity(com.peterphi.servicemanager.service.logging.LogLineTableEntity) TableBatchOperation(com.microsoft.azure.storage.table.TableBatchOperation) Retry(com.peterphi.std.guice.common.retry.annotation.Retry)

Example 3 with Retry

use of com.peterphi.std.guice.common.retry.annotation.Retry in project stdlib by petergeneric.

the class LetsEncryptService method proveOwnership.

@Retry
public void proveOwnership(final String domain) {
    Registration registration = getRegistration();
    final Authorization authorization;
    try {
        authorization = registration.authorizeDomain(domain);
    } catch (AcmeException e) {
        throw new RuntimeException("Error creating authorisation for " + domain, e);
    }
    Dns01Challenge challenge = authorization.findChallenge(Dns01Challenge.TYPE);
    if (challenge == null)
        throw new RuntimeException("DNS Challenge is not available! Cannot prove we own " + domain);
    final String domainName = "_acme-challenge." + domain;
    log.debug("Create TXT record " + domainName + " with value: " + challenge.getDigest());
    // Create the TXT record
    dns.createDNSRecord(domainName, RecordType.TXT, challenge.getDigest());
    // Wait for a short time for the change to DNS records to propagate through Microsoft's system
    // N.B. there's no docs suggesting this is needed or that this is the right value, but Let's Encrypt challenges
    // seem to fail more regularly against the live API without this wait
    new Timeout(5, TimeUnit.SECONDS).sleep();
    // Allow the CA to start checking the TXT record
    try {
        log.trace("Challenge status " + challenge.getStatus());
        challenge.trigger();
        log.trace("Challenge status " + challenge.getStatus());
    } catch (AcmeException e) {
        throw new RuntimeException("Error triggering authorisation for " + domain, e);
    }
    // Poll waiting for the challenge to complete
    int attempts = 10;
    for (int attempt = 0; attempt < 10; attempt++) {
        log.trace("Challenge status " + challenge.getStatus());
        if (challenge.getStatus() == Status.INVALID)
            break;
        else if (challenge.getStatus() == Status.VALID)
            break;
        Timeout.TEN_SECONDS.sleep();
        try {
            challenge.update();
        } catch (AcmeException e) {
            log.warn("Error updating challenge", e);
        }
    }
    log.trace("Challenge status " + challenge.getStatus());
    dns.deleteDNSRecord(domainName, RecordType.TXT);
    if (challenge.getStatus() != Status.VALID) {
        throw new RuntimeException("Challenge " + challenge + " failed for " + domainName + "! Failed with state " + challenge.getStatus());
    } else {
        log.debug("Challenge " + challenge + " passed!");
    }
}
Also used : Authorization(org.shredzone.acme4j.Authorization) Registration(org.shredzone.acme4j.Registration) AcmeException(org.shredzone.acme4j.exception.AcmeException) Timeout(com.peterphi.std.threading.Timeout) Dns01Challenge(org.shredzone.acme4j.challenge.Dns01Challenge) Retry(com.peterphi.std.guice.common.retry.annotation.Retry)

Example 4 with Retry

use of com.peterphi.std.guice.common.retry.annotation.Retry in project stdlib by petergeneric.

the class UserManagerOAuthServiceImpl method getAuth.

@Override
@AuthConstraint(id = "oauth2server_auth", role = "authenticated", comment = "Must be logged in to the User Manager to initiate a service login")
@Retry
public Response getAuth(final String responseType, final String clientId, final String redirectUri, final String state, final String scope) {
    // Has the current user approved this client+scope before? If so just redirect straight back
    // Otherwise, bring up the authorisation UI
    final Response response = createSessionAndRedirect(responseType, clientId, redirectUri, state, scope, autoGrantInteractiveAccessToAllServices);
    if (response != null) {
        return response;
    } else {
        final OAuthServiceEntity client = serviceDao.getByClientIdAndEndpoint(clientId, redirectUri);
        if (client == null)
            throw new IllegalArgumentException("Unknown client_id=" + clientId + " or invalid redirect uri for this service: " + redirectUri);
        final TemplateCall call = templater.template("connect_to_service");
        SessionNonceStore nonceStore = nonceStoreProvider.get();
        // Provide additional client information
        call.set("client", client);
        call.set("nonce", nonceStore.allocate());
        // Scopes as a list
        if (StringUtils.isBlank(scope))
            call.set("scopes", Collections.emptyList());
        else
            call.set("scopes", Arrays.asList(StringUtils.trimToEmpty(scope).split(" ")));
        // Copy the request info
        call.set("clientId", client.getId());
        call.set("responseType", responseType);
        call.set("redirectUri", redirectUri);
        call.set("scope", scope);
        call.set("state", state);
        return call.process(Response.ok().type(MediaType.APPLICATION_XML).cacheControl(CacheControl.valueOf(NO_CACHE)));
    }
}
Also used : OAuth2TokenResponse(com.peterphi.usermanager.rest.iface.oauth2server.types.OAuth2TokenResponse) Response(javax.ws.rs.core.Response) OAuthServiceEntity(com.peterphi.usermanager.db.entity.OAuthServiceEntity) SessionNonceStore(com.peterphi.usermanager.guice.nonce.SessionNonceStore) TemplateCall(com.peterphi.std.guice.web.rest.templating.TemplateCall) AuthConstraint(com.peterphi.std.guice.common.auth.annotations.AuthConstraint) Retry(com.peterphi.std.guice.common.retry.annotation.Retry)

Aggregations

Retry (com.peterphi.std.guice.common.retry.annotation.Retry)4 Timer (com.codahale.metrics.Timer)1 TableBatchOperation (com.microsoft.azure.storage.table.TableBatchOperation)1 LogLineTableEntity (com.peterphi.servicemanager.service.logging.LogLineTableEntity)1 AuthConstraint (com.peterphi.std.guice.common.auth.annotations.AuthConstraint)1 RetryManager (com.peterphi.std.guice.common.retry.retry.RetryManager)1 TemplateCall (com.peterphi.std.guice.web.rest.templating.TemplateCall)1 Timeout (com.peterphi.std.threading.Timeout)1 OAuthServiceEntity (com.peterphi.usermanager.db.entity.OAuthServiceEntity)1 SessionNonceStore (com.peterphi.usermanager.guice.nonce.SessionNonceStore)1 OAuth2TokenResponse (com.peterphi.usermanager.rest.iface.oauth2server.types.OAuth2TokenResponse)1 Response (javax.ws.rs.core.Response)1 Authorization (org.shredzone.acme4j.Authorization)1 Registration (org.shredzone.acme4j.Registration)1 Dns01Challenge (org.shredzone.acme4j.challenge.Dns01Challenge)1 AcmeException (org.shredzone.acme4j.exception.AcmeException)1