diff options
Diffstat (limited to 'opendc-serverless')
28 files changed, 0 insertions, 1947 deletions
diff --git a/opendc-serverless/build.gradle.kts b/opendc-serverless/build.gradle.kts deleted file mode 100644 index a458c809..00000000 --- a/opendc-serverless/build.gradle.kts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -description = "Serverless platform for OpenDC" diff --git a/opendc-serverless/opendc-serverless-api/build.gradle.kts b/opendc-serverless/opendc-serverless-api/build.gradle.kts deleted file mode 100644 index 0d9a8036..00000000 --- a/opendc-serverless/opendc-serverless-api/build.gradle.kts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -description = "Serverless API for OpenDC" - -/* Build configuration */ -plugins { - `kotlin-library-conventions` -} - -dependencies { - api(platform(projects.opendcPlatform)) -} diff --git a/opendc-serverless/opendc-serverless-api/src/main/kotlin/org/opendc/serverless/api/ServerlessClient.kt b/opendc-serverless/opendc-serverless-api/src/main/kotlin/org/opendc/serverless/api/ServerlessClient.kt deleted file mode 100644 index b66369ec..00000000 --- a/opendc-serverless/opendc-serverless-api/src/main/kotlin/org/opendc/serverless/api/ServerlessClient.kt +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.api - -import java.util.* - -/** - * Client interface to the OpenDC Serverless service. - */ -public interface ServerlessClient : AutoCloseable { - /** - * Obtain the list of [ServerlessFunction]s accessible by the requesting user. - */ - public suspend fun queryFunctions(): List<ServerlessFunction> - - /** - * Obtain a [ServerlessFunction] by its unique identifier. - * - * @param id The identifier of the flavor. - */ - public suspend fun findFunction(id: UUID): ServerlessFunction? - - /** - * Obtain a [ServerlessFunction] by its name. - * - * @param name The name of the function. - */ - public suspend fun findFunction(name: String): ServerlessFunction? - - /** - * Create a new serverless function. - * - * @param name The name of the function. - * @param memorySize The memory allocated for the function in MB. - * @param labels The labels associated with the function. - * @param meta The metadata associated with the function. - */ - public suspend fun newFunction( - name: String, - memorySize: Long, - labels: Map<String, String> = emptyMap(), - meta: Map<String, Any> = emptyMap() - ): ServerlessFunction - - /** - * Invoke the function with the specified [name]. - */ - public suspend fun invoke(name: String) - - /** - * Release the resources associated with this client, preventing any further API calls. - */ - public override fun close() -} diff --git a/opendc-serverless/opendc-serverless-api/src/main/kotlin/org/opendc/serverless/api/ServerlessFunction.kt b/opendc-serverless/opendc-serverless-api/src/main/kotlin/org/opendc/serverless/api/ServerlessFunction.kt deleted file mode 100644 index f1360966..00000000 --- a/opendc-serverless/opendc-serverless-api/src/main/kotlin/org/opendc/serverless/api/ServerlessFunction.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.api - -import java.util.UUID - -/** - * A serverless function instance. - */ -public interface ServerlessFunction { - /** - * The unique identifier of the function. - */ - public val uid: UUID - - /** - * The name of the function. - */ - public val name: String - - /** - * The amount of memory allocated for this function in MB. - */ - public val memorySize: Long - - /** - * The identifying labels attached to the resource. - */ - public val labels: Map<String, String> - - /** - * The non-identifying metadata attached to the resource. - */ - public val meta: Map<String, Any> - - /** - * Invoke the serverless function. - */ - public suspend operator fun invoke() - - /** - * Request the function to be deleted. - */ - public suspend fun delete() - - /** - * Refresh the local state of this object. - */ - public suspend fun refresh() -} diff --git a/opendc-serverless/opendc-serverless-service/build.gradle.kts b/opendc-serverless/opendc-serverless-service/build.gradle.kts deleted file mode 100644 index bce72c72..00000000 --- a/opendc-serverless/opendc-serverless-service/build.gradle.kts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -description = "Serverless service for OpenDC" - -/* Build configuration */ -plugins { - `kotlin-library-conventions` - `testing-conventions` - `jacoco-conventions` -} - -dependencies { - api(platform(projects.opendcPlatform)) - api(projects.opendcServerless.opendcServerlessApi) - api(projects.opendcTelemetry.opendcTelemetryApi) - implementation(projects.opendcUtils) - implementation(libs.kotlin.logging) - - testImplementation(projects.opendcSimulator.opendcSimulatorCore) - testRuntimeOnly(libs.log4j.slf4j) -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/FunctionObject.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/FunctionObject.kt deleted file mode 100644 index c12bbfe2..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/FunctionObject.kt +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service - -import io.opentelemetry.api.metrics.BoundLongCounter -import io.opentelemetry.api.metrics.BoundLongUpDownCounter -import io.opentelemetry.api.metrics.BoundLongValueRecorder -import io.opentelemetry.api.metrics.Meter -import io.opentelemetry.api.metrics.common.Labels -import org.opendc.serverless.service.deployer.FunctionInstance -import java.util.* - -/** - * An [FunctionObject] represents the service's view of a serverless function. - */ -public class FunctionObject( - meter: Meter, - public val uid: UUID, - name: String, - allocatedMemory: Long, - labels: Map<String, String>, - meta: Map<String, Any> -) : AutoCloseable { - /** - * The total amount of function invocations received by the function. - */ - public val invocations: BoundLongCounter = meter.longCounterBuilder("function.invocations.total") - .setDescription("Number of function invocations") - .setUnit("1") - .build() - .bind(Labels.of("function", uid.toString())) - - /** - * The amount of function invocations that could be handled directly. - */ - public val timelyInvocations: BoundLongCounter = meter.longCounterBuilder("function.invocations.warm") - .setDescription("Number of function invocations handled directly") - .setUnit("1") - .build() - .bind(Labels.of("function", uid.toString())) - - /** - * The amount of function invocations that were delayed due to function deployment. - */ - public val delayedInvocations: BoundLongCounter = meter.longCounterBuilder("function.invocations.cold") - .setDescription("Number of function invocations that are delayed") - .setUnit("1") - .build() - .bind(Labels.of("function", uid.toString())) - - /** - * The amount of function invocations that failed. - */ - public val failedInvocations: BoundLongCounter = meter.longCounterBuilder("function.invocations.failed") - .setDescription("Number of function invocations that failed") - .setUnit("1") - .build() - .bind(Labels.of("function", uid.toString())) - - /** - * The amount of instances for this function. - */ - public val activeInstances: BoundLongUpDownCounter = meter.longUpDownCounterBuilder("function.instances.active") - .setDescription("Number of active function instances") - .setUnit("1") - .build() - .bind(Labels.of("function", uid.toString())) - - /** - * The amount of idle instances for this function. - */ - public val idleInstances: BoundLongUpDownCounter = meter.longUpDownCounterBuilder("function.instances.idle") - .setDescription("Number of idle function instances") - .setUnit("1") - .build() - .bind(Labels.of("function", uid.toString())) - - /** - * The time that the function waited. - */ - public val waitTime: BoundLongValueRecorder = meter.longValueRecorderBuilder("function.time.wait") - .setDescription("Time the function has to wait before being started") - .setUnit("ms") - .build() - .bind(Labels.of("function", uid.toString())) - - /** - * The time that the function was running. - */ - public val activeTime: BoundLongValueRecorder = meter.longValueRecorderBuilder("function.time.active") - .setDescription("Time the function was running") - .setUnit("ms") - .build() - .bind(Labels.of("function", uid.toString())) - - /** - * The instances associated with this function. - */ - public val instances: MutableList<FunctionInstance> = mutableListOf() - - public var name: String = name - private set - - public var memorySize: Long = allocatedMemory - private set - - public val labels: MutableMap<String, String> = labels.toMutableMap() - - public val meta: MutableMap<String, Any> = meta.toMutableMap() - - override fun close() { - instances.forEach(FunctionInstance::close) - instances.clear() - } - - override fun equals(other: Any?): Boolean = other is FunctionObject && uid == other.uid - - override fun hashCode(): Int = uid.hashCode() -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/ServerlessService.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/ServerlessService.kt deleted file mode 100644 index e2f135ae..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/ServerlessService.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service - -import io.opentelemetry.api.metrics.Meter -import org.opendc.serverless.api.ServerlessClient -import org.opendc.serverless.service.autoscaler.FunctionTerminationPolicy -import org.opendc.serverless.service.deployer.FunctionDeployer -import org.opendc.serverless.service.internal.ServerlessServiceImpl -import org.opendc.serverless.service.router.RoutingPolicy -import java.time.Clock -import kotlin.coroutines.CoroutineContext - -/** - * The [ServerlessService] hosts the API implementation of the OpenDC Serverless service. - */ -public interface ServerlessService : AutoCloseable { - /** - * Create a new [ServerlessClient] to control the compute service. - */ - public fun newClient(): ServerlessClient - - /** - * Terminate the lifecycle of the serverless service, stopping all running function instances. - */ - public override fun close() - - public companion object { - /** - * Construct a new [ServerlessService] implementation. - * - * @param context The [CoroutineContext] to use in the service. - * @param clock The clock instance to use. - * @param meter The meter to report metrics to. - * @param deployer the [FunctionDeployer] to use for deploying function instances. - * @param routingPolicy The policy to route function invocations. - * @param terminationPolicy The policy for terminating function instances. - */ - public operator fun invoke( - context: CoroutineContext, - clock: Clock, - meter: Meter, - deployer: FunctionDeployer, - routingPolicy: RoutingPolicy, - terminationPolicy: FunctionTerminationPolicy, - ): ServerlessService { - return ServerlessServiceImpl(context, clock, meter, deployer, routingPolicy, terminationPolicy) - } - } -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicy.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicy.kt deleted file mode 100644 index 25df10a6..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicy.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.autoscaler - -import org.opendc.serverless.service.deployer.FunctionInstance -import org.opendc.serverless.service.deployer.FunctionInstanceListener - -/** - * A management policy that is responsible for downscaling the active function instances for a function. - */ -public interface FunctionTerminationPolicy : FunctionInstanceListener { - /** - * Enqueue the specified [instance] to be scheduled for termination a - */ - public fun enqueue(instance: FunctionInstance) -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicyFixed.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicyFixed.kt deleted file mode 100644 index 26b99f52..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicyFixed.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.autoscaler - -import org.opendc.serverless.service.deployer.FunctionInstance -import org.opendc.serverless.service.deployer.FunctionInstanceState -import org.opendc.utils.TimerScheduler -import java.time.Clock -import kotlin.coroutines.CoroutineContext - -/** - * A [FunctionTerminationPolicy] that terminates idle function instances after a fixed keep-alive time. - * - * @param timeout The idle timeout after which the function instance is terminated. - */ -public class FunctionTerminationPolicyFixed( - context: CoroutineContext, - clock: Clock, - public val timeout: Long -) : FunctionTerminationPolicy { - /** - * The [TimerScheduler] used to schedule the function terminations. - */ - private val scheduler = TimerScheduler<FunctionInstance>(context, clock) - - override fun enqueue(instance: FunctionInstance) { - // Cancel the existing timeout timer - scheduler.cancel(instance) - } - - override fun onStateChanged(instance: FunctionInstance, newState: FunctionInstanceState) { - when (newState) { - FunctionInstanceState.Active -> scheduler.cancel(instance) - FunctionInstanceState.Idle -> schedule(instance) - else -> {} - } - } - - /** - * Schedule termination for the specified [instance]. - */ - private fun schedule(instance: FunctionInstance) { - scheduler.startSingleTimer(instance, delay = timeout) { instance.close() } - } -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicyNull.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicyNull.kt deleted file mode 100644 index f2d8da59..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/autoscaler/FunctionTerminationPolicyNull.kt +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.autoscaler - -import org.opendc.serverless.service.deployer.FunctionInstance - -/** - * A [FunctionTerminationPolicy] that never terminates function instances. - */ -public class FunctionTerminationPolicyNull : FunctionTerminationPolicy { - override fun enqueue(instance: FunctionInstance) { - // No-op - } -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionDeployer.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionDeployer.kt deleted file mode 100644 index 5355b659..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionDeployer.kt +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.deployer - -import org.opendc.serverless.service.FunctionObject - -/** - * A [FunctionDeployer] is responsible for ensuring that an instance of an arbitrary function, a [FunctionInstance], - * is deployed. - * - * The function deployer should combines the configuration stored in the function registry, the parameters supplied by - * the requester, and other factors into a decision of how the function should be deployed, including how many and - * what kind of resources it should receive. - * - * Though it decides how the function instance should be deployed, the deployment of the function instance itself is - * delegated to the Resource Orchestration Layer. - */ -public interface FunctionDeployer { - /** - * Deploy the specified [function]. - */ - public fun deploy(function: FunctionObject, listener: FunctionInstanceListener): FunctionInstance -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstance.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstance.kt deleted file mode 100644 index d60648ea..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstance.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.deployer - -import org.opendc.serverless.service.FunctionObject - -/** - * A [FunctionInstance] is a a self-contained worker—typically a container—capable of handling function executions. - * - * Multiple, concurrent function instances can exists for a single function, for scalability purposes. - */ -public interface FunctionInstance : AutoCloseable { - /** - * The state of the instance. - */ - public val state: FunctionInstanceState - - /** - * The [FunctionObject] that is represented by this instance. - */ - public val function: FunctionObject - - /** - * Invoke the function instance. - * - * This method will suspend execution util the function instance has returned. - */ - public suspend fun invoke() - - /** - * Indicate to the resource manager that the instance is not needed anymore and may be cleaned up by the resource - * manager. - */ - public override fun close() -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstanceListener.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstanceListener.kt deleted file mode 100644 index 27803a63..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstanceListener.kt +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.deployer - -/** - * Listener interface for events originating from a [FunctionInstance]. - */ -public interface FunctionInstanceListener { - /** - * This method is invoked when the state of a [FunctionInstance] has changed. - */ - public fun onStateChanged(instance: FunctionInstance, newState: FunctionInstanceState) {} -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstanceState.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstanceState.kt deleted file mode 100644 index 4fc4a83f..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/deployer/FunctionInstanceState.kt +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.deployer - -/** - * This enumeration describes the states of a [FunctionInstance]. - */ -public enum class FunctionInstanceState { - /** - * The function instance is currently being provisioned. - */ - Provisioning, - - /** - * The function instance is idle and ready to execute. - */ - Idle, - - /** - * The function instance is executing. - */ - Active, - - /** - * The function instance is released and cannot be used anymore. - */ - Deleted -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/internal/ServerlessFunctionImpl.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/internal/ServerlessFunctionImpl.kt deleted file mode 100644 index 80b50e77..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/internal/ServerlessFunctionImpl.kt +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.internal - -import org.opendc.serverless.api.ServerlessFunction -import org.opendc.serverless.service.FunctionObject -import java.util.* - -/** - * A [ServerlessFunction] implementation that is passed to clients. - */ -internal class ServerlessFunctionImpl( - private val service: ServerlessServiceImpl, - private val state: FunctionObject -) : ServerlessFunction { - override val uid: UUID = state.uid - - override var name: String = state.name - private set - - override var memorySize: Long = state.memorySize - private set - - override var labels: Map<String, String> = state.labels.toMap() - private set - - override var meta: Map<String, Any> = state.meta.toMap() - private set - - override suspend fun delete() { - service.delete(state) - } - - override suspend fun invoke() { - service.invoke(state) - } - - override suspend fun refresh() { - name = state.name - memorySize = state.memorySize - labels = state.labels - meta = state.meta - } - - override fun equals(other: Any?): Boolean = other is ServerlessFunctionImpl && uid == other.uid - - override fun hashCode(): Int = uid.hashCode() - - override fun toString(): String = "ServerlessFunction[uid=$uid,name=$name]" -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/internal/ServerlessServiceImpl.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/internal/ServerlessServiceImpl.kt deleted file mode 100644 index 91a59279..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/internal/ServerlessServiceImpl.kt +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.internal - -import io.opentelemetry.api.metrics.Meter -import kotlinx.coroutines.* -import kotlinx.coroutines.intrinsics.startCoroutineCancellable -import mu.KotlinLogging -import org.opendc.serverless.api.ServerlessClient -import org.opendc.serverless.api.ServerlessFunction -import org.opendc.serverless.service.FunctionObject -import org.opendc.serverless.service.ServerlessService -import org.opendc.serverless.service.autoscaler.FunctionTerminationPolicy -import org.opendc.serverless.service.deployer.FunctionDeployer -import org.opendc.serverless.service.deployer.FunctionInstance -import org.opendc.serverless.service.deployer.FunctionInstanceListener -import org.opendc.serverless.service.deployer.FunctionInstanceState -import org.opendc.serverless.service.router.RoutingPolicy -import org.opendc.utils.TimerScheduler -import java.lang.IllegalStateException -import java.time.Clock -import java.util.* -import kotlin.coroutines.Continuation -import kotlin.coroutines.CoroutineContext -import kotlin.coroutines.resumeWithException - -/** - * Implementation of the [ServerlessService] interface. - * - * This component acts as the function router from the SPEC RG Reference Architecture for FaaS and is responsible - * for routing incoming requests or events to the correct [FunctionInstance]. If no [FunctionInstance] is available, - * this component queues the events to await the deployment of new instances. - */ -internal class ServerlessServiceImpl( - context: CoroutineContext, - private val clock: Clock, - private val meter: Meter, - private val deployer: FunctionDeployer, - private val routingPolicy: RoutingPolicy, - private val terminationPolicy: FunctionTerminationPolicy -) : ServerlessService, FunctionInstanceListener { - /** - * The [CoroutineScope] of the service bounded by the lifecycle of the service. - */ - private val scope = CoroutineScope(context + Job()) - - /** - * The logger instance of this server. - */ - private val logger = KotlinLogging.logger {} - - /** - * The [TimerScheduler] to use for scheduling the scheduler cycles. - */ - private val scheduler: TimerScheduler<Unit> = TimerScheduler(scope.coroutineContext, clock) - - /** - * The [Random] instance used to generate unique identifiers for the objects. - */ - private val random = Random(0) - - /** - * The registered functions for this service. - */ - private val functions = mutableMapOf<UUID, FunctionObject>() - private val functionsByName = mutableMapOf<String, FunctionObject>() - - /** - * The queue of invocation requests. - */ - private val queue = ArrayDeque<InvocationRequest>() - - /** - * The total amount of function invocations received by the service. - */ - private val _invocations = meter.longCounterBuilder("service.invocations.total") - .setDescription("Number of function invocations") - .setUnit("1") - .build() - - /** - * The amount of function invocations that could be handled directly. - */ - private val _timelyInvocations = meter.longCounterBuilder("service.invocations.warm") - .setDescription("Number of function invocations handled directly") - .setUnit("1") - .build() - - /** - * The amount of function invocations that were delayed due to function deployment. - */ - private val _delayedInvocations = meter.longCounterBuilder("service.invocations.cold") - .setDescription("Number of function invocations that are delayed") - .setUnit("1") - .build() - - override fun newClient(): ServerlessClient { - return object : ServerlessClient { - private var isClosed: Boolean = false - - /** - * Exposes a [FunctionObject] to a client-exposed [ServerlessFunction] instance. - */ - private fun FunctionObject.asClientFunction(): ServerlessFunction { - return ServerlessFunctionImpl(this@ServerlessServiceImpl, this) - } - - override suspend fun queryFunctions(): List<ServerlessFunction> { - check(!isClosed) { "Client is already closed" } - - return functions.values.map { it.asClientFunction() } - } - - override suspend fun findFunction(id: UUID): ServerlessFunction? { - check(!isClosed) { "Client is already closed" } - - return functions[id]?.asClientFunction() - } - - override suspend fun findFunction(name: String): ServerlessFunction? { - check(!isClosed) { "Client is already closed" } - - return functionsByName[name]?.asClientFunction() - } - - override suspend fun newFunction( - name: String, - memorySize: Long, - labels: Map<String, String>, - meta: Map<String, Any> - ): ServerlessFunction { - check(!isClosed) { "Client is already closed" } - require(name !in functionsByName) { "Function with same name exists" } - - val uid = UUID(clock.millis(), random.nextLong()) - val function = FunctionObject( - meter, - uid, - name, - memorySize, - labels, - meta - ) - - functionsByName[name] = function - functions[uid] = function - - return function.asClientFunction() - } - - override suspend fun invoke(name: String) { - check(!isClosed) { "Client is already closed" } - - val func = requireNotNull(functionsByName[name]) { "Unknown function" } - this@ServerlessServiceImpl.invoke(func) - } - - override fun close() { - isClosed = true - } - } - } - - /** - * Indicate that a new scheduling cycle is needed due to a change to the service's state. - */ - private fun schedule() { - // Bail out in case we have already requested a new cycle or the queue is empty. - if (scheduler.isTimerActive(Unit) || queue.isEmpty()) { - return - } - - val quantum = 100 - - // We assume that the provisioner runs at a fixed slot every time quantum (e.g t=0, t=60, t=120). - // This is important because the slices of the VMs need to be aligned. - // We calculate here the delay until the next scheduling slot. - val delay = quantum - (clock.millis() % quantum) - - scheduler.startSingleTimer(Unit, delay, ::doSchedule) - } - - /** - * Run a single scheduling iteration. - */ - @OptIn(InternalCoroutinesApi::class) - private fun doSchedule() { - try { - while (queue.isNotEmpty()) { - val (submitTime, function, cont) = queue.poll() - - val instances = function.instances - - // Check if there exists an instance of the function - val activeInstance = if (instances.isNotEmpty()) { - routingPolicy.select(instances, function) - } else { - null - } - - val instance = if (activeInstance != null) { - _timelyInvocations.add(1) - function.timelyInvocations.add(1) - - activeInstance - } else { - val instance = deployer.deploy(function, this) - instances.add(instance) - terminationPolicy.enqueue(instance) - - function.idleInstances.add(1) - - _delayedInvocations.add(1) - function.delayedInvocations.add(1) - - instance - } - - suspend { - val start = clock.millis() - function.waitTime.record(start - submitTime) - function.idleInstances.add(-1) - function.activeInstances.add(1) - try { - instance.invoke() - } catch (e: Throwable) { - logger.debug(e) { "Function invocation failed" } - function.failedInvocations.add(1) - } finally { - val end = clock.millis() - function.activeTime.record(end - start) - function.idleInstances.add(1) - function.activeInstances.add(-1) - } - }.startCoroutineCancellable(cont) - } - } catch (cause: Throwable) { - logger.error(cause) { "Exception occurred during scheduling cycle" } - } - } - - suspend fun invoke(function: FunctionObject) { - check(function.uid in functions) { "Function does not exist (anymore)" } - - _invocations.add(1) - function.invocations.add(1) - - return suspendCancellableCoroutine { cont -> - if (!queue.add(InvocationRequest(clock.millis(), function, cont))) { - cont.resumeWithException(IllegalStateException("Failed to enqueue request")) - } else { - schedule() - } - } - } - - fun delete(function: FunctionObject) { - functions.remove(function.uid) - functionsByName.remove(function.name) - } - - override fun close() { - scope.cancel() - - // Stop all function instances - for ((_, function) in functions) { - function.close() - } - } - - override fun onStateChanged(instance: FunctionInstance, newState: FunctionInstanceState) { - terminationPolicy.onStateChanged(instance, newState) - - if (newState == FunctionInstanceState.Deleted) { - val function = instance.function - function.instances.remove(instance) - } - } - - /** - * A request to invoke a function. - */ - private data class InvocationRequest(val timestamp: Long, val function: FunctionObject, val cont: Continuation<Unit>) -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/router/RandomRoutingPolicy.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/router/RandomRoutingPolicy.kt deleted file mode 100644 index 063fb80a..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/router/RandomRoutingPolicy.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.router - -import org.opendc.serverless.service.FunctionObject -import org.opendc.serverless.service.deployer.FunctionInstance -import kotlin.random.Random - -/** - * A [RoutingPolicy] that selects a random function instance. - */ -public class RandomRoutingPolicy(private val random: Random = Random(0)) : RoutingPolicy { - override fun select(instances: List<FunctionInstance>, function: FunctionObject): FunctionInstance { - return instances.random(random) - } -} diff --git a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/router/RoutingPolicy.kt b/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/router/RoutingPolicy.kt deleted file mode 100644 index d5d1166f..00000000 --- a/opendc-serverless/opendc-serverless-service/src/main/kotlin/org/opendc/serverless/service/router/RoutingPolicy.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service.router - -import org.opendc.serverless.service.FunctionObject -import org.opendc.serverless.service.deployer.FunctionInstance - -/** - * A [RoutingPolicy] decides to which [FunctionInstance] a function invocation should be routed. - */ -public interface RoutingPolicy { - /** - * Select the instance to which the request should be routed to. - */ - public fun select(instances: List<FunctionInstance>, function: FunctionObject): FunctionInstance? -} diff --git a/opendc-serverless/opendc-serverless-service/src/test/kotlin/org/opendc/serverless/service/ServerlessServiceTest.kt b/opendc-serverless/opendc-serverless-service/src/test/kotlin/org/opendc/serverless/service/ServerlessServiceTest.kt deleted file mode 100644 index 6b2e8223..00000000 --- a/opendc-serverless/opendc-serverless-service/src/test/kotlin/org/opendc/serverless/service/ServerlessServiceTest.kt +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.service - -import io.mockk.* -import io.opentelemetry.api.metrics.MeterProvider -import kotlinx.coroutines.ExperimentalCoroutinesApi -import org.junit.jupiter.api.Assertions.* -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertDoesNotThrow -import org.junit.jupiter.api.assertThrows -import org.opendc.serverless.api.ServerlessFunction -import org.opendc.serverless.service.deployer.FunctionDeployer -import org.opendc.serverless.service.deployer.FunctionInstance -import org.opendc.serverless.service.deployer.FunctionInstanceState -import org.opendc.simulator.core.runBlockingSimulation -import java.util.* - -/** - * Test suite for the [ServerlessService] implementation. - */ -@OptIn(ExperimentalCoroutinesApi::class) -internal class ServerlessServiceTest { - - @Test - fun testClientState() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = assertDoesNotThrow { service.newClient() } - assertDoesNotThrow { client.close() } - - assertThrows<IllegalStateException> { client.queryFunctions() } - assertThrows<IllegalStateException> { client.newFunction("test", 128) } - assertThrows<IllegalStateException> { client.invoke("test") } - assertThrows<IllegalStateException> { client.findFunction(UUID.randomUUID()) } - assertThrows<IllegalStateException> { client.findFunction("name") } - } - - @Test - fun testClientInvokeUnknown() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = service.newClient() - - assertThrows<IllegalArgumentException> { client.invoke("test") } - } - - @Test - fun testClientFunctionCreation() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = service.newClient() - - val function = client.newFunction("test", 128) - - assertEquals("test", function.name) - } - - @Test - fun testClientFunctionQuery() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = service.newClient() - - assertEquals(emptyList<ServerlessFunction>(), client.queryFunctions()) - - val function = client.newFunction("test", 128) - - assertEquals(listOf(function), client.queryFunctions()) - } - - @Test - fun testClientFunctionFindById() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = service.newClient() - - assertEquals(emptyList<ServerlessFunction>(), client.queryFunctions()) - - val function = client.newFunction("test", 128) - - assertNotNull(client.findFunction(function.uid)) - } - - @Test - fun testClientFunctionFindByName() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = service.newClient() - - assertEquals(emptyList<ServerlessFunction>(), client.queryFunctions()) - - val function = client.newFunction("test", 128) - - assertNotNull(client.findFunction(function.name)) - } - - @Test - fun testClientFunctionDuplicateName() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = service.newClient() - - client.newFunction("test", 128) - - assertThrows<IllegalArgumentException> { client.newFunction("test", 128) } - } - - @Test - fun testClientFunctionDelete() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = service.newClient() - val function = client.newFunction("test", 128) - assertNotNull(client.findFunction(function.uid)) - function.delete() - assertNull(client.findFunction(function.uid)) - - // Delete should be idempotent - function.delete() - } - - @Test - fun testClientFunctionCannotInvokeDeleted() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val service = ServerlessService(coroutineContext, clock, meter, mockk(), mockk(), mockk()) - - val client = service.newClient() - val function = client.newFunction("test", 128) - assertNotNull(client.findFunction(function.uid)) - function.delete() - - assertThrows<IllegalStateException> { function.invoke() } - } - - @Test - fun testClientFunctionInvoke() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val deployer = mockk<FunctionDeployer>() - val service = ServerlessService(coroutineContext, clock, meter, deployer, mockk(), mockk(relaxUnitFun = true)) - - every { deployer.deploy(any(), any()) } answers { - object : FunctionInstance { - override val state: FunctionInstanceState = FunctionInstanceState.Idle - override val function: FunctionObject = it.invocation.args[0] as FunctionObject - - override suspend fun invoke() {} - - override fun close() {} - } - } - - val client = service.newClient() - val function = client.newFunction("test", 128) - - function.invoke() - } -} diff --git a/opendc-serverless/opendc-serverless-simulator/build.gradle.kts b/opendc-serverless/opendc-serverless-simulator/build.gradle.kts deleted file mode 100644 index 5e2c522d..00000000 --- a/opendc-serverless/opendc-serverless-simulator/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -description = "Simulator for OpenDC Serverles" - -/* Build configuration */ -plugins { - `kotlin-library-conventions` - `testing-conventions` - `jacoco-conventions` -} - -dependencies { - api(platform(projects.opendcPlatform)) - api(projects.opendcServerless.opendcServerlessService) - api(projects.opendcSimulator.opendcSimulatorCompute) - - testImplementation(projects.opendcSimulator.opendcSimulatorCore) - testRuntimeOnly(libs.slf4j.simple) -} diff --git a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/SimFunctionDeployer.kt b/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/SimFunctionDeployer.kt deleted file mode 100644 index 32e5f75e..00000000 --- a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/SimFunctionDeployer.kt +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.simulator - -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.Channel -import org.opendc.serverless.service.FunctionObject -import org.opendc.serverless.service.deployer.FunctionDeployer -import org.opendc.serverless.service.deployer.FunctionInstance -import org.opendc.serverless.service.deployer.FunctionInstanceListener -import org.opendc.serverless.service.deployer.FunctionInstanceState -import org.opendc.serverless.simulator.delay.DelayInjector -import org.opendc.serverless.simulator.workload.SimServerlessWorkloadMapper -import org.opendc.simulator.compute.SimBareMetalMachine -import org.opendc.simulator.compute.SimMachine -import org.opendc.simulator.compute.SimMachineModel -import org.opendc.simulator.compute.power.ConstantPowerModel -import org.opendc.simulator.compute.power.SimplePowerDriver -import org.opendc.simulator.resources.SimResourceInterpreter -import java.time.Clock -import java.util.ArrayDeque -import kotlin.coroutines.Continuation -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException - -/** - * A [FunctionDeployer] that uses that simulates the [FunctionInstance]s. - */ -public class SimFunctionDeployer( - private val clock: Clock, - private val scope: CoroutineScope, - private val model: SimMachineModel, - private val delayInjector: DelayInjector, - private val mapper: SimServerlessWorkloadMapper -) : FunctionDeployer { - - override fun deploy(function: FunctionObject, listener: FunctionInstanceListener): Instance { - val instance = Instance(function, listener) - instance.start() - return instance - } - - /** - * A simulated [FunctionInstance]. - */ - public inner class Instance(override val function: FunctionObject, private val listener: FunctionInstanceListener) : FunctionInstance { - /** - * The workload associated with this instance. - */ - private val workload = mapper.createWorkload(function) - - /** - * The machine that will execute the workloads. - */ - public val machine: SimMachine = SimBareMetalMachine( - SimResourceInterpreter(scope.coroutineContext, clock), - model, - SimplePowerDriver(ConstantPowerModel(0.0)) - ) - - /** - * The job associated with the lifecycle of the instance. - */ - private var job: Job? = null - - /** - * The invocation request queue. - */ - private val queue = ArrayDeque<InvocationRequest>() - - /** - * A channel used to signal that new invocations have been enqueued. - */ - private val chan = Channel<Unit>(Channel.RENDEZVOUS) - - override var state: FunctionInstanceState = FunctionInstanceState.Provisioning - set(value) { - if (field != value) { - listener.onStateChanged(this, value) - } - - field = value - } - - override suspend fun invoke() { - check(state != FunctionInstanceState.Deleted) { "Function instance has been released" } - return suspendCancellableCoroutine { cont -> - queue.add(InvocationRequest(cont)) - chan.trySend(Unit) - } - } - - override fun close() { - state = FunctionInstanceState.Deleted - stop() - machine.close() - } - - override fun toString(): String = "FunctionInstance[state=$state]" - - /** - * Start the function instance. - */ - @OptIn(InternalCoroutinesApi::class) - internal fun start() { - check(state == FunctionInstanceState.Provisioning) { "Invalid state of function instance" } - job = scope.launch { - delay(delayInjector.getColdStartDelay(this@Instance)) - - launch { - try { - machine.run(workload) - } finally { - state = FunctionInstanceState.Deleted - } - } - - while (isActive) { - if (queue.isEmpty()) { - chan.receive() - } - - state = FunctionInstanceState.Active - while (queue.isNotEmpty()) { - val request = queue.poll() - try { - workload.invoke() - request.cont.resume(Unit) - } catch (cause: CancellationException) { - request.cont.resumeWithException(cause) - throw cause - } catch (cause: Throwable) { - request.cont.resumeWithException(cause) - } - } - state = FunctionInstanceState.Idle - } - } - } - - /** - * Stop the function instance. - */ - private fun stop() { - val job = job - - if (job != null) { - this.job = null - job.cancel() - } - } - } - - /** - * A function invocation request. - */ - private data class InvocationRequest(val cont: Continuation<Unit>) -} diff --git a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/ColdStartModel.kt b/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/ColdStartModel.kt deleted file mode 100644 index f9f3718e..00000000 --- a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/ColdStartModel.kt +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.simulator.delay - -/** - * Model parameters for the cold start times of serverless services. - */ -public enum class ColdStartModel { - // Min and max memory values from [Peeking Behind The Curtains of Serverless Platforms][2018], - // other values deduced from linear curve. - LAMBDA { - override fun coldStartParam(provisionedMemory: Int): Pair<Double, Double> { - return when (provisionedMemory) { - 128 -> Pair(265.21, 354.43) - 256 -> Pair(261.46, 334.23) - 512 -> Pair(257.71, 314.03) - 1024 -> Pair(253.96, 293.83) - 1536 -> Pair(250.07, 273.63) - 2048 -> Pair(246.11, 253.43) - else -> Pair(0.0, 1.0) - } - } - }, - AZURE { - // Azure by default uses 1.5gb memory to instantiate functions - override fun coldStartParam(provisionedMemory: Int): Pair<Double, Double> { - return Pair(242.66, 340.67) - } - }, - - GOOGLE { - override fun coldStartParam(provisionedMemory: Int): Pair<Double, Double> { - return when (provisionedMemory) { - 128 -> Pair(493.04, 345.8) - 256 -> Pair(416.59, 301.5) - 512 -> Pair(340.14, 257.2) - 1024 -> Pair(263.69, 212.9) - 1536 -> Pair(187.24, 168.6) - 2048 -> Pair(110.77, 124.3) - else -> Pair(0.0, 1.0) - } - } - }; - - /** - * Obtain the stochastic parameters for the cold start models. - */ - public abstract fun coldStartParam(provisionedMemory: Int): Pair<Double, Double> -} diff --git a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/DelayInjector.kt b/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/DelayInjector.kt deleted file mode 100644 index f882031b..00000000 --- a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/DelayInjector.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.simulator.delay - -import org.opendc.serverless.service.deployer.FunctionInstance - -/** - * An interface for modeling the delay caused by function cold starts. - */ -public interface DelayInjector { - /** - * Returns the cold start delay duration sampled from a normal distribution, the distribution is - * initialized using custom mean and standard deviation based on provisioned memory, language and - * failure model - */ - public fun getColdStartDelay(instance: FunctionInstance): Long -} diff --git a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/StochasticDelayInjector.kt b/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/StochasticDelayInjector.kt deleted file mode 100644 index 154378e1..00000000 --- a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/StochasticDelayInjector.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.simulator.delay - -import org.opendc.serverless.service.deployer.FunctionInstance -import java.util.* -import kotlin.math.abs - -/* - * Interface for instance deployment delay estimation. - */ -public class StochasticDelayInjector(private val model: ColdStartModel, private val random: Random) : DelayInjector { - override fun getColdStartDelay(instance: FunctionInstance): Long { - val (mean, sd) = model.coldStartParam(instance.function.memorySize.toInt()) - return abs(random.nextGaussian() * sd + mean).toLong() - } -} diff --git a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/ZeroDelayInjector.kt b/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/ZeroDelayInjector.kt deleted file mode 100644 index 0895ee18..00000000 --- a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/delay/ZeroDelayInjector.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.simulator.delay - -import org.opendc.serverless.service.deployer.FunctionInstance - -public object ZeroDelayInjector : DelayInjector { - override fun getColdStartDelay(instance: FunctionInstance): Long = 0 -} diff --git a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/workload/SimServerlessWorkload.kt b/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/workload/SimServerlessWorkload.kt deleted file mode 100644 index 121bf915..00000000 --- a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/workload/SimServerlessWorkload.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.simulator.workload - -import org.opendc.simulator.compute.workload.SimWorkload - -/** - * A model for a serverless workload, which may be invoked multiple times. - */ -public interface SimServerlessWorkload : SimWorkload { - /** - * This method is invoked when an active function instance is invoked. - */ - public suspend fun invoke() -} diff --git a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/workload/SimServerlessWorkloadMapper.kt b/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/workload/SimServerlessWorkloadMapper.kt deleted file mode 100644 index 3a47eb53..00000000 --- a/opendc-serverless/opendc-serverless-simulator/src/main/kotlin/org/opendc/serverless/simulator/workload/SimServerlessWorkloadMapper.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.simulator.workload - -import org.opendc.serverless.api.ServerlessFunction -import org.opendc.serverless.service.FunctionObject - -/** - * A [SimServerlessWorkloadMapper] is responsible for mapping a [ServerlessFunction] to a [SimServerlessWorkload] that - * can be simulated. - */ -public fun interface SimServerlessWorkloadMapper { - /** - * Map the specified [function] to a [SimServerlessWorkload] that can be simulated. - */ - public fun createWorkload(function: FunctionObject): SimServerlessWorkload -} diff --git a/opendc-serverless/opendc-serverless-simulator/src/test/kotlin/org/opendc/serverless/simulator/SimServerlessServiceTest.kt b/opendc-serverless/opendc-serverless-simulator/src/test/kotlin/org/opendc/serverless/simulator/SimServerlessServiceTest.kt deleted file mode 100644 index 6afa1b65..00000000 --- a/opendc-serverless/opendc-serverless-simulator/src/test/kotlin/org/opendc/serverless/simulator/SimServerlessServiceTest.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2021 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.serverless.simulator - -import io.mockk.coVerify -import io.mockk.spyk -import io.opentelemetry.api.metrics.MeterProvider -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.delay -import kotlinx.coroutines.yield -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertAll -import org.opendc.serverless.service.ServerlessService -import org.opendc.serverless.service.autoscaler.FunctionTerminationPolicyFixed -import org.opendc.serverless.service.router.RandomRoutingPolicy -import org.opendc.serverless.simulator.delay.ZeroDelayInjector -import org.opendc.serverless.simulator.workload.SimServerlessWorkload -import org.opendc.simulator.compute.SimMachineModel -import org.opendc.simulator.compute.model.MemoryUnit -import org.opendc.simulator.compute.model.ProcessingNode -import org.opendc.simulator.compute.model.ProcessingUnit -import org.opendc.simulator.compute.workload.SimFlopsWorkload -import org.opendc.simulator.compute.workload.SimWorkload -import org.opendc.simulator.core.runBlockingSimulation - -/** - * A test suite for the [ServerlessService] implementation under simulated conditions. - */ -@OptIn(ExperimentalCoroutinesApi::class) -internal class SimServerlessServiceTest { - - private lateinit var machineModel: SimMachineModel - - @BeforeEach - fun setUp() { - val cpuNode = ProcessingNode("Intel", "Xeon", "amd64", 2) - - machineModel = SimMachineModel( - cpus = List(cpuNode.coreCount) { ProcessingUnit(cpuNode, it, 1000.0) }, - memory = List(4) { MemoryUnit("Crucial", "MTA18ASF4G72AZ-3G2B1", 3200.0, 32_000) } - ) - } - - @Test - fun testSmoke() = runBlockingSimulation { - val meter = MeterProvider.noop().get("opendc-serverless") - val workload = spyk(object : SimServerlessWorkload, SimWorkload by SimFlopsWorkload(1000) { - override suspend fun invoke() {} - }) - val deployer = SimFunctionDeployer(clock, this, machineModel, ZeroDelayInjector) { workload } - val service = ServerlessService( - coroutineContext, clock, meter, deployer, RandomRoutingPolicy(), - FunctionTerminationPolicyFixed(coroutineContext, clock, timeout = 10000) - ) - - val client = service.newClient() - - val function = client.newFunction("test", 128) - function.invoke() - delay(2000) - - service.close() - - yield() - - assertAll( - { coVerify { workload.invoke() } }, - ) - } -} |
