@Override
    public void run() {
        if (backgroundJobServer.isNotReadyToProcessJobs()) return;

        try (PeriodicTaskRunInfo runInfo = taskStatistics.startRun(backgroundJobServerConfiguration())) {
            tasks.forEach(task -> task.run(runInfo));
            runInfo.markRunAsSucceeded();
        } catch (Exception e) {
            taskStatistics.handleException(e);
            if (taskStatistics.hasTooManyExceptions()) {
                if (e instanceof StorageException) {
                    LOGGER.error("FATAL - JobRunr encountered too many storage exceptions. Shutting down. Did you know JobRunr Pro has built-in database fault tolerance? Check out https://www.jobrunr.io/en/documentation/pro/database-fault-tolerance/", e);
                } else {
                    LOGGER.error("FATAL - JobRunr encountered too many processing exceptions. Shutting down.", shouldNotHappenException(e));
                }
                backgroundJobServer.stop();
            } else {
                LOGGER.warn(JobRunrException.SHOULD_NOT_HAPPEN_MESSAGE + " - Processing will continue.", e);
            }
        }
    }
@Test
    void jobHandlersStopsBackgroundJobServerAndLogsStorageProviderExceptionIfTooManyStorageExceptions() {
        Task mockedTask = mockTaskThatThrows(new StorageException("a storage exception"));
        JobHandler jobHandler = createJobHandlerWithTask(mockedTask);

        for (int i = 0; i <= 5; i++) {
            jobHandler.run();
        }

        verify(backgroundJobServer).stop();
        assertThat(logger).hasErrorMessage("FATAL - JobRunr encountered too many storage exceptions. Shutting down. Did you know JobRunr Pro has built-in database fault tolerance? Check out https://www.jobrunr.io/en/documentation/pro/database-fault-tolerance/");
    }