Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trust Mark Validation #56

Merged
merged 3 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fun getNpmVersion(): String {

allprojects {
group = "com.sphereon.oid.fed"
version = "0.4.8-SNAPSHOT"
version = "0.5.1-SNAPSHOT"
val npmVersion by extra { getNpmVersion() }

// Common repository configuration for all projects
Expand Down
7 changes: 2 additions & 5 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
kotlin.code.style=official

#Gradle
org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"

#Android
android.nonTransitiveRClass=true
android.useAndroidX=true

#Ktor
io.ktor.development=true

#MPP
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.mpp.enableCInteropCommonization=true
kotlin.mpp.enableCInteropCommonization=true
ktor_version=3.0.3
84 changes: 84 additions & 0 deletions modules/cache/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig

plugins {
alias(libs.plugins.kotlinMultiplatform)
kotlin("plugin.serialization") version libs.versions.kotlin.get()
}

group = "com.sphereon.oid.fed"

repositories {
mavenCentral()
mavenLocal()
google()
maven("https://jitpack.io")
}

kotlin {
jvm()

js(IR) {
browser {
commonWebpackConfig {
devServer = KotlinWebpackConfig.DevServer().apply {
port = 8083
}
}
}
nodejs {
testTask {
useMocha {
timeout = "5000"
}
}
}
binaries.library()
generateTypeScriptDefinitions()
compilations["main"].packageJson {
name = "@sphereon/openid-federation-cache"
version = rootProject.extra["npmVersion"] as String
description = "OpenID Federation Cache Module"
customField("description", "OpenID Federation Cache Module")
customField("license", "Apache-2.0")
customField("author", "Sphereon International")
customField(
"repository", mapOf(
"type" to "git",
"url" to "https://github.com/Sphereon-Opensource/openid-federation"
)
)

customField(
"publishConfig", mapOf(
"access" to "public"
)
)

types = "./index.d.ts"
}
}

sourceSets {
val commonMain by getting {
dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation("com.mayakapps.kache:kache:2.1.0")
implementation("com.mayakapps.kache:file-kache:2.1.0")
}
}

val commonTest by getting {
dependencies {
implementation(kotlin("test"))
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.0")
implementation("org.jetbrains.kotlin:kotlin-stdlib:2.0.0")
}
}
}
}

tasks.named<Test>("jvmTest") {
useJUnitPlatform()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.sphereon.oid.fed.cache

import kotlinx.coroutines.Deferred

interface Cache<K, V> {
suspend fun clear()
suspend fun close()

suspend fun evictAll()
suspend fun evictExpired()
suspend fun trimToSize(size: Long)

suspend fun get(key: K, options: CacheOptions = CacheOptions()): V?
suspend fun getAllKeys(options: CacheOptions = CacheOptions()): Set<K>
fun getIfAvailable(key: K, options: CacheOptions = CacheOptions()): V?
fun getIfAvailableOrDefault(key: K, defaultValue: V, options: CacheOptions = CacheOptions()): V
suspend fun getKeys(options: CacheOptions = CacheOptions()): Set<K>
suspend fun getOrDefault(key: K, defaultValue: V, options: CacheOptions = CacheOptions()): V
suspend fun getOrPut(
key: K,
creationFunction: suspend (key: K) -> V?,
options: CacheOptions = CacheOptions()
): V?

suspend fun getUnderCreationKeys(options: CacheOptions = CacheOptions()): Set<K>

suspend fun put(key: K, value: V): V?
suspend fun put(
key: K,
creationFunction: suspend (key: K) -> V?
): V?

suspend fun putAll(from: Map<out K, V>)
suspend fun putAsync(
key: K,
creationFunction: suspend (key: K) -> V?
): Deferred<V?>

suspend fun remove(key: K): V?
suspend fun removeAllUnderCreation()

suspend fun resize(maxSize: Long)
suspend fun getCurrentSize(options: CacheOptions = CacheOptions()): Long
suspend fun getMaxSize(options: CacheOptions = CacheOptions()): Long
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.sphereon.oid.fed.cache

import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds

data class CacheConfig(
val maxSize: Long = 1000,
val expireAfterWrite: Duration = 1800.seconds,
val expireAfterAccess: Duration? = null,
val persistentCacheEnabled: Boolean = false,
val persistentCachePath: String? = null,
val evictOnClose: Boolean = false,
val cleanupOnStart: Boolean = true,
val compressionEnabled: Boolean = false,
val compressionThresholdBytes: Long = 1024L
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.sphereon.oid.fed.cache

enum class CacheStrategy {
CACHE_FIRST,
CACHE_ONLY,
FORCE_REMOTE
}

data class CacheOptions(
val strategy: CacheStrategy = CacheStrategy.CACHE_FIRST
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.sphereon.oid.fed.cache

import com.mayakapps.kache.InMemoryKache
import com.mayakapps.kache.KacheStrategy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlin.time.Duration

class InMemoryCache<K : Any, V : Any>(
private val maxSize: Long = 1000,
private val expireAfterWrite: Duration? = null,
private val expireAfterAccess: Duration? = null,
private val strategy: KacheStrategy = KacheStrategy.LRU,
private val scope: CoroutineScope = CoroutineScope(Dispatchers.Default)
) : Cache<K, V> {

private val cache: InMemoryKache<K, V> = InMemoryKache(maxSize) {
creationScope = scope
strategy = this@InMemoryCache.strategy
expireAfterWrite?.let { expireAfterWriteDuration = it }
expireAfterAccess?.let { expireAfterAccessDuration = it }
maxSize = this@InMemoryCache.maxSize
}

override suspend fun clear() {
cache.clear()
}

override suspend fun close() {
// InMemoryKache doesn't require explicit closing
}

override suspend fun evictAll() {
cache.evictAll()
}

override suspend fun evictExpired() {
cache.evictExpired()
}

override suspend fun trimToSize(size: Long) {
cache.trimToSize(size)
}

override suspend fun get(key: K, options: CacheOptions): V? {
// Check cache first unless FORCE_REMOTE
if (options.strategy != CacheStrategy.FORCE_REMOTE) {
val cachedValue = cache.get(key)
if (cachedValue != null) {
return cachedValue
}

// If cache-only, return null
if (options.strategy == CacheStrategy.CACHE_ONLY) {
return null
}
}

// At this point we either have FORCE_REMOTE or CACHE_FIRST with no valid cache entry
return null // The actual value should be created using getOrPut with a creationFunction
}

override suspend fun getAllKeys(options: CacheOptions): Set<K> {
val kacheKeys = cache.getAllKeys()
return (kacheKeys.keys + kacheKeys.underCreationKeys).toSet()
}

override fun getIfAvailable(key: K, options: CacheOptions): V? {
return cache.getIfAvailable(key)
}

override fun getIfAvailableOrDefault(key: K, defaultValue: V, options: CacheOptions): V {
return getIfAvailable(key, options) ?: defaultValue
}

override suspend fun getKeys(options: CacheOptions): Set<K> {
return cache.getKeys().toSet()
}

override suspend fun getOrDefault(key: K, defaultValue: V, options: CacheOptions): V {
return get(key, options) ?: defaultValue
}

override suspend fun getOrPut(
key: K,
creationFunction: suspend (key: K) -> V?,
options: CacheOptions
): V? {
return cache.getOrPut(key, creationFunction)
}

override suspend fun getUnderCreationKeys(options: CacheOptions): Set<K> {
return cache.getUnderCreationKeys()
}

override suspend fun put(key: K, value: V): V? {
return cache.put(key, value)
}

override suspend fun put(
key: K,
creationFunction: suspend (key: K) -> V?
): V? {
return cache.put(key, creationFunction)
}

override suspend fun putAll(from: Map<out K, V>) {
cache.putAll(from)
}

override suspend fun putAsync(
key: K,
creationFunction: suspend (key: K) -> V?
): Deferred<V?> {
return cache.putAsync(key, creationFunction)
}

override suspend fun remove(key: K): V? {
return cache.remove(key)
}

override suspend fun removeAllUnderCreation() {
cache.getUnderCreationKeys().forEach { cache.remove(it) }
}

override suspend fun resize(maxSize: Long) {
trimToSize(maxSize)
}

override suspend fun getCurrentSize(options: CacheOptions): Long {
return cache.getKeys().size.toLong()
}

override suspend fun getMaxSize(options: CacheOptions): Long {
return cache.maxSize
}
}
Loading