diff --git a/src/main/java/io/linuxserver/fleet/core/FleetBeans.java b/src/main/java/io/linuxserver/fleet/core/FleetBeans.java index 0199522..fb33103 100644 --- a/src/main/java/io/linuxserver/fleet/core/FleetBeans.java +++ b/src/main/java/io/linuxserver/fleet/core/FleetBeans.java @@ -27,7 +27,11 @@ import io.linuxserver.fleet.db.dao.DefaultUserDAO; import io.linuxserver.fleet.db.migration.DatabaseVersion; import io.linuxserver.fleet.delegate.*; import io.linuxserver.fleet.dockerhub.DockerHubV2Client; +import io.linuxserver.fleet.dockerhub.queue.DockerHubSyncConsumer; +import io.linuxserver.fleet.dockerhub.queue.DockerHubSyncQueue; import io.linuxserver.fleet.thread.TaskManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** *

@@ -36,6 +40,8 @@ import io.linuxserver.fleet.thread.TaskManager; */ public class FleetBeans { + private static final Logger LOGGER = LoggerFactory.getLogger(FleetBeans.class); + private final FleetProperties properties; private final ImageDelegate imageDelegate; private final RepositoryDelegate repositoryDelegate; @@ -46,6 +52,7 @@ public class FleetBeans { private final TaskDelegate taskDelegate; private final UserDelegate userDelegate; private final PasswordEncoder passwordEncoder; + private final DockerHubSyncQueue dockerHubSyncQueue; /** * Ensures the database is kept up to date. @@ -68,6 +75,14 @@ public class FleetBeans { userDelegate = new UserDelegate(passwordEncoder, new DefaultUserDAO(databaseConnection)); taskDelegate = new TaskDelegate(this); authenticationDelegate = new DefaultAuthenticationDelegate(AuthenticatorFactory.getAuthenticator(this)); + dockerHubSyncQueue = new DockerHubSyncQueue(); + + final int consumerThreadCount = properties.getQueueThreadCount(); + for (int i = 0; i < consumerThreadCount; i++) { + + LOGGER.info("Starting consumer thread " + i + "..."); + new DockerHubSyncConsumer(imageDelegate, dockerHubSyncQueue, "SyncThread-" + i).start(); + } } public FleetProperties getProperties() { diff --git a/src/main/java/io/linuxserver/fleet/core/FleetProperties.java b/src/main/java/io/linuxserver/fleet/core/FleetProperties.java index 6f5b2b4..8b38434 100644 --- a/src/main/java/io/linuxserver/fleet/core/FleetProperties.java +++ b/src/main/java/io/linuxserver/fleet/core/FleetProperties.java @@ -79,6 +79,10 @@ public class FleetProperties { return new DockerHubCredentials(username, password); } + public int getQueueThreadCount() { + return Integer.parseInt(getStringProperty("fleet.queue.threads")); + } + /** *

* Obtains the property value from three separate sources: first from the config file. If not present, it will look diff --git a/src/main/java/io/linuxserver/fleet/db/dao/DefaultImageDAO.java b/src/main/java/io/linuxserver/fleet/db/dao/DefaultImageDAO.java index 5ae5a3e..a01b45b 100644 --- a/src/main/java/io/linuxserver/fleet/db/dao/DefaultImageDAO.java +++ b/src/main/java/io/linuxserver/fleet/db/dao/DefaultImageDAO.java @@ -23,6 +23,7 @@ import io.linuxserver.fleet.db.query.InsertUpdateStatus; import io.linuxserver.fleet.db.query.LimitedResult; import io.linuxserver.fleet.model.internal.Image; import io.linuxserver.fleet.model.internal.ImagePullStat; +import io.linuxserver.fleet.model.internal.Repository; import io.linuxserver.fleet.model.internal.Tag; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -230,7 +231,10 @@ public class DefaultImageDAO implements ImageDAO { Image image = new Image( results.getInt("ImageId"), - results.getInt("RepositoryId"), + new Repository( + results.getInt("RepositoryId"), + results.getString("RepositoryName") + ), results.getString("ImageName"), new Tag( results.getString("LatestTagVersion"), diff --git a/src/main/java/io/linuxserver/fleet/delegate/DockerHubDelegate.java b/src/main/java/io/linuxserver/fleet/delegate/DockerHubDelegate.java index 369cc6e..e03084b 100644 --- a/src/main/java/io/linuxserver/fleet/delegate/DockerHubDelegate.java +++ b/src/main/java/io/linuxserver/fleet/delegate/DockerHubDelegate.java @@ -63,6 +63,10 @@ public class DockerHubDelegate { return images; } + public DockerImage fetchImageFromRepository(String repositoryName, String imageName) { + return convertImage(dockerHubClient.fetchImageFromRepository(repositoryName, imageName)); + } + public List fetchAllTagsForImage(String repositoryName, String imageName) { return dockerHubClient.fetchAllTagsForImage(repositoryName, imageName).stream().map(this::convertTag).collect(Collectors.toList()); } @@ -80,6 +84,10 @@ public class DockerHubDelegate { private DockerImage convertImage(DockerHubV2Image dockerHubV2Image) { + if (dockerHubV2Image == null) { + return null; + } + return new DockerImage( dockerHubV2Image.getName(), dockerHubV2Image.getNamespace(), @@ -92,6 +100,10 @@ public class DockerHubDelegate { private DockerTag convertTag(DockerHubV2Tag dockerHubV2Tag) { + if (dockerHubV2Tag == null) { + return null; + } + return new DockerTag( dockerHubV2Tag.getName(), dockerHubV2Tag.getFullSize(), diff --git a/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncConsumer.java b/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncConsumer.java new file mode 100644 index 0000000..911ac11 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncConsumer.java @@ -0,0 +1,47 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.dockerhub.queue; + +import io.linuxserver.fleet.delegate.ImageDelegate; +import io.linuxserver.fleet.exception.SaveException; +import io.linuxserver.fleet.model.internal.Image; +import io.linuxserver.fleet.queue.AbstractQueueConsumer; +import io.linuxserver.fleet.queue.RequestQueue; + +public class DockerHubSyncConsumer extends AbstractQueueConsumer { + + private final ImageDelegate imageDelegate; + + public DockerHubSyncConsumer(ImageDelegate imageDelegate, RequestQueue requestQueue, String name) { + super(requestQueue, name); + this.imageDelegate = imageDelegate; + } + + @Override + protected void handleResponse(DockerHubSyncResponse response) { + + try { + + final Image image = response.getImage(); + imageDelegate.saveImage(image); + + } catch (SaveException e) { + getLogger().error("handleResponse unable to save image: {}", e.getMessage()); + } + } +} diff --git a/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncQueue.java b/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncQueue.java new file mode 100644 index 0000000..54535e4 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncQueue.java @@ -0,0 +1,23 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.dockerhub.queue; + +import io.linuxserver.fleet.queue.AbstractRequestQueue; + +public class DockerHubSyncQueue extends AbstractRequestQueue { +} diff --git a/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncRequest.java b/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncRequest.java new file mode 100644 index 0000000..3b1b89d --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncRequest.java @@ -0,0 +1,54 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.dockerhub.queue; + +import io.linuxserver.fleet.delegate.DockerHubDelegate; +import io.linuxserver.fleet.model.internal.Image; +import io.linuxserver.fleet.queue.FleetRequest; + +import java.util.Objects; + +public class DockerHubSyncRequest implements FleetRequest { + + private final DockerHubDelegate dockerHubDelegate; + private final Image image; + + public DockerHubSyncRequest(DockerHubDelegate dockerHubDelegate, Image image) { + + this.dockerHubDelegate = dockerHubDelegate; + this.image = image; + } + + @Override + public DockerHubSyncResponse execute() { + return new DockerHubSyncResponse(dockerHubDelegate, image); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DockerHubSyncRequest that = (DockerHubSyncRequest) o; + return Objects.equals(image, that.image); + } + + @Override + public int hashCode() { + return Objects.hash(image); + } +} diff --git a/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncResponse.java b/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncResponse.java new file mode 100644 index 0000000..f3f84d1 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/dockerhub/queue/DockerHubSyncResponse.java @@ -0,0 +1,99 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.dockerhub.queue; + +import io.linuxserver.fleet.delegate.DockerHubDelegate; +import io.linuxserver.fleet.model.docker.DockerImage; +import io.linuxserver.fleet.model.docker.DockerTag; +import io.linuxserver.fleet.model.internal.Image; +import io.linuxserver.fleet.model.internal.Tag; +import io.linuxserver.fleet.queue.FleetResponse; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DockerHubSyncResponse implements FleetResponse { + + private final DockerHubDelegate dockerHubDelegate; + private final Image image; + + public DockerHubSyncResponse(DockerHubDelegate dockerHubDelegate, Image image) { + + this.dockerHubDelegate = dockerHubDelegate; + this.image = Image.copyOf(image); + } + + @Override + public void handle() { + + DockerImage dockerImage = dockerHubDelegate.fetchImageFromRepository(image.getRepository().getName(), image.getName()); + String versionMask = getVersionMask(image.getRepository().getVersionMask(), image.getVersionMask()); + Tag maskedVersion = getLatestTagAndCreateMaskedVersion(versionMask); + + image.withPullCount(dockerImage.getPullCount()); + image.updateTag(maskedVersion); + } + + public Image getImage() { + return image; + } + + private String getVersionMask(String repositoryMask, String imageMask) { + return imageMask == null ? repositoryMask : imageMask; + } + + private Tag getLatestTagAndCreateMaskedVersion(String versionMask) { + + DockerTag tag = dockerHubDelegate.fetchLatestImageTag(image.getRepository().getName(), image.getName()); + + if (null == tag) + return Tag.NONE; + + if (isTagJustLatestAndNotAVersion(tag) || null == versionMask) + return new Tag(tag.getName(), tag.getName(), tag.getBuildDate()); + + return new Tag(tag.getName(), extractMaskedVersion(tag.getName(), versionMask), tag.getBuildDate()); + } + + private String extractMaskedVersion(String fullTag, String versionMask) { + + Pattern pattern = Pattern.compile(versionMask); + Matcher matcher = pattern.matcher(fullTag); + + if (matcher.matches()) { + + StringBuilder tagBuilder = new StringBuilder(); + + for (int groupNum = 1; groupNum <= matcher.groupCount(); groupNum++) + tagBuilder.append(matcher.group(groupNum)); + + return tagBuilder.toString(); + } + + return fullTag; + } + + /** + *

+ * If the top-level tag is not versioned, a mask can't be applied. + *

+ */ + private boolean isTagJustLatestAndNotAVersion(DockerTag tag) { + return "latest".equals(tag.getName()); + } +} diff --git a/src/main/java/io/linuxserver/fleet/model/internal/Image.java b/src/main/java/io/linuxserver/fleet/model/internal/Image.java index 83e987c..4a85650 100644 --- a/src/main/java/io/linuxserver/fleet/model/internal/Image.java +++ b/src/main/java/io/linuxserver/fleet/model/internal/Image.java @@ -29,34 +29,34 @@ import java.util.Objects; */ public class Image extends PersistableItem { - private final int repositoryId; - private final String name; + private final Repository repository; + private final String name; - private Tag tag; - private long pullCount; - private String versionMask; - private boolean unstable; - private boolean hidden; + private Tag tag; + private long pullCount; + private String versionMask; + private boolean unstable; + private boolean hidden; - private boolean deprecated; - private String deprecationReason; + private boolean deprecated; + private String deprecationReason; - public Image(Integer id, int repositoryId, String name, Tag latestVersion) { + public Image(Integer id, Repository repository, String name, Tag latestVersion) { super(id); this.name = name; - this.repositoryId = repositoryId; + this.repository = repository; this.tag = new Tag(latestVersion.getVersion(), latestVersion.getMaskedVersion(), latestVersion.getBuildDate()); } - public Image(int repositoryId, String name) { - this(null, repositoryId, name, Tag.NONE); + public Image(Repository repository, String name) { + this(null, repository, name, Tag.NONE); } public static Image copyOf(Image image) { - Image cloned = new Image(image.getId(), image.repositoryId, image.name, image.tag); + Image cloned = new Image(image.getId(), Repository.copyOf(image.repository), image.name, image.tag); cloned.pullCount = image.pullCount; cloned.versionMask = image.versionMask; cloned.unstable = image.unstable; @@ -108,7 +108,11 @@ public class Image extends PersistableItem { } public int getRepositoryId() { - return repositoryId; + return repository.getId(); + } + + public Repository getRepository() { + return repository; } public String getName() { @@ -166,11 +170,11 @@ public class Image extends PersistableItem { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Image image = (Image) o; - return repositoryId == image.repositoryId && Objects.equals(name, image.name); + return Objects.equals(repository, image.repository) && Objects.equals(name, image.name); } @Override public int hashCode() { - return Objects.hash(repositoryId, name); + return Objects.hash(repository, name); } } diff --git a/src/main/java/io/linuxserver/fleet/model/internal/Repository.java b/src/main/java/io/linuxserver/fleet/model/internal/Repository.java index 6289df2..a8262e4 100644 --- a/src/main/java/io/linuxserver/fleet/model/internal/Repository.java +++ b/src/main/java/io/linuxserver/fleet/model/internal/Repository.java @@ -17,6 +17,8 @@ package io.linuxserver.fleet.model.internal; +import java.util.Objects; + public class Repository extends PersistableItem { private final String name; @@ -36,6 +38,10 @@ public class Repository extends PersistableItem { this.name = name; } + public static Repository copyOf(Repository repository) { + return new Repository(repository.getId(), repository.name).withVersionMask(repository.versionMask).withSyncEnabled(repository.syncEnabled); + } + public Repository withVersionMask(String versionMask) { this.versionMask = versionMask; @@ -59,4 +65,17 @@ public class Repository extends PersistableItem { public boolean isSyncEnabled() { return syncEnabled; } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Repository that = (Repository) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } } diff --git a/src/main/java/io/linuxserver/fleet/queue/AbstractQueueConsumer.java b/src/main/java/io/linuxserver/fleet/queue/AbstractQueueConsumer.java new file mode 100644 index 0000000..6ce840c --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/queue/AbstractQueueConsumer.java @@ -0,0 +1,69 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.queue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractQueueConsumer> extends Thread implements QueueConsumer { + + private final Logger LOGGER = LoggerFactory.getLogger(getClass().getName()); + + private final RequestQueue requestQueue; + + public AbstractQueueConsumer(final RequestQueue requestQueue, final String name) { + super(name + "-Consumer"); + this.requestQueue = requestQueue; + } + + @Override + public void run() { + + while (true) { + consume(); + } + } + + @Override + public void start() { + + getLogger().info("Starting..."); + super.start(); + } + + @Override + public void consume() { + + try { + + T request = requestQueue.takeOneRequest(); + R response = request.execute(); + + handleResponse(response); + + } catch (Exception e) { + getLogger().error("consume caught unhandled exception", e); + } + } + + protected abstract void handleResponse(R response); + + public Logger getLogger() { + return LOGGER; + } +} diff --git a/src/main/java/io/linuxserver/fleet/queue/AbstractRequestQueue.java b/src/main/java/io/linuxserver/fleet/queue/AbstractRequestQueue.java new file mode 100644 index 0000000..3392685 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/queue/AbstractRequestQueue.java @@ -0,0 +1,64 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.queue; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingDeque; + +public class AbstractRequestQueue> implements RequestQueue { + + private final Logger LOGGER = LoggerFactory.getLogger(getClass().getName()); + + private final BlockingQueue requestQueue; + + public AbstractRequestQueue() { + this.requestQueue = new LinkedBlockingDeque<>(); + } + + @Override + public synchronized void enqueueRequest(final T request) { + + try { + + if (!requestQueue.contains(request)) { + + final boolean added = requestQueue.add(request); + if (!added) { + LOGGER.warn("enqueueRequest unable to add request to queue"); + } + } + + } catch (Exception e) { + LOGGER.error("enqueueRequest caught unhandled exception {}", e.getMessage()); + } + } + + @Override + public synchronized T takeOneRequest() { + + try { + return requestQueue.take(); + } catch (InterruptedException e) { + LOGGER.error("takeOneRequest was interrupted: {}", e.getMessage()); + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/io/linuxserver/fleet/queue/FleetRequest.java b/src/main/java/io/linuxserver/fleet/queue/FleetRequest.java new file mode 100644 index 0000000..5e3616d --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/queue/FleetRequest.java @@ -0,0 +1,23 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.queue; + +public interface FleetRequest { + + T execute(); +} diff --git a/src/main/java/io/linuxserver/fleet/queue/FleetResponse.java b/src/main/java/io/linuxserver/fleet/queue/FleetResponse.java new file mode 100644 index 0000000..91a12bd --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/queue/FleetResponse.java @@ -0,0 +1,23 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.queue; + +public interface FleetResponse { + + void handle(); +} diff --git a/src/main/java/io/linuxserver/fleet/queue/QueueConsumer.java b/src/main/java/io/linuxserver/fleet/queue/QueueConsumer.java new file mode 100644 index 0000000..d49a187 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/queue/QueueConsumer.java @@ -0,0 +1,23 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.queue; + +public interface QueueConsumer> { + + void consume(); +} diff --git a/src/main/java/io/linuxserver/fleet/queue/RequestQueue.java b/src/main/java/io/linuxserver/fleet/queue/RequestQueue.java new file mode 100644 index 0000000..14c4ba0 --- /dev/null +++ b/src/main/java/io/linuxserver/fleet/queue/RequestQueue.java @@ -0,0 +1,25 @@ +/* + * 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 . + */ + +package io.linuxserver.fleet.queue; + +public interface RequestQueue { + + void enqueueRequest(T request); + + T takeOneRequest(); +} diff --git a/src/main/java/io/linuxserver/fleet/sync/DefaultSynchronisationState.java b/src/main/java/io/linuxserver/fleet/sync/DefaultSynchronisationState.java index 6c713b0..ab05aa8 100644 --- a/src/main/java/io/linuxserver/fleet/sync/DefaultSynchronisationState.java +++ b/src/main/java/io/linuxserver/fleet/sync/DefaultSynchronisationState.java @@ -137,7 +137,7 @@ public class DefaultSynchronisationState implements SynchronisationState { try { DockerImage dockerImage = images.get(i); - Image image = configureImage(repository.getId(), dockerImage, context); + Image image = configureImage(repository, dockerImage, context); String versionMask = getVersionMask(repository.getVersionMask(), image.getVersionMask()); Tag maskedVersion = getLatestTagAndCreateMaskedVersion(repository.getName(), image.getName(), versionMask, context); @@ -230,15 +230,15 @@ public class DefaultSynchronisationState implements SynchronisationState { * Looks up the image in the database to see if it already exists. If it does, it gets returned, otherwise a base * image is created with just the top-level information, as the rest will get updated later. */ - private Image configureImage(int repositoryId, DockerImage dockerHubImage, SynchronisationContext context) { + private Image configureImage(Repository repository, DockerImage dockerHubImage, SynchronisationContext context) { - Image image = context.getImageDelegate().findImageByRepositoryAndImageName(repositoryId, dockerHubImage.getName()); + Image image = context.getImageDelegate().findImageByRepositoryAndImageName(repository.getId(), dockerHubImage.getName()); if (isImageNew(image)) { try { - return context.getImageDelegate().saveImage(new Image(repositoryId, dockerHubImage.getName())); + return context.getImageDelegate().saveImage(new Image(repository, dockerHubImage.getName())); } catch (SaveException e) { LOGGER.error("Tried to save new image during sync but failed", e); diff --git a/src/main/resources/db/migration/V1.10__UpdateImageViewWithRepository.sql b/src/main/resources/db/migration/V1.10__UpdateImageViewWithRepository.sql new file mode 100644 index 0000000..4969880 --- /dev/null +++ b/src/main/resources/db/migration/V1.10__UpdateImageViewWithRepository.sql @@ -0,0 +1,24 @@ +DELIMITER // + +CREATE OR REPLACE VIEW `Image_View` AS ( + + SELECT + images.`id` AS `ImageId`, + images.`repository` AS `RepositoryId`, + repositories.`name` AS `RepositoryName`, + images.`name` AS `ImageName`, + images.`pulls` AS `ImagePullCount`, + images.`latest_version` AS `LatestTagVersion`, + images.`latest_version_raw` AS `LatestMaskedTagVersion`, + images.`latest_version_buildtime` AS `LatestTagBuildDate`, + images.`version_mask` AS `ImageVersionMask`, + images.`hidden` AS `ImageHidden`, + images.`unstable` AS `ImageUnstable`, + images.`deprecated` AS `ImageDeprecated`, + images.`deprecation_reason` AS `ImageDeprecationReason`, + images.`modified` AS `ModifiedTime` + FROM + Images images + JOIN Repositories repositories ON repositories.`id` = images.`repository` +); +// \ No newline at end of file