Search in sources :

Example 1 with TaskFinalFailureException

use of net.petafuel.styx.keepalive.entities.TaskFinalFailureException in project styx by petafuel.

the class ConsentPoll method execute.

public void execute() {
    LOG.debug("Executing Task id:{} signature:{}", getId(), getSignature());
    Consent currentConsent = persistentConsent.get(consent);
    if (currentConsent == null) {
        throw new TaskFinalFailureException("Consent queued for polling does not exist in the styx database, cannot poll", TaskFinalFailureCode.POLL_ON_NOT_EXISTING_CONSENT);
    } else if (currentConsent.getState() == ConsentStatus.VALID) {
        throw new TaskFinalFailureException("Consent with id " + currentConsent.getId() + " is already on state valid, no polling required", TaskFinalFailureCode.POLL_ON_ALREADY_VALID_CONSENT);
    }
    // TODO make the request type as a parameter
    StatusConsentRequest statusConsentRequest = new StatusConsentRequest(null, consent.getId(), null, null);
    statusConsentRequest.setPsu(consent.getPsu());
    Iterator<Integer> retryIterator = IntStream.range(0, maxRequestRetries).iterator();
    while (retryIterator.hasNext()) {
        if (Thread.interrupted()) {
            throw new TaskFinalFailureException("Task Thread was interrupted");
        }
        try {
            ConsentStatus currentStatus = this.csInterface.getStatus(statusConsentRequest);
            if (currentStatus == ConsentStatus.VALID) {
                LOG.debug("Consent is valid, SCA was successful");
                break;
            } else if (!(currentStatus.equals(ConsentStatus.RECEIVED) || currentStatus.equals(ConsentStatus.PARTIALLY_AUTHORISED))) {
                currentConsent.setState(currentStatus);
                persistentConsent.update(currentConsent);
                throw new TaskFinalFailureException("Consent cannot be polled anymore due to unrecoverable status: " + currentStatus.toString(), TaskFinalFailureCode.UNRECOVERABLE_STATUS);
            }
            LOG.debug("Consent status was not valid: {}", currentStatus);
        } catch (BankRequestFailedException e) {
            LOG.warn("Trying to poll consent resulted in an error: {} status: {} retry-iteration: {}", e.getMessage(), e.getHttpStatusCode(), retryIterator.next());
        }
        try {
            Thread.sleep(timeoutBetweenRetries);
        } catch (InterruptedException e) {
            LOG.error("Task {} execution was interrupted: {}", getId(), e.getMessage());
            Thread.currentThread().interrupt();
        }
        retryIterator.next();
    }
    // TODO make GetConsentRequest class as a parameter
    GetConsentRequest getConsentRequest = new GetConsentRequest(null, consent.getId(), null, null);
    try {
        Consent aspspConsent = csInterface.getConsent(getConsentRequest);
        if (!aspspConsent.getState().equals(ConsentStatus.VALID)) {
            throw new TaskRetryFailureException("Upon Consent Poll completion, consent is still not authorized by PSU");
        }
        currentConsent.setFrequencyPerDay(aspspConsent.getFrequencyPerDay());
        currentConsent.setValidUntil(aspspConsent.getValidUntil());
        currentConsent.setState(aspspConsent.getState());
        persistentConsent.update(currentConsent);
        LOG.info("Successfully updated consent");
    } catch (BankRequestFailedException e) {
        LOG.error("Unable to get consent information after polling was successful -> task marked as failed");
        throw new TaskRetryFailureException("Unable to get consent information after polling was successful", e);
    }
}
Also used : StatusConsentRequest(net.petafuel.styx.core.xs2a.standards.berlingroup.v1_2.http.StatusConsentRequest) PersistentConsent(net.petafuel.styx.core.persistence.layers.PersistentConsent) Consent(net.petafuel.styx.core.xs2a.entities.Consent) ConsentStatus(net.petafuel.styx.core.xs2a.entities.ConsentStatus) GetConsentRequest(net.petafuel.styx.core.xs2a.standards.berlingroup.v1_2.http.GetConsentRequest) TaskFinalFailureException(net.petafuel.styx.keepalive.entities.TaskFinalFailureException) TaskRetryFailureException(net.petafuel.styx.keepalive.entities.TaskRetryFailureException) BankRequestFailedException(net.petafuel.styx.core.xs2a.exceptions.BankRequestFailedException)

Example 2 with TaskFinalFailureException

use of net.petafuel.styx.keepalive.entities.TaskFinalFailureException in project styx by petafuel.

the class CoreWorker method run.

// try-catch required for error handling
@SuppressWarnings("java:S3776")
@Override
public void run() {
    Thread.currentThread().setName("KeepAlive-Worker-" + getType().toString() + "-" + getId().toString());
    LOG.info("Started CoreWorker id: {}", this.getId());
    setRunning(true);
    while (running.get()) {
        if (ThreadManager.getInstance().getCoreQueue().isEmpty()) {
            LOG.info("No polling from queue: Queue is empty -> ideling/waiting");
            try {
                synchronized (ThreadManager.getInstance().getCoreQueue()) {
                    ThreadManager.getInstance().getCoreQueue().wait();
                }
            } catch (InterruptedException e) {
                LOG.error("CoreWorker {} was interrupted", this.getId());
                Thread.currentThread().interrupt();
            }
        }
        WorkableTask task;
        synchronized (ThreadManager.getInstance().getCoreQueue()) {
            task = ThreadManager.getInstance().getCoreQueue().poll();
        }
        if (task == null) {
            continue;
        }
        currentTask.set(task);
        LOG.info("Task id:{} signature:{} polled from queue", task.getId(), task.getSignature());
        try {
            TaskRecoveryDB.updateState(task.getId(), TaskState.RUNNING);
            currentTaskStartTime.set(new Date().getTime());
            task.execute();
            LOG.info("Task id:{} signature: {} finished successfully", task.getId(), task.getSignature());
            currentTaskStartTime.set(0);
            TaskRecoveryDB.updateState(task.getId(), TaskState.DONE);
        } catch (TaskRetryFailureException retryFailure) {
            LOG.warn("Task id: {} signature: {} failed but will be requeued as RETRY_FAILURE -> {}", task.getId(), task.getSignature(), retryFailure.getMessage());
            TaskRecoveryDB.updateWorker(task.getId(), WorkerType.RETRY_FAILURE);
            ThreadManager.getInstance().queueTask(task, WorkerType.RETRY_FAILURE);
        } catch (TaskFinalFailureException finalFailure) {
            LOG.error("Task id: {} signature: {} finally failed with code:{} -> {}", task.getId(), task.getSignature(), finalFailure.getCode(), finalFailure.getMessage());
            TaskRecoveryDB.setFinallyFailed(task.getId(), finalFailure.getMessage(), finalFailure.getCode());
        } catch (Throwable throwable) {
            LOG.error("Task id: {} signature: {} encountered an unexpected error", task.getId(), task.getSignature(), throwable);
            TaskRecoveryDB.setFinallyFailed(task.getId(), throwable.getMessage(), TaskFinalFailureCode.UNKNOWN);
        }
    }
    LOG.info("Terminated CoreWorker id: {}", this.getId());
}
Also used : TaskFinalFailureException(net.petafuel.styx.keepalive.entities.TaskFinalFailureException) TaskRetryFailureException(net.petafuel.styx.keepalive.entities.TaskRetryFailureException) WorkableTask(net.petafuel.styx.keepalive.contracts.WorkableTask) Date(java.util.Date)

Example 3 with TaskFinalFailureException

use of net.petafuel.styx.keepalive.entities.TaskFinalFailureException in project styx by petafuel.

the class PaymentStatusPoll method poll.

private void poll() {
    if (((new Date().getTime()) - startTimestamp) >= maxExecutionTime) {
        throw new TaskFinalFailureException(String.format("Max execution time of %s was reached", maxExecutionTime), TaskFinalFailureCode.EXCEEDED_MAX_EXECUTION_TIME);
    } else if (maxRequestFailures != 0 && currentRequestFailures >= maxRequestFailures) {
        throw new TaskFinalFailureException(String.format("Max xs2a request failures reached %s out of %s", currentRequestFailures, maxRequestFailures), TaskFinalFailureCode.EXCEEDED_MAX_XS2A_REQUEST_FAILURES);
    }
    HookStatus hookStatus;
    PaymentStatus paymentStatus;
    try {
        String authorisationHeader = this.checkAccessToken(xRequestId);
        paymentStatusRequest.setAuthorization(authorisationHeader);
        this.ioProcessor.modifyRequest(paymentStatusRequest, xs2aFactoryInput);
        paymentStatus = xs2AStandard.getPis().getPaymentStatus(paymentStatusRequest);
        this.ioProcessor.modifyResponse(paymentStatus, xs2aFactoryInput);
        hookStatus = hookImpl.onStatusUpdate(paymentStatus);
    } catch (BankRequestFailedException e) {
        currentRequestFailures += 1;
        LOG.warn("Request towards the ASPSP failed. maxRequestFailures={}, currentRequestFailures={}", maxRequestFailures, currentRequestFailures, e);
        return;
    }
    if (hookStatus == HookStatus.SUCCESS) {
        LOG.info("PaymentStatus Hook was successful, calling Service Provider onSuccess and cancel task execution");
        hookImpl.onSuccess(payment);
        future.cancel(true);
    } else if (hookStatus == HookStatus.FAILURE) {
        LOG.info("PaymentStatus Hook failed, calling Service Provider onFailure and cancel task execution");
        hookImpl.onFailure(payment);
        future.cancel(true);
    }
}
Also used : HookStatus(net.petafuel.styx.spi.paymentstatushook.api.HookStatus) TaskFinalFailureException(net.petafuel.styx.keepalive.entities.TaskFinalFailureException) Date(java.util.Date) PaymentStatus(net.petafuel.styx.core.xs2a.entities.PaymentStatus) BankRequestFailedException(net.petafuel.styx.core.xs2a.exceptions.BankRequestFailedException)

Example 4 with TaskFinalFailureException

use of net.petafuel.styx.keepalive.entities.TaskFinalFailureException in project styx by petafuel.

the class PaymentStatusPoll method execute.

@Override
public void execute() throws Throwable {
    startTimestamp = new Date().getTime();
    ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    try {
        // Execute polling method at a fixed rate
        future = executorService.scheduleAtFixedRate(this::poll, 0, timeoutBetweenRetries, TimeUnit.MILLISECONDS);
        // wait until the future gets canceled
        future.get();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw new TaskFinalFailureException(e.getMessage(), TaskFinalFailureCode.EXECUTING_TASK_INTERRUPTED);
    } catch (ExecutionException e) {
        // throw cause
        throw e.getCause();
    } catch (CancellationException e) {
        // log task was cancelled
        LOG.debug("Task was canceled because of success/failure", e);
    } finally {
        executorService.shutdown();
    }
    LOG.debug("PaymentStatusPoll Task finished");
}
Also used : ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) CancellationException(java.util.concurrent.CancellationException) TaskFinalFailureException(net.petafuel.styx.keepalive.entities.TaskFinalFailureException) ExecutionException(java.util.concurrent.ExecutionException) Date(java.util.Date)

Example 5 with TaskFinalFailureException

use of net.petafuel.styx.keepalive.entities.TaskFinalFailureException in project styx by petafuel.

the class RetryFailureWorker method run.

// try-catch required for error handling
@SuppressWarnings("java:S3776")
@Override
public void run() {
    Thread.currentThread().setName("KeepAlive-Worker-" + getType().toString() + "-" + getId().toString());
    LOG.info("Started RetryFailureWorker id: {}", this.getId());
    this.setRunning(true);
    while (running.get()) {
        if (ThreadManager.getInstance().getRetryFailureQueue().isEmpty()) {
            LOG.info("No polling from queue: Queue is empty -> ideling/waiting");
            try {
                synchronized (ThreadManager.getInstance().getRetryFailureQueue()) {
                    ThreadManager.getInstance().getRetryFailureQueue().wait();
                }
            } catch (InterruptedException e) {
                LOG.error("RetryFailure Worker {} was interrupted", this.getId());
                Thread.currentThread().interrupt();
            }
        }
        WorkableTask task;
        synchronized (ThreadManager.getInstance().getRetryFailureQueue()) {
            task = ThreadManager.getInstance().getRetryFailureQueue().poll();
        }
        if (task == null) {
            continue;
        }
        currentTask.set(task);
        LOG.info("Task id:{} signature:{} polled from queue", task.getId(), task.getSignature());
        try {
            if (TaskRecoveryDB.incrementExecutionCounter(task.getId()) >= maxRetriesPerTask) {
                throw new TaskFinalFailureException("Maximum amount of executions by a RetryFailureWorker was reached for task: " + task.getId(), TaskFinalFailureCode.EXCEEDED_MAX_RETRIES_THROUGH_RETRYFAILUREWORKER);
            }
            TaskRecoveryDB.updateState(task.getId(), TaskState.RUNNING);
            currentTaskStartTime.set(new Date().getTime());
            task.execute();
            LOG.info("Task id:{} signature: {} finished successfully", task.getId(), task.getSignature());
            currentTaskStartTime.set(0);
            TaskRecoveryDB.updateState(task.getId(), TaskState.DONE);
        } catch (TaskRetryFailureException retryFailure) {
            LOG.warn("Task id: {} signature: {} failed but will be requeued as RETRY_FAILURE -> {}", task.getId(), task.getSignature(), retryFailure.getMessage());
            TaskRecoveryDB.updateWorker(task.getId(), WorkerType.RETRY_FAILURE);
            ThreadManager.getInstance().queueTask(task, WorkerType.RETRY_FAILURE);
        } catch (TaskFinalFailureException finalFailure) {
            LOG.error("Task id: {} signature: {} finally failed with code:{} -> {}", task.getId(), task.getSignature(), finalFailure.getCode(), finalFailure.getMessage());
            TaskRecoveryDB.setFinallyFailed(task.getId(), finalFailure.getMessage(), finalFailure.getCode());
        } catch (Throwable throwable) {
            Throwable cause = throwable.getCause();
            String causeMessage = cause != null ? cause.getMessage() : "";
            LOG.error("Task id: {} signature: {} encountered an unexpected error exception={}, message={}, cause={}, causeMessage={}", task.getId(), task.getSignature(), throwable.getClass().getSimpleName(), throwable.getMessage(), cause, causeMessage);
            TaskRecoveryDB.setFinallyFailed(task.getId(), throwable.getMessage(), TaskFinalFailureCode.UNKNOWN);
        }
    }
    LOG.info("Terminated RetryFailureWorker id: {}", this.getId());
}
Also used : TaskFinalFailureException(net.petafuel.styx.keepalive.entities.TaskFinalFailureException) TaskRetryFailureException(net.petafuel.styx.keepalive.entities.TaskRetryFailureException) WorkableTask(net.petafuel.styx.keepalive.contracts.WorkableTask) Date(java.util.Date)

Aggregations

TaskFinalFailureException (net.petafuel.styx.keepalive.entities.TaskFinalFailureException)5 Date (java.util.Date)4 TaskRetryFailureException (net.petafuel.styx.keepalive.entities.TaskRetryFailureException)3 BankRequestFailedException (net.petafuel.styx.core.xs2a.exceptions.BankRequestFailedException)2 WorkableTask (net.petafuel.styx.keepalive.contracts.WorkableTask)2 CancellationException (java.util.concurrent.CancellationException)1 ExecutionException (java.util.concurrent.ExecutionException)1 ScheduledExecutorService (java.util.concurrent.ScheduledExecutorService)1 PersistentConsent (net.petafuel.styx.core.persistence.layers.PersistentConsent)1 Consent (net.petafuel.styx.core.xs2a.entities.Consent)1 ConsentStatus (net.petafuel.styx.core.xs2a.entities.ConsentStatus)1 PaymentStatus (net.petafuel.styx.core.xs2a.entities.PaymentStatus)1 GetConsentRequest (net.petafuel.styx.core.xs2a.standards.berlingroup.v1_2.http.GetConsentRequest)1 StatusConsentRequest (net.petafuel.styx.core.xs2a.standards.berlingroup.v1_2.http.StatusConsentRequest)1 HookStatus (net.petafuel.styx.spi.paymentstatushook.api.HookStatus)1