borgbutler-core/src/main/java/de/micromata/borgbutler/BorgCommands.java
@@ -174,14 +174,18 @@ // The returned job might be an already queued or running one! final ProgressInfo progressInfo = new ProgressInfo() .setMessage("Getting file list...") .setCurrent(0); .setCurrent(0) .setTotal(archive.getStats().getNfiles()); BorgJob<List<BorgFilesystemItem>> job = BorgQueueExecutor.getInstance().execute(new BorgJob<List<BorgFilesystemItem>>(command) { @Override protected void processStdOutLine(String line, int level) { BorgFilesystemItem item = JsonUtils.fromJson(BorgFilesystemItem.class, line); item.setMtime(DateUtils.format(item.getMtime())); payload.add(item); setProgressInfo(progressInfo.incrementCurrent()); if ("-".equals(item.getType())) { // Only increment for files, because number of files is the total. setProgressInfo(progressInfo.incrementCurrent()); } } }); job.payload = new ArrayList<>(); borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/JobsRest.java
@@ -63,34 +63,27 @@ if (testList == null) { testList = new ArrayList<>(); JsonJobQueue queue = new JsonJobQueue().setRepo("My Computer"); addTestJob(queue, "Calculating statistics... ", "Loading info of archive 'my-computer-2018-12-05T23:10:33' of repo 'My-Computer-Cloud'.", 0, 1000); addTestJob(queue, null, "Loading list of files of archive 'my-computer-2018-12-05T23:10:33' of repo 'My-Computer-Cloud'.", 0, 0); addTestJob(queue, "info", "my-macbook", 0, 2342); addTestJob(queue, "list", "my-macbook", -1, -1); testList.add(queue); queue = new JsonJobQueue().setRepo("My Server"); addTestJob(queue, "Getting file list...", "Loading list of files of archive 'my-server-2018-12-05T23:10:33' of repo 'My-Server-Cloud'.", 0, 0); addTestJob(queue, null, "Loading info of archive 'my-server-2018-12-05T23:10:33' of repo 'My-Server-Cloud'.", 0, 1000); addTestJob(queue, "list", "my-server", 0, 1135821); addTestJob(queue, "info", "my-server", -1, -1); testList.add(queue); } else { for (JsonJobQueue jobQueue : testList) { for (JsonJob job : jobQueue.getJobs()) { if (job.getStatus() != AbstractJob.Status.RUNNING) continue; long current = job.getProgressInfo().getCurrent(); long total = job.getProgressInfo().getTotal(); current += Math.random() * total / 30; if (current > total) { current = 0; // Reset to beginning. } job.getProgressInfo().setCurrent(current); if (job.getProgressText().startsWith("Calculating")) { long current = job.getProgressInfo().getCurrent(); current += Math.random() * 100; if (current > 1000) { current = 0; // Reset to beginning. } job.getProgressInfo().setCurrent(current); job.getProgressInfo().setMessage("Calculating statistics... " + Math.round(current / 10) + "%"); } else { long current = job.getProgressInfo().getCurrent(); current += Math.random() * 10000; job.getProgressInfo().setCurrent(current); job.getProgressInfo().setMessage("Calculating statistics... " + Math.round(100 * current / total) + "%"); } job.buildProgressText(); } @@ -100,20 +93,24 @@ } private JsonJob addTestJob(JsonJobQueue queue, String message, String description, long current, long total) { private JsonJob addTestJob(JsonJobQueue queue, String operation, String host, long current, long total) { ProgressInfo msg = new ProgressInfo() .setMessage(message) .setCurrent(current) .setTotal(total); JsonJob job = new JsonJob() .setProgressInfo(msg) .setDescription(description) .setStatus(AbstractJob.Status.QUEUED) .setCommandLineAsString("borg info --json --log-json --progress ssh://...:23/./backups/my-computer::my-computer-2018-12-05T23:10:33"); .setStatus(AbstractJob.Status.QUEUED); if ("info".equals(operation)) { msg.setMessage("Calculating statistics... "); job.setDescription("Loading info of archive '" + host + "-2018-12-05T23:10:33' of repo '" + queue.getRepo() + "'.") .setCommandLineAsString("borg info --json --log-json --progress ssh://...:23/./backups/" + host + "::" + host + "-2018-12-05T23:10:33"); } else { msg.setMessage("Getting file list... "); job.setCommandLineAsString("borg list --json-lines ssh://...:23/./backups/" + host + "::" + host + "-2018-12-05T17:30:38"); } job.buildProgressText(); if (message != null) { if (current >= 0) { job.setStatus(AbstractJob.Status.RUNNING); } else { job.setStatus(AbstractJob.Status.QUEUED); } borgbutler-server/src/main/java/de/micromata/borgbutler/server/rest/queue/JsonJob.java
@@ -1,11 +1,13 @@ package de.micromata.borgbutler.server.rest.queue; import com.fasterxml.jackson.annotation.JsonProperty; import de.micromata.borgbutler.BorgJob; import de.micromata.borgbutler.jobs.AbstractJob; import de.micromata.borgbutler.json.borg.ProgressInfo; import de.micromata.borgbutler.server.user.UserUtils; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.StringUtils; public class JsonJob { @Getter @@ -48,6 +50,7 @@ /** * Builds and sets progressText from the progressInfo object if given. * * @return progressText */ public String buildProgressText() { @@ -59,6 +62,13 @@ sb.append(progressInfo.getMessage()); } if (progressInfo.getCurrent() > 0) { if (StringUtils.indexOf(progressInfo.getMessage(), '%') < 0) { // No percentage given by borg, try to create an own one: short percentage = getProgressPercent(); if (percentage >= 0) { sb.append(" ").append(percentage).append("%"); } } sb.append(" (").append(UserUtils.formatNumber(progressInfo.getCurrent())); if (progressInfo.getTotal() > 0) { sb.append("/").append(UserUtils.formatNumber(progressInfo.getTotal())); @@ -68,9 +78,25 @@ if (progressInfo.isFinished()) { sb.append(" (finished)"); } sb.append("."); progressText = sb.toString(); return progressText; } /** * If current and total of {@link ProgressInfo} is available, this value is given, otherwise this value is -1. */ @JsonProperty public short getProgressPercent() { if (progressInfo == null || progressInfo.getTotal() <= 0) { return -1; } long value = 100 * progressInfo.getCurrent() / progressInfo.getTotal(); if (value < 0) { return 0; } if (value >= 100) { return 100; } return (short) value; } } borgbutler-webapp/src/components/views/jobs/Job.jsx
@@ -17,9 +17,13 @@ let content = undefined; let job = this.props.job; if (job.status === 'RUNNING') { content = <Progress animated color={'success'} value="100">{job.progressText}</Progress>; let progressPercent = 100; if (job.progressPercent >= 0 && job.progressPercent <= 100) { progressPercent = job.progressPercent; } content = <Progress animated color={'success'} value={progressPercent}>{job.progressText}</Progress>; } else { content = <Progress color={'info'} value="100">{job.status}</Progress> content = <Progress color={'info'} value={100}>{job.status}</Progress> } return ( <div> @@ -28,8 +32,8 @@ <Collapse isOpen={this.state.collapse}> <Card> <CardBody> <table><tr><th>Status</th><td>{job.status}</td></tr> <tr><th>Command line</th><td>{job.commandLineAsString}</td></tr></table> <table><tbody><tr><th>Status</th><td>{job.status}</td></tr> <tr><th>Command line</th><td>{job.commandLineAsString}</td></tr></tbody></table> </CardBody> </Card> </Collapse>