Merge pull request #3 from linuxserver/task_error_handling

Task error handling
This commit is contained in:
Josh Stark 2019-05-19 09:22:36 +01:00 committed by GitHub
commit 9aa48e4303
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 119 additions and 48 deletions

View File

@ -11,7 +11,7 @@ repositories {
mavenCentral()
}
version = '1.3.0'
version = '1.3.1'
sourceSets {

View File

@ -20,6 +20,7 @@ package io.linuxserver.fleet.delegate;
import io.linuxserver.fleet.dockerhub.DockerHubClient;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2Image;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2Tag;
import io.linuxserver.fleet.dockerhub.util.DockerTagFinder;
import io.linuxserver.fleet.model.DockerHubImage;
import java.time.LocalDateTime;
@ -31,9 +32,12 @@ import java.util.List;
public class DockerHubDelegate {
private final DockerHubClient dockerHubClient;
private final DockerTagFinder dockerTagFinder;
public DockerHubDelegate(DockerHubClient dockerHubClient) {
this.dockerHubClient = dockerHubClient;
this.dockerTagFinder = new DockerTagFinder();
}
public List<String> fetchAllRepositories() {
@ -52,14 +56,19 @@ public class DockerHubDelegate {
return images;
}
public List<DockerHubV2Tag> fetchAllTagsForImage(String repositoryName, String imageName) {
return dockerHubClient.fetchAllTagsForImage(repositoryName, imageName);
}
public String fetchLatestImageTag(String repositoryName, String imageName) {
DockerHubV2Tag dockerHubV2Tag = dockerHubClient.fetchLatestTagForImage(repositoryName, imageName);
List<DockerHubV2Tag> tags = fetchAllTagsForImage(repositoryName, imageName);
if (null != dockerHubV2Tag)
return dockerHubV2Tag.getName();
if (tags.isEmpty()) {
return null;
}
return null;
return dockerTagFinder.findVersionedTagMatchingBranch(tags, "latest").getName();
}
private DockerHubImage convertApiImageToInternalImage(DockerHubV2Image apiImage) {

View File

@ -31,5 +31,5 @@ public interface DockerHubClient {
DockerHubV2Image fetchImageFromRepository(String repositoryName, String imageName);
DockerHubV2Tag fetchLatestTagForImage(String repositoryName, String imageName);
List<DockerHubV2Tag> fetchAllTagsForImage(String repositoryName, String imageName);
}

View File

@ -22,17 +22,15 @@ import io.linuxserver.fleet.rest.HttpException;
import io.linuxserver.fleet.rest.RestClient;
import io.linuxserver.fleet.rest.RestResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* Client class to interface with Docker Hub's V2 API.
*/
public class DockerHubV2Client implements DockerHubClient {
static final String DOCKERHUB_BASE_URI = "https://hub.docker.com/v2";
private static final int DEFAULT_PAGE_SIZE = 1000;
static final String DOCKERHUB_BASE_URI = "https://hub.docker.com/v2";
private final RestClient restClient;
private final DockerHubAuthenticator authenticator;
@ -70,8 +68,7 @@ public class DockerHubV2Client implements DockerHubClient {
try {
String url = DOCKERHUB_BASE_URI + "/repositories/" + repositoryName;
String url = DOCKERHUB_BASE_URI + "/repositories/" + repositoryName + "?page_size=" + DEFAULT_PAGE_SIZE;
while (url != null) {
RestResponse<DockerHubV2ImageListResult> response = doCall(url, DockerHubV2ImageListResult.class);
@ -108,19 +105,27 @@ public class DockerHubV2Client implements DockerHubClient {
}
@Override
public DockerHubV2Tag fetchLatestTagForImage(String repositoryName, String imageName) {
public List<DockerHubV2Tag> fetchAllTagsForImage(String repositoryName, String imageName) {
try {
String absoluteUrl = DOCKERHUB_BASE_URI + "/repositories/" + repositoryName + "/" + imageName + "/tags" ;
List<DockerHubV2Tag> tags = new ArrayList<>();
RestResponse<DockerHubV2TagListResult> restResponse = doCall(absoluteUrl, DockerHubV2TagListResult.class);
String absoluteUrl = DOCKERHUB_BASE_URI + "/repositories/" + repositoryName + "/" + imageName + "/tags?page_size=" + DEFAULT_PAGE_SIZE;
while (absoluteUrl != null) {
List<DockerHubV2Tag> results = restResponse.getPayload().getResults();
if (!results.isEmpty())
return results.get(0);
RestResponse<DockerHubV2TagListResult> response = doCall(absoluteUrl, DockerHubV2TagListResult.class);
return null;
if (isResponseOK(response)) {
DockerHubV2TagListResult payload = response.getPayload();
tags.addAll(payload.getResults());
absoluteUrl = payload.getNext();
}
}
return tags;
} catch (HttpException e) {
throw new DockerHubException("Unable to get tags for " + repositoryName + "/" + imageName, e);

View File

@ -34,4 +34,28 @@ public class DockerHubV2Tag {
public long getFullSize() {
return fullSize;
}
@Override
public String toString() {
return name;
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object other) {
if (!(other instanceof DockerHubV2Tag)) {
return false;
}
if (other == this) {
return true;
}
return name.equals(((DockerHubV2Tag) other).name);
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright (c) 2019 LinuxServer.io
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.linuxserver.fleet.dockerhub.util;
import io.linuxserver.fleet.dockerhub.model.DockerHubV2Tag;
import java.util.List;
import java.util.Optional;
public class DockerTagFinder {
public DockerHubV2Tag findVersionedTagMatchingBranch(List<DockerHubV2Tag> tags, String namedBranch) {
Optional<DockerHubV2Tag> trueLatest = tags.stream().filter(tag -> namedBranch.equals(tag.getName())).findFirst();
if (trueLatest.isPresent()) {
DockerHubV2Tag trueLatestTag = trueLatest.get();
Optional<DockerHubV2Tag> versionedLatestTag = tags.stream()
.filter(tag -> !tag.equals(trueLatestTag) && tag.getFullSize() == trueLatestTag.getFullSize()).findFirst();
return versionedLatestTag.orElse(trueLatestTag);
}
return tags.get(0);
}
}

View File

@ -28,7 +28,7 @@ public class DefaultLoggingSyncListener implements SynchronisationListener {
@Override
public void onSynchronisationStart() {
LOGGER.info("Sync started");
LOGGER.info("Sync started.");
}
@Override
@ -38,7 +38,7 @@ public class DefaultLoggingSyncListener implements SynchronisationListener {
@Override
public void onImageUpdated(ImageUpdateEvent event) {
LOGGER.info("({}/{}) {}.", event.getCurrentPosition(), event.getTotalImages(), event.getImage().getName());
}
@Override

View File

@ -82,10 +82,10 @@ public class DefaultSynchronisationState implements SynchronisationState {
if (isProcessIdle()) {
onStart(context);
try {
onStart(context);
List<String> repositories = context.getDockerHubDelegate().fetchAllRepositories();
onRepositoryScanned(context, repositories);
@ -98,9 +98,10 @@ public class DefaultSynchronisationState implements SynchronisationState {
LOGGER.error("Synchronisation process failed on the first step. Will skip for now.", e);
onSkip(context);
}
onFinish(context);
} finally {
onFinish(context);
}
} else {
onSkip(context);

View File

@ -17,24 +17,26 @@
package io.linuxserver.fleet.thread;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class FleetTask implements Runnable {
private TaskListener taskListener;
private final Logger logger;
public void setTaskListener(TaskListener listener) {
this.taskListener = listener;
}
protected TaskListener getTaskListener() {
return taskListener;
FleetTask() {
logger = LoggerFactory.getLogger(getClass().getSimpleName());
}
@Override
public void run() {
onStart(toString() + " has started.");
executeTask();
onEnd(toString() + " has finished.");
try {
executeTask();
} catch (Exception e) {
logger.error("run() Caught unhandled exception during task execution.", e);
}
}
protected abstract void executeTask();
@ -43,16 +45,4 @@ public abstract class FleetTask implements Runnable {
public String toString() {
return getClass().getSimpleName();
}
private void onStart(String message) {
if (taskListener != null)
taskListener.onTaskStart(message);
}
private void onEnd(String message) {
if (taskListener != null)
taskListener.onTaskEnd(message);
}
}