Skip to content

Commit eac2ba0

Browse files
committed
adapt to latest version running on production
1 parent 9543826 commit eac2ba0

File tree

11 files changed

+75
-70
lines changed

11 files changed

+75
-70
lines changed

server/src/main/java/org/eclipse/openvsx/cache/CacheService.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,11 @@ public void evictExtensionJsons(Extension extension) {
101101
return;
102102
}
103103

104-
var namespaceName = extension.getNamespace().getName();
105-
var extensionName = extension.getName();
106-
107-
// Special optimization in case of a redis cache: evict all keys that match the <namespace>.<extension>* pattern
104+
// Special optimization in case of a redis cache: evict all keys that match the <namespace>.<extension>* pattern.
105+
// This uses the redis KEYS command that might take a while but considering the typical size of the EXTENSION_JSON
106+
// cache its acceptable.
108107
if (cache instanceof RedisCacheWriter redisCache) {
109-
redisCache.clean(CACHE_EXTENSION_JSON, extensionJsonCacheKey.generateWildcard(namespaceName, extensionName).getBytes());
108+
redisCache.clean(CACHE_EXTENSION_JSON, extensionJsonCacheKey.generateWildcard(extension).getBytes());
110109
return;
111110
}
112111

@@ -115,6 +114,8 @@ public void evictExtensionJsons(Extension extension) {
115114
.map(ExtensionVersion::getVersion)
116115
.forEach(versions::add);
117116

117+
var namespaceName = extension.getNamespace().getName();
118+
var extensionName = extension.getName();
118119
var targetPlatforms = new ArrayList<>(TargetPlatform.TARGET_PLATFORM_NAMES);
119120
targetPlatforms.add("null");
120121
for (var version : versions) {
@@ -154,6 +155,14 @@ public void evictLatestExtensionVersion(Extension extension) {
154155
return;
155156
}
156157

158+
// Special optimization in case of a redis cache: evict all keys that match the <namespace>.<extension>* pattern.
159+
// This uses the redis KEYS command that might take a while but considering the typical size of the EXTENSION_JSON
160+
// cache its acceptable.
161+
if (cache instanceof RedisCacheWriter redisCache) {
162+
redisCache.clean(CACHE_LATEST_EXTENSION_VERSION, latestExtensionVersionCacheKey.generateWildcard(extension).getBytes());
163+
return;
164+
}
165+
157166
var targetPlatforms = new ArrayList<>(TargetPlatform.TARGET_PLATFORM_NAMES);
158167
targetPlatforms.add(null);
159168
for (var targetPlatform : targetPlatforms) {

server/src/main/java/org/eclipse/openvsx/cache/ExtensionJsonCacheKeyGenerator.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* ****************************************************************************** */
1010
package org.eclipse.openvsx.cache;
1111

12+
import org.eclipse.openvsx.entities.Extension;
1213
import org.eclipse.openvsx.util.NamingUtil;
1314
import org.eclipse.openvsx.util.VersionAlias;
1415
import org.springframework.cache.interceptor.KeyGenerator;
@@ -29,7 +30,9 @@ public String generate(String namespaceName, String extensionName, String target
2930
return NamingUtil.toFileFormat(namespaceName, extensionName, version, targetPlatform);
3031
}
3132

32-
public String generateWildcard(String namespaceName, String extensionName) {
33+
public String generateWildcard(Extension extension) {
34+
var extensionName = extension.getName();
35+
var namespaceName = extension.getNamespace().getName();
3336
return NamingUtil.toExtensionId(namespaceName, extensionName) + "*";
3437
}
3538
}

server/src/main/java/org/eclipse/openvsx/cache/LatestExtensionVersionCacheKeyGenerator.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,10 @@ public String generate(Extension extension, String targetPlatform, boolean preRe
5656
return NamingUtil.toFileFormat(namespaceName, extensionName, targetPlatform, VersionAlias.LATEST) +
5757
",pre-release=" + preRelease + ",only-active=" + onlyActive + ",type=" + type;
5858
}
59+
60+
public String generateWildcard(Extension extension) {
61+
var extensionName = extension.getName();
62+
var namespaceName = extension.getNamespace().getName();
63+
return NamingUtil.toExtensionId(namespaceName, extensionName) + "*";
64+
}
5965
}

server/src/main/java/org/eclipse/openvsx/mirror/aop/DownloadCountServiceAspect.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
@ConditionalOnProperty(value = "ovsx.data.mirror.enabled", havingValue = "true")
2020
public class DownloadCountServiceAspect {
2121

22-
@Around("execution(* org.eclipse.openvsx.storage.log.DownloadCountService.isEnabled(..))")
22+
@Around("execution(* org.eclipse.openvsx.storage.log.*DownloadCountService.isEnabled(..))")
2323
public Object isEnabled() throws Throwable {
2424
return false;
2525
}

server/src/main/java/org/eclipse/openvsx/repositories/AzureDownloadCountProcessedItemRepository.java

Lines changed: 0 additions & 22 deletions
This file was deleted.

server/src/main/java/org/eclipse/openvsx/storage/log/AwsDownloadCountService.java

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package org.eclipse.openvsx.storage.log;
1111

1212
import org.apache.commons.lang3.StringUtils;
13+
import org.eclipse.openvsx.entities.Extension;
1314
import org.eclipse.openvsx.entities.FileResource;
1415
import org.eclipse.openvsx.storage.AwsStorageService;
1516
import org.eclipse.openvsx.util.TempFile;
@@ -52,6 +53,7 @@
5253
public class AwsDownloadCountService {
5354
private final Logger logger = LoggerFactory.getLogger(AwsDownloadCountService.class);
5455

56+
private static final String LOG_LOCATION_PREFIX = "AWSLogs/";
5557
private static final int MAX_KEYS = 100;
5658

5759
private final AwsStorageService awsStorageService;
@@ -60,8 +62,8 @@ public class AwsDownloadCountService {
6062
@Value("${ovsx.logs.aws.bucket:}")
6163
String bucket;
6264

63-
@Value("${ovsx.logs.aws.prefix:AWSLogs/}")
64-
String prefix;
65+
@Value("${ovsx.logs.aws.log-location-prefix:" + LOG_LOCATION_PREFIX + "}")
66+
String logLocationPrefix;
6567

6668
public AwsDownloadCountService(AwsStorageService awsStorageService, DownloadCountProcessor processor) {
6769
this.awsStorageService = awsStorageService;
@@ -138,39 +140,46 @@ private boolean processResponse(
138140
}
139141
logFiles.removeAll(failedItems);
140142

141-
for (var name : logFiles) {
142-
var processedOn = LocalDateTime.now();
143+
var allUpdatedExtensions = new HashMap<Long, Extension>();
143144

144-
if (processedOn.isAfter(maxExecutionTime)) {
145-
logger.info("Failed to process all download counts within timeslot, next job run is at {}", nextJobRunTime);
146-
return false;
147-
}
145+
try {
146+
for (var name : logFiles) {
147+
var processedOn = LocalDateTime.now();
148148

149-
var success = false;
150-
stopWatch.start();
151-
try {
152-
var counts = processLogFile(name);
153-
if (!counts.isEmpty()) {
154-
var extensionDownloads = processor.processDownloadCounts(FileResource.STORAGE_AWS, counts);
155-
var updatedExtensions = processor.increaseDownloadCounts(extensionDownloads);
156-
processor.evictCaches(updatedExtensions);
157-
processor.updateSearchEntries(updatedExtensions);
149+
if (processedOn.isAfter(maxExecutionTime)) {
150+
logger.info("Failed to process all download counts within timeslot, next job run is at {}", nextJobRunTime);
151+
return false;
158152
}
159153

160-
success = true;
161-
} catch (Exception e) {
162-
logger.error("failed to process log file: {}", name, e);
163-
}
154+
var success = false;
155+
stopWatch.start();
156+
try {
157+
var counts = processLogFile(name);
158+
if (!counts.isEmpty()) {
159+
var extensionDownloads = processor.processDownloadCounts(FileResource.STORAGE_AWS, counts);
160+
var updatedExtensions = processor.increaseDownloadCounts(extensionDownloads);
161+
updatedExtensions.forEach(extension -> allUpdatedExtensions.put(extension.getId(), extension));
162+
}
163+
164+
success = true;
165+
} catch (Exception e) {
166+
logger.error("failed to process log file: {}", name, e);
167+
}
164168

165-
stopWatch.stop();
166-
var executionTime = (int) stopWatch.lastTaskInfo().getTimeMillis();
167-
processor.persistProcessedItem(name, FileResource.STORAGE_AWS, processedOn, executionTime, success);
168-
if (success) {
169-
deleteFile(name);
169+
stopWatch.stop();
170+
var executionTime = (int) stopWatch.lastTaskInfo().getTimeMillis();
171+
processor.persistProcessedItem(name, FileResource.STORAGE_AWS, processedOn, executionTime, success);
172+
if (success) {
173+
deleteFile(name);
174+
}
170175
}
171-
}
172176

173-
return true;
177+
return true;
178+
} finally {
179+
// evict caches and update search entries for all updated extensions
180+
allUpdatedExtensions.values().forEach(processor::evictCaches);
181+
processor.updateSearchEntries(allUpdatedExtensions.values().stream().toList());
182+
}
174183
}
175184

176185
private Map<String, Integer> processLogFile(String fileName) throws IOException {
@@ -188,6 +197,8 @@ private Map<String, Integer> processLogFile(String fileName) throws IOException
188197
continue;
189198
}
190199

200+
// Format:
201+
// date time x-edge-location sc-bytes c-ip cs-method cs(Host) cs-uri-stem sc-status cs(Referer) cs(User-Agent) cs-uri-query cs(Cookie) x-edge-result-type x-edge-request-id x-host-header cs-protocol cs-bytes time-taken x-forwarded-for ssl-protocol ssl-cipher x-edge-response-result-type cs-protocol-version fle-status fle-encrypted-fields c-port time-to-first-byte x-edge-detailed-result-type sc-content-type sc-content-len sc-range-start sc-range-end
191202
var components = line.split("[ \t]+");
192203

193204
if (isGetOperation(components) && isStatusOk(components) && isExtensionPackageUri(components)) {
@@ -232,7 +243,7 @@ private void deleteFile(String objectKey) {
232243
}
233244

234245
private ListObjectsV2Response listObjects(String continuationToken) {
235-
var builder = ListObjectsV2Request.builder().bucket(bucket).maxKeys(MAX_KEYS).prefix(prefix);
246+
var builder = ListObjectsV2Request.builder().bucket(bucket).maxKeys(MAX_KEYS).prefix(logLocationPrefix);
236247

237248
if (continuationToken != null) {
238249
builder.continuationToken(continuationToken);

server/src/main/java/org/eclipse/openvsx/storage/log/AzureDownloadCountService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ private boolean processResponse(PagedResponse<BlobItem> response, StopWatch stop
145145
if (!files.isEmpty()) {
146146
var extensionDownloads = processor.processDownloadCounts(FileResource.STORAGE_AZURE, files);
147147
var updatedExtensions = processor.increaseDownloadCounts(extensionDownloads);
148-
processor.evictCaches(updatedExtensions);
148+
updatedExtensions.forEach(processor::evictCaches);
149149
processor.updateSearchEntries(updatedExtensions);
150150
}
151151

server/src/main/java/org/eclipse/openvsx/storage/log/DownloadCountProcessor.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ public List<Extension> increaseDownloadCounts(Map<Long, Integer> extensionDownlo
8888
});
8989
}
9090

91-
@Transactional //needs transaction for lazy-loading versions
92-
public void evictCaches(List<Extension> extensions) {
93-
Observation.createNotStarted("DownloadCountProcessor#evictCaches", observations).observe(() -> extensions.forEach(extension -> {
94-
extension = entityManager.merge(extension);
95-
cache.evictExtensionJsons(extension);
96-
cache.evictLatestExtensionVersion(extension);
97-
}));
91+
@Transactional // needs transaction for lazy-loading versions
92+
public void evictCaches(Extension extension) {
93+
Observation.createNotStarted("DownloadCountProcessor#evictCaches", observations).observe(() -> {
94+
var mergedExtension = entityManager.merge(extension);
95+
cache.evictExtensionJsons(mergedExtension);
96+
cache.evictLatestExtensionVersion(mergedExtension);
97+
});
9898
}
9999

100100
public void updateSearchEntries(List<Extension> extensions) {

server/src/main/jooq-gen/org/eclipse/openvsx/jooq/Indexes.java

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

server/src/main/jooq-gen/org/eclipse/openvsx/jooq/tables/DownloadCountProcessedItem.java

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)