borgbutler-core/src/main/java/de/micromata/borgbutler/BorgQueueExecutor.java
@@ -78,16 +78,17 @@ * For displaying purposes. * * @param repoConfig * @param oldJobs If false, the running and queued jobs are returned, otherwise the done ones. * @return A list of all jobs of the queue (as copies). */ public List<BorgJob<?>> getJobListCopy(BorgRepoConfig repoConfig) { public List<BorgJob<?>> getJobListCopy(BorgRepoConfig repoConfig, boolean oldJobs) { JobQueue<String> origQueue = getQueue(repoConfig); List<BorgJob<?>> jobList = new ArrayList<>(); if (origQueue == null) { return jobList; } synchronized (origQueue) { Iterator<AbstractJob<String>> it = origQueue.getQueueIterator(); Iterator<AbstractJob<String>> it = oldJobs ? origQueue.getOldJobsIterator() : origQueue.getQueueIterator(); while (it.hasNext()) { AbstractJob<String> origJob = it.next(); if (!(origJob instanceof BorgJob)) { borgbutler-core/src/main/java/de/micromata/borgbutler/jobs/JobQueue.java
@@ -9,7 +9,7 @@ import java.util.concurrent.Executors; public class JobQueue<T> { private static final int MAX_OLD_JOBS_SIZE = 50; private static final int MAX_OLD_JOBS_SIZE = 10; private static long jobSequence = 0; private Logger log = LoggerFactory.getLogger(JobQueue.class); private List<AbstractJob<T>> queue = new ArrayList<>(); @@ -43,6 +43,12 @@ } } public Iterator<AbstractJob<T>> getOldJobsIterator() { synchronized (oldJobs) { return Collections.unmodifiableList(oldJobs).iterator(); } } /** * Searches only for queued jobs (not done jobs). * borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/JobsRest.java
@@ -39,6 +39,7 @@ */ public String getJobs(@QueryParam("repo") String repo, @QueryParam("testMode") boolean testMode, @QueryParam("oldJobs") boolean oldJobs, @QueryParam("prettyPrinter") boolean prettyPrinter) { if (testMode) { // Return dynamic test queue: @@ -51,13 +52,13 @@ BorgQueueExecutor borgQueueExecutor = BorgQueueExecutor.getInstance(); List<JsonJobQueue> queueList = new ArrayList<>(); if (validRepo) { // Get only the queue of the given repo: JsonJobQueue queue = getQueue(repo); JsonJobQueue queue = getQueue(repo, oldJobs); if (queue != null) { queueList.add(queue); } } else { // Get all the queues (of all repos). for (String rep : borgQueueExecutor.getRepos()) { JsonJobQueue queue = getQueue(rep); JsonJobQueue queue = getQueue(rep, oldJobs); if (queue != null) { queueList.add(queue); } @@ -66,13 +67,13 @@ return JsonUtils.toJson(queueList, prettyPrinter); } private JsonJobQueue getQueue(String repo) { private JsonJobQueue getQueue(String repo, boolean oldJobs) { BorgQueueExecutor borgQueueExecutor = BorgQueueExecutor.getInstance(); BorgRepoConfig repoConfig = ConfigurationHandler.getConfiguration().getRepoConfig(repo); if (repoConfig == null) { return null; } List<BorgJob<?>> borgJobList = borgQueueExecutor.getJobListCopy(repoConfig); List<BorgJob<?>> borgJobList = borgQueueExecutor.getJobListCopy(repoConfig, oldJobs); if (CollectionUtils.isEmpty(borgJobList)) return null; JsonJobQueue queue = new JsonJobQueue().setRepo(repoConfig.getDisplayName()); borgbutler-webapp/src/components/views/jobs/JobMonitorPanel.jsx
@@ -1,5 +1,5 @@ import React from 'react'; import {Button} from 'reactstrap'; import {Button, Collapse} from 'reactstrap'; import {getRestServiceUrl, isDevelopmentMode} from '../../../utilities/global'; import JobQueue from './JobQueue'; import ErrorAlert from '../archives/ArchiveView'; @@ -8,12 +8,13 @@ class JobMonitorPanel extends React.Component { state = { isFetching: false, testMode: false testMode: false, collapseOldJobs: false }; componentDidMount = () => { this.fetchQueues(); this.interval = setInterval(() => this.fetchQueues(), 2000); this.fetchQueues(false); this.interval = setInterval(() => this.fetchQueues(false), 2000); }; componentWillUnmount() { @@ -26,14 +27,23 @@ }); } fetchQueues = () => { toggleOldJobs() { if (!this.state.collapseOldJobs) { this.fetchQueues(true); } this.setState({collapseOldJobs: !this.state.collapseOldJobs}); } fetchQueues = (oldJobs) => { this.setState({ isFetching: true, failed: false }); fetch(getRestServiceUrl('jobs', { repo: this.props.repo, testMode: this.state.testMode testMode: this.state.testMode, oldJobs: oldJobs }), { method: 'GET', headers: { @@ -45,10 +55,17 @@ const queues = json.map(queue => { return queue; }); this.setState({ isFetching: false, queues }); if (oldJobs) { this.setState({ isFetching: false, oldJobsQueues: queues }); } else { this.setState({ isFetching: false, queues: queues }); } }) .catch(() => this.setState({isFetching: false, failed: true})); }; @@ -85,8 +102,24 @@ content = <React.Fragment>No jobs are running or queued.</React.Fragment> } } let oldJobs = 'Old jobs...'; if (this.state.oldJobsQueues && this.state.oldJobsQueues.length > 0) { oldJobs = <React.Fragment> {this.state.oldJobsQueues .map((queue) => <JobQueue embedded={this.props.embedded} queue={queue} key={queue.repo} />)} </React.Fragment> } return <React.Fragment> {content} <h5 onClick={this.toggleOldJobs}>Show old jobs </h5> <Collapse isOpen={this.state.collapseOldJobs}> {oldJobs} </Collapse> </React.Fragment>; } @@ -95,15 +128,18 @@ this.fetchQueues = this.fetchQueues.bind(this); this.toggleTestMode = this.toggleTestMode.bind(this); this.toggleOldJobs = this.toggleOldJobs.bind(this); } } JobMonitorPanel.propTypes = { JobMonitorPanel .propTypes = { embedded: PropTypes.bool, repo: PropTypes.string }; JobMonitorPanel.defaultProps = { JobMonitorPanel .defaultProps = { embedded: true, repo: null };