docs: private void processRetryableTaskFailure(Throwable failure, ClassLoader loader, short consecutiveFailureCount, Config config, String taskName) {
          taskName = taskName == null || taskName.length() == 0 || taskName.length() == 1 && taskName.charAt(0) == ' ' ? String.valueOf(taskId) // empty task name
                          : taskId + " (" + taskName + ")";
          TaskStore taskStore = persistentExecutor.taskStore;
          TransactionManager tranMgr = persistentExecutor.tranMgrRef.getServiceWithException();
          boolean retry = false;
  
          try {
              Throwable failed = null;
              // Auto purge if we reached the failure limit and auto purge is enabled
              if (config.retryLimit >= 0
                  && consecutiveFailureCount > config.retryLimit
                  && (binaryFlags & TaskRecord.Flags.AUTO_PURGE_ALWAYS.bit) != 0) {
  
                  if (failure == null)
                      Tr.warning(tc, "CWWKC1510.retry.limit.reached.rollback", persistentExecutor.name, taskName, consecutiveFailureCount);
                  else
                      Tr.warning(tc, "CWWKC1511.retry.limit.reached.failed", persistentExecutor.name, taskName, consecutiveFailureCount, failure);
  
                  tranMgr.begin();
                  try {
                      taskStore.remove(taskId, null, false);
                  } catch (Throwable x) {
                      failed = x;
                  } finally {
                      if (failed == null)
                          tranMgr.commit();
                      else
                          tranMgr.rollback();
                  }
              } else {
                  // Update database with new count
                  tranMgr.begin();
                  try {
                      if (config.retryLimit < 0 || consecutiveFailureCount <= config.retryLimit)
                          consecutiveFailureCount = taskStore.incrementFailureCount(taskId);
  
                      if (config.retryLimit >= 0 && consecutiveFailureCount > config.retryLimit) {
                          if (failure == null)
                              Tr.warning(tc, "CWWKC1510.retry.limit.reached.rollback", persistentExecutor.name, taskName, consecutiveFailureCount);
                          else
                              Tr.warning(tc, "CWWKC1511.retry.limit.reached.failed", persistentExecutor.name, taskName, consecutiveFailureCount, failure);
  
                          TaskFailure taskFailure = new TaskFailure(failure, failure == null ? null : loader, persistentExecutor, TaskFailure.FAILURE_LIMIT_REACHED, Short.toString(consecutiveFailureCount));
                          // Update database with the result and state if we reached the limit
                          TaskRecord updates = new TaskRecord(false);
                          updates.setConsecutiveFailureCount(consecutiveFailureCount);
                          updates.setResult(persistentExecutor.serialize(taskFailure));
                          updates.setState((short) (TaskState.ENDED.bit | TaskState.FAILURE_LIMIT_REACHED.bit));
                          TaskRecord expected = new TaskRecord(false);
                          expected.setId(taskId);
                          taskStore.persist(updates, expected);
                      } else {
                          // -1 indicates the task is no longer in the persistent store
                          retry = consecutiveFailureCount != -1;
  
                          if (retry) {
                              String seconds = consecutiveFailureCount == 1 || config.retryInterval == 0L ? "0" : NumberFormat.getInstance().format(config.retryInterval / 1000.0);
                              if (failure == null)
                                  Tr.warning(tc, "CWWKC1500.task.rollback.retry", persistentExecutor.name, taskName, seconds);
                              else
                                  Tr.warning(tc, "CWWKC1501.task.failure.retry", persistentExecutor.name, taskName, failure, seconds);
                          } else if (failure == null)
                              Tr.warning(tc, "CWWKC1502.task.rollback", persistentExecutor.name, taskName);
                          else
                              Tr.warning(tc, "CWWKC1503.task.failure", persistentExecutor.name, taskName, failure);
                      }
                  } catch (Throwable x) {
                      failed = x;
                      retry = true;
                  } finally {
                      if (failed == null)
                          tranMgr.commit();
                      else
                          tranMgr.rollback();
                  }
              }
          } catch (Throwable x) {
              retry = true;
          }
  
          if (retry == true) {
              // Always retry the first failure immediately
              if (consecutiveFailureCount == 1 || config.retryInterval == 0L)
                  persistentExecutor.scheduledExecutor.submit(this);
              else {
                  persistentExecutor.scheduledExecutor.schedule(this, config.retryInterval, TimeUnit.MILLISECONDS);
              }
          }
  
      }