Skip to content

Commit

Permalink
Added AwsEcrCache
Browse files Browse the repository at this point in the history
Signed-off-by: munishchouhan <[email protected]>
  • Loading branch information
munishchouhan committed Dec 19, 2024
1 parent d5c086d commit 1e13c9f
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 14 deletions.
32 changes: 18 additions & 14 deletions src/main/groovy/io/seqera/wave/service/aws/AwsEcrService.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,13 @@ import java.util.regex.Pattern
import com.github.benmanes.caffeine.cache.AsyncLoadingCache
import com.github.benmanes.caffeine.cache.CacheLoader
import com.github.benmanes.caffeine.cache.Caffeine
import com.google.common.hash.Hashing
import groovy.transform.Canonical
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import io.micronaut.scheduling.TaskExecutors
import io.seqera.wave.service.aws.cache.AwsEcrCache
import io.seqera.wave.store.cache.TieredCacheKey
import io.seqera.wave.util.StringUtils
import jakarta.annotation.PostConstruct
import jakarta.inject.Inject
Expand Down Expand Up @@ -56,11 +59,22 @@ class AwsEcrService {
static final private Pattern AWS_ECR_PUBLIC = ~/public\.ecr\.aws/

@Canonical
private static class AwsCreds {
private static class AwsCreds implements TieredCacheKey {
String accessKey
String secretKey
String region
boolean ecrPublic

@Override
String stableHash() {
final h = Hashing.sipHash24().newHasher()
for( Object it : [accessKey, secretKey, region, ecrPublic] ) {
if( it!=null )
h.putUnencodedChars(it.toString())
h.putUnencodedChars('/')
}
return h.hash()
}
}

@Canonical
Expand All @@ -82,18 +96,8 @@ class AwsEcrService {
@Named(TaskExecutors.BLOCKING)
private ExecutorService ioExecutor

// FIXME https://github.com/seqeralabs/wave/issues/747
private AsyncLoadingCache<AwsCreds, String> cache

@PostConstruct
private void init() {
cache = Caffeine
.newBuilder()
.maximumSize(10_000)
.expireAfterWrite(3, TimeUnit.HOURS)
.executor(ioExecutor)
.buildAsync(loader)
}
@Inject
AwsEcrCache cache

private EcrClient ecrClient(String accessKey, String secretKey, String region) {
EcrClient.builder()
Expand Down Expand Up @@ -142,7 +146,7 @@ class AwsEcrService {
// get the token from the cache, if missing the it's automatically
// fetch using the AWS ECR client
// FIXME https://github.com/seqeralabs/wave/issues/747
return cache.synchronous().get(new AwsCreds(accessKey,secretKey,region,isPublic))
return cache.get(new AwsCreds(accessKey,secretKey,region,isPublic).stableHash())
}
catch (Exception e) {
final type = isPublic ? "ECR public" : "ECR"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Wave, containers provisioning service
* Copyright (c) 2023-2024, Seqera Labs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package io.seqera.wave.service.aws.cache

import java.time.Duration

import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import io.micronaut.context.annotation.Value
import io.micronaut.core.annotation.Nullable
import io.seqera.wave.store.cache.AbstractTieredCache
import io.seqera.wave.store.cache.L2TieredCache
import io.seqera.wave.tower.client.cache.ClientEncoder
import jakarta.inject.Singleton

/**
* Implement a tiered cache for AWS ECR client
*
* @author Munish Chouhan <[email protected]>
*/
@Slf4j
@Singleton
@CompileStatic
class AwsEcrCache extends AbstractTieredCache {
AwsEcrCache(@Nullable L2TieredCache l2,
@Value('${wave.aws.ecr.cache.duration:3h}') Duration duration,
@Value('${wave.aws.ecr.cache.max-size:10000}') int maxSize)
{
super(l2, ClientEncoder.instance(), duration, maxSize)
}

@Override
protected getName() {
return 'aws-ecr-cache'
}

@Override
protected String getPrefix() {
return 'aws-ecr-cache/v1'
}
}
30 changes: 30 additions & 0 deletions src/main/groovy/io/seqera/wave/store/cache/TieredCacheKey.groovy
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Wave, containers provisioning service
* Copyright (c) 2023-2024, Seqera Labs
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package io.seqera.wave.store.cache

/**
* Implement a tiered cache for AWS ECR client
*
* @author Munish Chouhan <[email protected]>
*/
interface TieredCacheKey {

String stableHash()

}

0 comments on commit 1e13c9f

Please sign in to comment.