<commit_before>package io.bootique.job.scheduler.execution;

import io.bootique.job.Job;
import io.bootique.job.JobListener;
import io.bootique.job.runnable.JobResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

class Callback implements Consumer<Consumer<JobResult>> {

    private static final Logger LOGGER = LoggerFactory.getLogger(Callback.class);

    static JobResult runAndNotify(Job job, Map<String, Object> parameters, Set<JobListener> listeners) {
        if (listeners.isEmpty()) {
            return job.run(parameters);
        }

        String jobName = job.getMetadata().getName();

        Callback callback = new Callback(jobName);
        listeners.forEach(listener -> {
            try {
                listener.onJobStarted(jobName, parameters, callback);
            } catch (Exception e) {
                LOGGER.error("Error invoking job listener for job: " + jobName, e);
            }
        });
        JobResult result;
        try {
            result = job.run(parameters);
        } catch (Exception e) {
            callback.invoke(JobResult.failure(job.getMetadata(), e));
            throw e;
        }
        callback.invoke(result);
        return result;
    }

    private String jobName;
    private List<Consumer<JobResult>> callbacks;

    public Callback(String jobName) {
        this.jobName = jobName;
    }

    @Override
    public void accept(Consumer<JobResult> callback) {
        if (callbacks == null) {
            callbacks = new ArrayList<>();
        }
        callbacks.add(callback);
    }

    public void invoke(JobResult result) {
        callbacks.forEach(cb -> {
            try {
                cb.accept(result);
            } catch (Exception e) {
                LOGGER.error("Error invoking completion callback for job: " + jobName, e);
            }
        });
    }
}
<commit_msg>Provide info on currently running jobs #21<commit_after>package io.bootique.job.scheduler.execution;

import io.bootique.job.Job;
import io.bootique.job.JobListener;
import io.bootique.job.runnable.JobResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;

class Callback implements Consumer<Consumer<JobResult>> {

    private static final Logger LOGGER = LoggerFactory.getLogger(Callback.class);

    static JobResult runAndNotify(Job job, Map<String, Object> parameters, Set<JobListener> listeners) {
        if (listeners.isEmpty()) {
            return job.run(parameters);
        }

        String jobName = job.getMetadata().getName();

        Callback callback = new Callback(jobName);
        listeners.forEach(listener -> {
            try {
                listener.onJobStarted(jobName, parameters, callback);
            } catch (Exception e) {
                LOGGER.error("Error invoking job listener for job: " + jobName, e);
            }
        });
        JobResult result;
        try {
            result = job.run(parameters);
        } catch (Exception e) {
            callback.invoke(JobResult.failure(job.getMetadata(), e));
            throw e;
        }
        if (result == null) {
            result = JobResult.unknown(job.getMetadata());
        }
        callback.invoke(result);
        return result;
    }

    private String jobName;
    private List<Consumer<JobResult>> callbacks;

    public Callback(String jobName) {
        this.jobName = jobName;
    }

    @Override
    public void accept(Consumer<JobResult> callback) {
        if (callbacks == null) {
            callbacks = new ArrayList<>();
        }
        callbacks.add(callback);
    }

    public void invoke(JobResult result) {
        callbacks.forEach(cb -> {
            try {
                cb.accept(result);
            } catch (Exception e) {
                LOGGER.error("Error invoking completion callback for job: " + jobName, e);
            }
        });
    }
}

{'fraction_non_alphanumeric': 0.10721200387221684, 'fraction_numerical': 0.001452081316553727, 'mean_word_length': 2.2339593114241003, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3139277', 'n_tokens_mistral': 1152, 'n_tokens_neox': 1122, 'n_words': 259}