Skip to content
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
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package app.simplecloud.controller.api

import app.simplecloud.controller.shared.group.Group
import build.buf.gen.simplecloud.controller.v1.ServerType
import app.simplecloud.controller.shared.server.Server
import build.buf.gen.simplecloud.controller.v1.ServerStartCause
import build.buf.gen.simplecloud.controller.v1.ServerState
import build.buf.gen.simplecloud.controller.v1.ServerStopCause
import build.buf.gen.simplecloud.controller.v1.ServerType
import java.util.concurrent.CompletableFuture

interface ServerApi {
Expand Down Expand Up @@ -52,21 +52,54 @@ interface ServerApi {
* @param groupName the group name of the group the new server should be of.
* @return a [CompletableFuture] with a [Server] or null.
*/
fun startServer(groupName: String, startCause: ServerStartCause = ServerStartCause.API_START): CompletableFuture<Server?>
fun startServer(
groupName: String,
startCause: ServerStartCause = ServerStartCause.API_START
): CompletableFuture<Server?>

/**
* @param groupName the group name of the servers group.
* @param numericalId the numerical id of the server.
* @return a [CompletableFuture] with the stopped [Server].
*/
fun stopServer(groupName: String, numericalId: Long, stopCause: ServerStopCause = ServerStopCause.API_STOP): CompletableFuture<Server>
fun stopServer(
groupName: String,
numericalId: Long,
stopCause: ServerStopCause = ServerStopCause.API_STOP
): CompletableFuture<Server>

/**
* @param id the id of the server.
* @return a [CompletableFuture] with the stopped [Server].
*/
fun stopServer(id: String, stopCause: ServerStopCause = ServerStopCause.API_STOP): CompletableFuture<Server>

/**
* Stops all servers within a specified group.
*
* @param groupName The name of the server group to stop.
* @param stopCause The reason for stopping the servers. Defaults to [ServerStopCause.API_STOP].
* @return A [CompletableFuture] containing a list of stopped [Server] instances.
*/
fun stopServers(
groupName: String,
stopCause: ServerStopCause = ServerStopCause.API_STOP
): CompletableFuture<List<Server>>

/**
* Stops all servers within a specified group and sets a timeout to prevent new server starts for the group.
*
* @param groupName The name of the server group to stop.
* @param timeoutSeconds The duration (in seconds) for which new server starts will be prevented.
* @param stopCause The reason for stopping the servers. Defaults to [ServerStopCause.API_STOP].
* @return A [CompletableFuture] containing a list of stopped [Server] instances.
*/
fun stopServers(
groupName: String,
timeoutSeconds: Int,
stopCause: ServerStopCause = ServerStopCause.API_STOP
): CompletableFuture<List<Server>>

/**
* @param id the id of the server.
* @param state the new state of the server.
Expand Down Expand Up @@ -145,6 +178,32 @@ interface ServerApi {
*/
suspend fun stopServer(id: String, stopCause: ServerStopCause = ServerStopCause.API_STOP): Server

/**
* Stops all servers within a specified group.
*
* @param groupName The name of the server group to stop.
* @param stopCause The reason for stopping the servers. Defaults to [ServerStopCause.API_STOP].
* @return A list of stopped [Server] instances.
*/
suspend fun stopServers(
groupName: String,
stopCause: ServerStopCause = ServerStopCause.API_STOP
): List<Server>

/**
* Stops all servers within a specified group and sets a timeout to prevent new server starts for the group.
*
* @param groupName The name of the server group to stop.
* @param timeoutSeconds The duration (in seconds) for which new server starts will be prevented.
* @param stopCause The reason for stopping the servers. Defaults to [ServerStopCause.API_STOP].
* @return A list of stopped [Server] instances.
*/
suspend fun stopServers(
groupName: String,
timeoutSeconds: Int,
stopCause: ServerStopCause = ServerStopCause.API_STOP
): List<Server>

/**
* @param id the id of the server.
* @param state the new state of the server.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package app.simplecloud.controller.api.impl.coroutines

import app.simplecloud.controller.api.ServerApi
import app.simplecloud.controller.shared.group.Group
import build.buf.gen.simplecloud.controller.v1.*
import app.simplecloud.controller.shared.server.Server
import app.simplecloud.droplet.api.auth.AuthCallCredentials
import build.buf.gen.simplecloud.controller.v1.*
import io.grpc.ManagedChannel

class ServerApiCoroutineImpl(
Expand All @@ -13,7 +13,8 @@ class ServerApiCoroutineImpl(
) : ServerApi.Coroutine {

private val serverServiceStub: ControllerServerServiceGrpcKt.ControllerServerServiceCoroutineStub =
ControllerServerServiceGrpcKt.ControllerServerServiceCoroutineStub(managedChannel).withCallCredentials(authCallCredentials)
ControllerServerServiceGrpcKt.ControllerServerServiceCoroutineStub(managedChannel)
.withCallCredentials(authCallCredentials)

override suspend fun getAllServers(): List<Server> {
return serverServiceStub.getAllServers(getAllServersRequest {}).serversList.map {
Expand Down Expand Up @@ -100,6 +101,25 @@ class ServerApiCoroutineImpl(
)
}

override suspend fun stopServers(groupName: String, stopCause: ServerStopCause): List<Server> {
return serverServiceStub.stopServersByGroup(stopServersByGroupRequest {
this.groupName = groupName
this.stopCause = stopCause
}).serversList.map {
Server.fromDefinition(it)
}
}

override suspend fun stopServers(groupName: String, timeoutSeconds: Int, stopCause: ServerStopCause): List<Server> {
return serverServiceStub.stopServersByGroupWithTimeout(stopServersByGroupWithTimeoutRequest {
this.groupName = groupName
this.stopCause = stopCause
this.timeoutSeconds = timeoutSeconds
}).serversList.map {
Server.fromDefinition(it)
}
}

override suspend fun updateServerState(id: String, state: ServerState): Server {
return Server.fromDefinition(
serverServiceStub.updateServerState(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ package app.simplecloud.controller.api.impl.future

import app.simplecloud.controller.api.ServerApi
import app.simplecloud.controller.shared.group.Group
import build.buf.gen.simplecloud.controller.v1.*
import app.simplecloud.controller.shared.server.Server
import app.simplecloud.droplet.api.auth.AuthCallCredentials
import app.simplecloud.droplet.api.future.toCompletable
import build.buf.gen.simplecloud.controller.v1.*
import io.grpc.ManagedChannel
import java.util.concurrent.CompletableFuture

Expand Down Expand Up @@ -79,7 +79,11 @@ class ServerApiFutureImpl(
}
}

override fun stopServer(groupName: String, numericalId: Long, stopCause: ServerStopCause): CompletableFuture<Server> {
override fun stopServer(
groupName: String,
numericalId: Long,
stopCause: ServerStopCause
): CompletableFuture<Server> {
return serverServiceStub.stopServerByNumerical(
StopServerByNumericalRequest.newBuilder()
.setGroupName(groupName)
Expand All @@ -102,6 +106,33 @@ class ServerApiFutureImpl(
}
}

override fun stopServers(groupName: String, stopCause: ServerStopCause): CompletableFuture<List<Server>> {
return serverServiceStub.stopServersByGroup(
StopServersByGroupRequest.newBuilder()
.setGroupName(groupName)
.setStopCause(stopCause)
.build()
).toCompletable().thenApply {
Server.fromDefinition(it.serversList)
}
}

override fun stopServers(
groupName: String,
timeoutSeconds: Int,
stopCause: ServerStopCause
): CompletableFuture<List<Server>> {
return serverServiceStub.stopServersByGroupWithTimeout(
StopServersByGroupWithTimeoutRequest.newBuilder()
.setGroupName(groupName)
.setStopCause(stopCause)
.setTimeoutSeconds(timeoutSeconds)
.build()
).toCompletable().thenApply {
Server.fromDefinition(it.serversList)
}
}

override fun updateServerState(id: String, state: ServerState): CompletableFuture<Server> {
return serverServiceStub.updateServerState(
UpdateServerStateRequest.newBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ class AuthenticationHandler(
call.respond(HttpStatusCode.NotFound, "User not found")
return
}
call.respond(mapOf(
call.respond(
mapOf(
"user_id" to user.userId,
"username" to user.username,
"scope" to user.scopes.joinToString(" "),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,14 @@ class GroupReconciler(

private suspend fun startServers() {
val available = serverHostRepository.areServerHostsAvailable()
if(!available) return
if(isNewServerNeeded())
if (!available) return
group.timeout?.let {
if (it.isCooldownActive()) {
return
}
}

if (isNewServerNeeded())
startServer()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package app.simplecloud.controller.runtime.server
import app.simplecloud.controller.runtime.group.GroupRepository
import app.simplecloud.controller.runtime.host.ServerHostRepository
import app.simplecloud.controller.shared.group.Group
import app.simplecloud.controller.shared.group.GroupTimeout
import app.simplecloud.controller.shared.host.ServerHost
import app.simplecloud.controller.shared.server.Server
import app.simplecloud.droplet.api.auth.AuthCallCredentials
Expand Down Expand Up @@ -198,6 +199,43 @@ class ServerService(
}
}

override suspend fun stopServersByGroupWithTimeout(request: StopServersByGroupWithTimeoutRequest): StopServersByGroupResponse {
return stopServersByGroup(request.groupName, request.timeoutSeconds, request.stopCause)
}

override suspend fun stopServersByGroup(request: StopServersByGroupRequest): StopServersByGroupResponse {
return stopServersByGroup(request.groupName, null, request.stopCause)
}

private suspend fun stopServersByGroup(
groupName: String,
timeout: Int?,
cause: ServerStopCause = ServerStopCause.NATURAL_STOP
): StopServersByGroupResponse {
val group = groupRepository.find(groupName)
?: throw StatusException(Status.NOT_FOUND.withDescription("No group was found matching this name. $groupName"))
val groupServers = serverRepository.findServersByGroup(group.name)
if (groupServers.isEmpty()) {
throw StatusException(Status.NOT_FOUND.withDescription("No server was found matching this group name. ${group.name}"))
}

val serverDefinitionList = mutableListOf<ServerDefinition>()

try {
timeout?.let {
group.timeout = GroupTimeout(it);
}

groupServers.forEach { server ->
serverDefinitionList.add(stopServer(server.toDefinition(), cause))
}

return stopServersByGroupResponse { servers.addAll(serverDefinitionList) }
} catch (e: Exception) {
throw StatusException(Status.INTERNAL.withDescription("Error whilst stopping server by group").withCause(e))
}
}

private suspend fun stopServer(
server: ServerDefinition,
cause: ServerStopCause = ServerStopCause.NATURAL_STOP
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ data class Group(
val properties: Map<String, String> = mutableMapOf()
) {

@Transient
var timeout: GroupTimeout? = null

fun toDefinition(): GroupDefinition {
return GroupDefinition.newBuilder()
.setName(name)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package app.simplecloud.controller.shared.group

data class GroupTimeout(val timeoutDuration: Int, val timeoutBegin: Long = System.currentTimeMillis()) {

fun isCooldownActive(): Boolean {
val cooldownEndTime = timeoutBegin + timeoutDuration * 1000L
return System.currentTimeMillis() < cooldownEndTime
}

fun remainingTimeInSeconds(): Long {
val cooldownEndTime = timeoutBegin + timeoutDuration * 1000L
val remainingTime = cooldownEndTime - System.currentTimeMillis()
return if (remainingTime > 0) remainingTime / 1000 else 0
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ import app.simplecloud.droplet.api.time.ProtobufTimestamp
import build.buf.gen.simplecloud.controller.v1.ServerDefinition
import build.buf.gen.simplecloud.controller.v1.ServerState
import build.buf.gen.simplecloud.controller.v1.ServerType
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId

data class Server(
val uniqueId: String,
Expand Down
3 changes: 1 addition & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ kotlin = "2.0.20"
kotlin-coroutines = "1.9.0"
shadow = "8.3.3"
log4j = "2.20.0"
droplet-api = "0.0.1-dev.7e049d6"
droplet-api = "0.0.1-dev.cf07a34"
simplecloud-pubsub = "1.0.5"
simplecloud-metrics = "1.0.0"
jooq = "3.19.3"
Expand All @@ -24,7 +24,6 @@ log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "lo
log4j-api = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j" }
log4j-slf4j = { module = "org.apache.logging.log4j:log4j-slf4j-impl", version.ref = "log4j" }


simplecloud-droplet-api = { module = "app.simplecloud.droplet.api:droplet-api", version.ref = "droplet-api" }
simplecloud-pubsub = { module = "app.simplecloud:simplecloud-pubsub", version.ref = "simplecloud-pubsub" }
simplecloud-metrics = { module = "app.simplecloud:internal-metrics-api", version.ref = "simplecloud-metrics" }
Expand Down