From 909bda14000957e380e4e0414948693d122ee3e8 Mon Sep 17 00:00:00 2001 From: munishchouhan Date: Mon, 15 Jul 2024 14:26:07 +0200 Subject: [PATCH] added deleteAllMatchingEntries Signed-off-by: munishchouhan --- .../counter/AbstractCounterStore.groovy | 5 +++++ .../wave/service/counter/CounterStore.groovy | 6 +++++ .../counter/impl/CounterProvider.groovy | 8 +++++++ .../counter/impl/LocalCounterProvider.groovy | 12 ++++++++++ .../counter/impl/RedisCounterProvider.groovy | 13 +++++++++++ .../impl/LocalCounterProviderTest.groovy | 22 +++++++++++++++++++ .../impl/RedisCounterProviderTest.groovy | 22 +++++++++++++++++++ 7 files changed, 88 insertions(+) diff --git a/src/main/groovy/io/seqera/wave/service/counter/AbstractCounterStore.groovy b/src/main/groovy/io/seqera/wave/service/counter/AbstractCounterStore.groovy index 3e51f771c..232fb5990 100644 --- a/src/main/groovy/io/seqera/wave/service/counter/AbstractCounterStore.groovy +++ b/src/main/groovy/io/seqera/wave/service/counter/AbstractCounterStore.groovy @@ -55,4 +55,9 @@ abstract class AbstractCounterStore implements CounterStore { Map getAllMatchingEntries(String pattern) { provider.getAllMatchingEntries(getPrefix(), pattern) } + + @Override + void deleteAllMatchingEntries(String pattern) { + provider.getAllMatchingEntries(getPrefix(), pattern) + } } diff --git a/src/main/groovy/io/seqera/wave/service/counter/CounterStore.groovy b/src/main/groovy/io/seqera/wave/service/counter/CounterStore.groovy index 41e64c4e0..c91b46067 100644 --- a/src/main/groovy/io/seqera/wave/service/counter/CounterStore.groovy +++ b/src/main/groovy/io/seqera/wave/service/counter/CounterStore.groovy @@ -34,4 +34,10 @@ interface CounterStore { * @return all the entries whose field matches 'pattern' */ Map getAllMatchingEntries(String pattern) + + /** + * @param pattern + * @return void + */ + void deleteAllMatchingEntries(String pattern) } diff --git a/src/main/groovy/io/seqera/wave/service/counter/impl/CounterProvider.groovy b/src/main/groovy/io/seqera/wave/service/counter/impl/CounterProvider.groovy index c13f8f4e2..64823b435 100644 --- a/src/main/groovy/io/seqera/wave/service/counter/impl/CounterProvider.groovy +++ b/src/main/groovy/io/seqera/wave/service/counter/impl/CounterProvider.groovy @@ -35,4 +35,12 @@ interface CounterProvider { * @return all the entries whose field matches 'pattern' */ Map getAllMatchingEntries(String key, String pattern) + + /** + * + * @param key + * @param pattern + * @return void + */ + void deleteAllMatchingEntries(String key, String pattern) } diff --git a/src/main/groovy/io/seqera/wave/service/counter/impl/LocalCounterProvider.groovy b/src/main/groovy/io/seqera/wave/service/counter/impl/LocalCounterProvider.groovy index c7ea99ac6..b94c07cff 100644 --- a/src/main/groovy/io/seqera/wave/service/counter/impl/LocalCounterProvider.groovy +++ b/src/main/groovy/io/seqera/wave/service/counter/impl/LocalCounterProvider.groovy @@ -61,4 +61,16 @@ class LocalCounterProvider implements CounterProvider { } return result } + + @Override + void deleteAllMatchingEntries(String key, String pattern) { + Pattern compiledPattern = Pattern.compile(pattern.replace('*', '.*')) + Map keyStore = store.get(key) + if (keyStore){ + def matchingPairs = keyStore.findAll {entry -> compiledPattern.matcher(entry.key).matches()} + matchingPairs.each { k, v -> + keyStore.remove(k) + } + } + } } diff --git a/src/main/groovy/io/seqera/wave/service/counter/impl/RedisCounterProvider.groovy b/src/main/groovy/io/seqera/wave/service/counter/impl/RedisCounterProvider.groovy index 5e28467bf..c0e9bb1d9 100644 --- a/src/main/groovy/io/seqera/wave/service/counter/impl/RedisCounterProvider.groovy +++ b/src/main/groovy/io/seqera/wave/service/counter/impl/RedisCounterProvider.groovy @@ -70,4 +70,17 @@ class RedisCounterProvider implements CounterProvider { return result } } + + @Override + void deleteAllMatchingEntries(String key, String pattern) { + try(Jedis conn=pool.getResource() ) { + final scanResult = conn.hscan(key, "0", new ScanParams().match(pattern).count(hscanCount)) + if( !scanResult ) + return + for(String entry : scanResult.result) { + final parts = entry.tokenize('=') + conn.hdel(key, parts[0]) + } + } + } } diff --git a/src/test/groovy/io/seqera/wave/service/counter/impl/LocalCounterProviderTest.groovy b/src/test/groovy/io/seqera/wave/service/counter/impl/LocalCounterProviderTest.groovy index 1787b61f5..54d6ec088 100644 --- a/src/test/groovy/io/seqera/wave/service/counter/impl/LocalCounterProviderTest.groovy +++ b/src/test/groovy/io/seqera/wave/service/counter/impl/LocalCounterProviderTest.groovy @@ -73,4 +73,26 @@ class LocalCounterProviderTest extends Specification { ['pulls/o/abc.com.au/d/2024-05-30':1] } + def 'should delete records with given pattern' () { + when: + localCounterProvider.inc('metrics/v1', 'builds/o/foo.com', 1) + localCounterProvider.inc('metrics/v1', 'builds/o/bar.io', 1) + localCounterProvider.inc('metrics/v1', 'builds/o/abc.org', 2) + localCounterProvider.inc('metrics/v1', 'pulls/o/foo.it', 1) + localCounterProvider.inc('metrics/v1', 'pulls/o/bar.es', 2) + localCounterProvider.inc('metrics/v1', 'pulls/o/abc.in', 3) + localCounterProvider.inc('metrics/v1', 'pulls/o/abc.com.au/d/2024-07-15', 1) + localCounterProvider.inc('metrics/v1', 'pulls/o/abc.com.au/d/2024-07-14', 1) + localCounterProvider.inc('metrics/v1', 'builds/o/abc.com.au/d/2024-07-14', 1) + localCounterProvider.inc('metrics/v1', 'builds/o/abc.com.au/d/2024-07-14', 1) + + then:'delete all pull counter keys' + localCounterProvider.deleteAllMatchingEntries('metrics/v1', 'pulls/o/*') + localCounterProvider.getAllMatchingEntries('metrics/v1', 'pulls/o/*') == [:] + localCounterProvider.getAllMatchingEntries('metrics/v1', 'pulls/o/*/d/2024-05-30') == [:] + and:'delete only build per specific date counter keys' + localCounterProvider.deleteAllMatchingEntries('metrics/v1', 'builds/o/abc.com.au/d/2024-07-14') + localCounterProvider.getAllMatchingEntries('metrics/v1', 'builds/o/*') == ['builds/o/foo.com':1, 'builds/o/bar.io':1, 'builds/o/abc.org':2] + } + } diff --git a/src/test/groovy/io/seqera/wave/service/counter/impl/RedisCounterProviderTest.groovy b/src/test/groovy/io/seqera/wave/service/counter/impl/RedisCounterProviderTest.groovy index d592171a9..5a7d56970 100644 --- a/src/test/groovy/io/seqera/wave/service/counter/impl/RedisCounterProviderTest.groovy +++ b/src/test/groovy/io/seqera/wave/service/counter/impl/RedisCounterProviderTest.groovy @@ -82,4 +82,26 @@ class RedisCounterProviderTest extends Specification implements RedisTestContain redisCounterProvider.getAllMatchingEntries('metrics/v1', 'pulls/o/*/d/2024-05-30') == ['pulls/o/abc.com.au/d/2024-05-30':1] } + + def 'should delete records with given pattern' () { + when: + redisCounterProvider.inc('metrics/v1', 'builds/o/foo.com', 1) + redisCounterProvider.inc('metrics/v1', 'builds/o/bar.io', 1) + redisCounterProvider.inc('metrics/v1', 'builds/o/abc.org', 2) + redisCounterProvider.inc('metrics/v1', 'pulls/o/foo.it', 1) + redisCounterProvider.inc('metrics/v1', 'pulls/o/bar.es', 2) + redisCounterProvider.inc('metrics/v1', 'pulls/o/abc.in', 3) + redisCounterProvider.inc('metrics/v1', 'pulls/o/abc.com.au/d/2024-07-15', 1) + redisCounterProvider.inc('metrics/v1', 'pulls/o/abc.com.au/d/2024-07-14', 1) + redisCounterProvider.inc('metrics/v1', 'builds/o/abc.com.au/d/2024-07-14', 1) + redisCounterProvider.inc('metrics/v1', 'builds/o/abc.com.au/d/2024-07-14', 1) + + then:'delete all pull counter keys' + redisCounterProvider.deleteAllMatchingEntries('metrics/v1', 'pulls/o/*') + redisCounterProvider.getAllMatchingEntries('metrics/v1', 'pulls/o/*') == [:] + redisCounterProvider.getAllMatchingEntries('metrics/v1', 'pulls/o/*/d/2024-05-30') == [:] + and:'delete only build per specific date counter keys' + redisCounterProvider.deleteAllMatchingEntries('metrics/v1', 'builds/o/abc.com.au/d/2024-07-14') + redisCounterProvider.getAllMatchingEntries('metrics/v1', 'builds/o/*') == ['builds/o/foo.com':1, 'builds/o/bar.io':1, 'builds/o/abc.org':2] + } }