Skip to content

Commit

Permalink
Remove locking, has little effect for multiple Open VSX instances
Browse files Browse the repository at this point in the history
Add extra unit tests
  • Loading branch information
amvanbaren committed Jan 29, 2024
1 parent 84d0140 commit cadcb38
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 335 deletions.
13 changes: 13 additions & 0 deletions server/src/main/java/org/eclipse/openvsx/adapter/PublicIds.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/** ******************************************************************************
* Copyright (c) 2024 Precies. Software Ltd and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
* ****************************************************************************** */
package org.eclipse.openvsx.adapter;

public record PublicIds(String namespace, String extension) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.springframework.web.client.RestTemplate;

import java.time.ZoneId;
import java.util.UUID;

@Component
public class VSCodeIdService {
Expand Down Expand Up @@ -66,18 +67,24 @@ public void applicationStarted(ApplicationStartedEvent event) {
scheduler.scheduleRecurrently("VSCodeIdDailyUpdate", Cron.daily(3), ZoneId.of("UTC"), new HandlerJobRequest<>(VSCodeIdDailyUpdateJobRequestHandler.class));
}

public void getUpstreamPublicIds(Extension extension) {
extension.setPublicId(null);
extension.getNamespace().setPublicId(null);
public String getRandomPublicId() {
return UUID.randomUUID().toString();
}

public PublicIds getUpstreamPublicIds(Extension extension) {
String extensionPublicId = null;
String namespacePublicId = null;
var upstream = getUpstreamExtension(extension);
if (upstream != null) {
if (upstream.extensionId != null) {
extension.setPublicId(upstream.extensionId);
extensionPublicId = upstream.extensionId;
}
if (upstream.publisher != null && upstream.publisher.publisherId != null) {
extension.getNamespace().setPublicId(upstream.publisher.publisherId);
namespacePublicId = upstream.publisher.publisherId;
}
}

return new PublicIds(namespacePublicId, extensionPublicId);
}

private ExtensionQueryResult.Extension getUpstreamExtension(Extension extension) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,11 @@
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
public class VSCodeIdUpdateService {
private static final Logger LOGGER = LoggerFactory.getLogger(VSCodeIdUpdateService.class);
private static final Semaphore LOCK = new Semaphore(1);

@Autowired
RepositoryService repositories;
Expand All @@ -36,75 +33,69 @@ public class VSCodeIdUpdateService {
VSCodeIdService service;

public void update(String namespaceName, String extensionName) throws InterruptedException {
var acquired = LOCK.tryAcquire(15, TimeUnit.SECONDS);
if(!acquired) {
throw new RuntimeException("Failed to update public id for " + NamingUtil.toExtensionId(namespaceName, extensionName));
}
if(BuiltInExtensionUtil.isBuiltIn(namespaceName)) {
LOGGER.debug("SKIP BUILT-IN EXTENSION {}", NamingUtil.toExtensionId(namespaceName, extensionName));
return;
}

var extension = repositories.findPublicId(namespaceName, extensionName);
var extensionUpdates = new HashMap<Long, String>();
updateExtensionPublicId(extension, extensionUpdates);
updateExtensionPublicId(extension, extensionUpdates, false);
if(!extensionUpdates.isEmpty()) {
repositories.updateExtensionPublicIds(extensionUpdates);
}

var namespaceUpdates = new HashMap<Long, String>();
updateNamespacePublicId(extension, namespaceUpdates);
updateNamespacePublicId(extension, namespaceUpdates, false);
if(!namespaceUpdates.isEmpty()) {
repositories.updateNamespacePublicIds(namespaceUpdates);
}
LOCK.release();
}

private void updateExtensionPublicId(Extension extension, Map<Long, String> updates) {
private void updateExtensionPublicId(Extension extension, Map<Long, String> updates, boolean mustUpdate) {
LOGGER.debug("updateExtensionPublicId: {}", NamingUtil.toExtensionId(extension));
service.getUpstreamPublicIds(extension);
if(extension.getPublicId() == null) {
var publicId = "";
var oldPublicId = extension.getPublicId();
var newPublicId = service.getUpstreamPublicIds(extension).extension();
if(newPublicId == null || (mustUpdate && newPublicId.equals(oldPublicId))) {
do {
publicId = UUID.randomUUID().toString();
LOGGER.debug("RANDOM EXTENSION PUBLIC ID: {}", publicId);
} while(updates.containsValue(publicId) || repositories.extensionPublicIdExists(publicId));
LOGGER.debug("RANDOM PUT UPDATE: {} - {}", extension.getId(), publicId);
updates.put(extension.getId(), publicId);
} else {
LOGGER.debug("UPSTREAM PUT UPDATE: {} - {}", extension.getId(), extension.getPublicId());
updates.put(extension.getId(), extension.getPublicId());
var duplicatePublicId = repositories.findPublicId(extension.getPublicId());
newPublicId = service.getRandomPublicId();
LOGGER.debug("RANDOM EXTENSION PUBLIC ID: {}", newPublicId);
} while(updates.containsValue(newPublicId) || repositories.extensionPublicIdExists(newPublicId));
LOGGER.debug("RANDOM PUT UPDATE: {} - {}", extension.getId(), newPublicId);
updates.put(extension.getId(), newPublicId);
} else if (!newPublicId.equals(oldPublicId)) {
LOGGER.debug("UPSTREAM PUT UPDATE: {} - {}", extension.getId(), newPublicId);
updates.put(extension.getId(), newPublicId);
var duplicatePublicId = repositories.findPublicId(newPublicId);
if(duplicatePublicId != null) {
updateExtensionPublicId(duplicatePublicId, updates);
updateExtensionPublicId(duplicatePublicId, updates, true);
}
}
}

private void updateNamespacePublicId(Extension extension, Map<Long, String> updates) {
private void updateNamespacePublicId(Extension extension, Map<Long, String> updates, boolean mustUpdate) {
LOGGER.debug("updateNamespacePublicId: {}", extension.getNamespace().getName());
service.getUpstreamPublicIds(extension);
var namespace = extension.getNamespace();
if(namespace.getPublicId() == null) {
var publicId = "";
var oldPublicId = extension.getNamespace().getPublicId();
var newPublicId = service.getUpstreamPublicIds(extension).namespace();
var id = extension.getNamespace().getId();
if(newPublicId == null || (mustUpdate && newPublicId.equals(oldPublicId))) {
do {
publicId = UUID.randomUUID().toString();
LOGGER.debug("RANDOM NAMESPACE PUBLIC ID: {}", publicId);
} while(updates.containsValue(publicId) || repositories.namespacePublicIdExists(publicId));
LOGGER.debug("RANDOM PUT UPDATE: {} - {}", namespace.getId(), publicId);
updates.put(namespace.getId(), publicId);
} else {
LOGGER.debug("UPSTREAM PUT UPDATE: {} - {}", namespace.getId(), namespace.getPublicId());
updates.put(namespace.getId(), namespace.getPublicId());
var duplicatePublicId = repositories.findNamespacePublicId(namespace.getPublicId());
newPublicId = service.getRandomPublicId();
LOGGER.debug("RANDOM NAMESPACE PUBLIC ID: {}", newPublicId);
} while(updates.containsValue(newPublicId) || repositories.namespacePublicIdExists(newPublicId));
LOGGER.debug("RANDOM PUT UPDATE: {} - {}", id, newPublicId);
updates.put(id, newPublicId);
} else if(!newPublicId.equals(oldPublicId)) {
LOGGER.debug("UPSTREAM PUT UPDATE: {} - {}", id, newPublicId);
updates.put(id, newPublicId);
var duplicatePublicId = repositories.findNamespacePublicId(newPublicId);
if(duplicatePublicId != null) {
updateNamespacePublicId(duplicatePublicId, updates);
updateNamespacePublicId(duplicatePublicId, updates, true);
}
}
}

public void updateAll() throws InterruptedException {
LOCK.acquire();
LOGGER.debug("DAILY UPDATE ALL");
var extensions = repositories.findAllPublicIds();
var extensionPublicIdsMap = extensions.stream()
Expand All @@ -124,16 +115,16 @@ public void updateAll() throws InterruptedException {
}

LOGGER.trace("GET UPSTREAM PUBLIC ID: {} | {}", extension.getId(), NamingUtil.toExtensionId(extension));
service.getUpstreamPublicIds(extension);
var publicIds = service.getUpstreamPublicIds(extension);
if(upstreamExtensionPublicIds.get(extension.getId()) == null) {
LOGGER.trace("ADD EXTENSION PUBLIC ID: {} - {}", extension.getId(), extension.getPublicId());
upstreamExtensionPublicIds.put(extension.getId(), extension.getPublicId());
LOGGER.trace("ADD EXTENSION PUBLIC ID: {} - {}", extension.getId(), publicIds.extension());
upstreamExtensionPublicIds.put(extension.getId(), publicIds.extension());
}

var namespace = extension.getNamespace();
if(upstreamNamespacePublicIds.get(namespace.getId()) == null) {
LOGGER.trace("ADD NAMESPACE PUBLIC ID: {} - {}", namespace.getId(), namespace.getPublicId());
upstreamNamespacePublicIds.put(namespace.getId(), namespace.getPublicId());
LOGGER.trace("ADD NAMESPACE PUBLIC ID: {} - {}", namespace.getId(), publicIds.namespace());
upstreamNamespacePublicIds.put(namespace.getId(), publicIds.namespace());
}
}

Expand All @@ -160,8 +151,6 @@ public void updateAll() throws InterruptedException {

repositories.updateNamespacePublicIds(changedNamespacePublicIds);
}

LOCK.release();
}

private Map<Long, String> getChangedPublicIds(Map<Long, String> upstreamPublicIds, Map<Long, String> currentPublicIds) {
Expand Down Expand Up @@ -190,15 +179,15 @@ private void updatePublicIdNulls(Map<Long, String> changedPublicIds, Set<String>
return remove;
});

// put random UUIDs where upstream public id is missing
// put random public ids where upstream public id is missing
for(var key : changedPublicIds.keySet()) {
if(changedPublicIds.get(key) != null) {
continue;
}

String publicId = null;
while(newPublicIds.contains(publicId)) {
publicId = UUID.randomUUID().toString();
publicId = service.getRandomPublicId();
LOGGER.debug("NEW PUBLIC ID - {}: '{}'", key, publicId);
}

Expand Down
Loading

0 comments on commit cadcb38

Please sign in to comment.