Skip to content

Commit 2d36526

Browse files
committed
Merge remote-tracking branch 'origin/develop' into develop
2 parents 9243cc8 + b14db0e commit 2d36526

File tree

10 files changed

+185
-14
lines changed

10 files changed

+185
-14
lines changed

controller-api/src/main/kotlin/app/simplecloud/controller/api/ServerApi.kt

Lines changed: 62 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package app.simplecloud.controller.api
22

33
import app.simplecloud.controller.shared.group.Group
4-
import build.buf.gen.simplecloud.controller.v1.ServerType
54
import app.simplecloud.controller.shared.server.Server
65
import build.buf.gen.simplecloud.controller.v1.ServerStartCause
76
import build.buf.gen.simplecloud.controller.v1.ServerState
87
import build.buf.gen.simplecloud.controller.v1.ServerStopCause
8+
import build.buf.gen.simplecloud.controller.v1.ServerType
99
import java.util.concurrent.CompletableFuture
1010

1111
interface ServerApi {
@@ -52,21 +52,54 @@ interface ServerApi {
5252
* @param groupName the group name of the group the new server should be of.
5353
* @return a [CompletableFuture] with a [Server] or null.
5454
*/
55-
fun startServer(groupName: String, startCause: ServerStartCause = ServerStartCause.API_START): CompletableFuture<Server?>
55+
fun startServer(
56+
groupName: String,
57+
startCause: ServerStartCause = ServerStartCause.API_START
58+
): CompletableFuture<Server?>
5659

5760
/**
5861
* @param groupName the group name of the servers group.
5962
* @param numericalId the numerical id of the server.
6063
* @return a [CompletableFuture] with the stopped [Server].
6164
*/
62-
fun stopServer(groupName: String, numericalId: Long, stopCause: ServerStopCause = ServerStopCause.API_STOP): CompletableFuture<Server>
65+
fun stopServer(
66+
groupName: String,
67+
numericalId: Long,
68+
stopCause: ServerStopCause = ServerStopCause.API_STOP
69+
): CompletableFuture<Server>
6370

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

77+
/**
78+
* Stops all servers within a specified group.
79+
*
80+
* @param groupName The name of the server group to stop.
81+
* @param stopCause The reason for stopping the servers. Defaults to [ServerStopCause.API_STOP].
82+
* @return A [CompletableFuture] containing a list of stopped [Server] instances.
83+
*/
84+
fun stopServers(
85+
groupName: String,
86+
stopCause: ServerStopCause = ServerStopCause.API_STOP
87+
): CompletableFuture<List<Server>>
88+
89+
/**
90+
* Stops all servers within a specified group and sets a timeout to prevent new server starts for the group.
91+
*
92+
* @param groupName The name of the server group to stop.
93+
* @param timeoutSeconds The duration (in seconds) for which new server starts will be prevented.
94+
* @param stopCause The reason for stopping the servers. Defaults to [ServerStopCause.API_STOP].
95+
* @return A [CompletableFuture] containing a list of stopped [Server] instances.
96+
*/
97+
fun stopServers(
98+
groupName: String,
99+
timeoutSeconds: Int,
100+
stopCause: ServerStopCause = ServerStopCause.API_STOP
101+
): CompletableFuture<List<Server>>
102+
70103
/**
71104
* @param id the id of the server.
72105
* @param state the new state of the server.
@@ -145,6 +178,32 @@ interface ServerApi {
145178
*/
146179
suspend fun stopServer(id: String, stopCause: ServerStopCause = ServerStopCause.API_STOP): Server
147180

181+
/**
182+
* Stops all servers within a specified group.
183+
*
184+
* @param groupName The name of the server group to stop.
185+
* @param stopCause The reason for stopping the servers. Defaults to [ServerStopCause.API_STOP].
186+
* @return A list of stopped [Server] instances.
187+
*/
188+
suspend fun stopServers(
189+
groupName: String,
190+
stopCause: ServerStopCause = ServerStopCause.API_STOP
191+
): List<Server>
192+
193+
/**
194+
* Stops all servers within a specified group and sets a timeout to prevent new server starts for the group.
195+
*
196+
* @param groupName The name of the server group to stop.
197+
* @param timeoutSeconds The duration (in seconds) for which new server starts will be prevented.
198+
* @param stopCause The reason for stopping the servers. Defaults to [ServerStopCause.API_STOP].
199+
* @return A list of stopped [Server] instances.
200+
*/
201+
suspend fun stopServers(
202+
groupName: String,
203+
timeoutSeconds: Int,
204+
stopCause: ServerStopCause = ServerStopCause.API_STOP
205+
): List<Server>
206+
148207
/**
149208
* @param id the id of the server.
150209
* @param state the new state of the server.

controller-api/src/main/kotlin/app/simplecloud/controller/api/impl/coroutines/ServerApiCoroutineImpl.kt

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ package app.simplecloud.controller.api.impl.coroutines
22

33
import app.simplecloud.controller.api.ServerApi
44
import app.simplecloud.controller.shared.group.Group
5-
import build.buf.gen.simplecloud.controller.v1.*
65
import app.simplecloud.controller.shared.server.Server
76
import app.simplecloud.droplet.api.auth.AuthCallCredentials
7+
import build.buf.gen.simplecloud.controller.v1.*
88
import io.grpc.ManagedChannel
99

1010
class ServerApiCoroutineImpl(
@@ -13,7 +13,8 @@ class ServerApiCoroutineImpl(
1313
) : ServerApi.Coroutine {
1414

1515
private val serverServiceStub: ControllerServerServiceGrpcKt.ControllerServerServiceCoroutineStub =
16-
ControllerServerServiceGrpcKt.ControllerServerServiceCoroutineStub(managedChannel).withCallCredentials(authCallCredentials)
16+
ControllerServerServiceGrpcKt.ControllerServerServiceCoroutineStub(managedChannel)
17+
.withCallCredentials(authCallCredentials)
1718

1819
override suspend fun getAllServers(): List<Server> {
1920
return serverServiceStub.getAllServers(getAllServersRequest {}).serversList.map {
@@ -100,6 +101,25 @@ class ServerApiCoroutineImpl(
100101
)
101102
}
102103

104+
override suspend fun stopServers(groupName: String, stopCause: ServerStopCause): List<Server> {
105+
return serverServiceStub.stopServersByGroup(stopServersByGroupRequest {
106+
this.groupName = groupName
107+
this.stopCause = stopCause
108+
}).serversList.map {
109+
Server.fromDefinition(it)
110+
}
111+
}
112+
113+
override suspend fun stopServers(groupName: String, timeoutSeconds: Int, stopCause: ServerStopCause): List<Server> {
114+
return serverServiceStub.stopServersByGroupWithTimeout(stopServersByGroupWithTimeoutRequest {
115+
this.groupName = groupName
116+
this.stopCause = stopCause
117+
this.timeoutSeconds = timeoutSeconds
118+
}).serversList.map {
119+
Server.fromDefinition(it)
120+
}
121+
}
122+
103123
override suspend fun updateServerState(id: String, state: ServerState): Server {
104124
return Server.fromDefinition(
105125
serverServiceStub.updateServerState(

controller-api/src/main/kotlin/app/simplecloud/controller/api/impl/future/ServerApiFutureImpl.kt

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package app.simplecloud.controller.api.impl.future
22

33
import app.simplecloud.controller.api.ServerApi
44
import app.simplecloud.controller.shared.group.Group
5-
import build.buf.gen.simplecloud.controller.v1.*
65
import app.simplecloud.controller.shared.server.Server
76
import app.simplecloud.droplet.api.auth.AuthCallCredentials
87
import app.simplecloud.droplet.api.future.toCompletable
8+
import build.buf.gen.simplecloud.controller.v1.*
99
import io.grpc.ManagedChannel
1010
import java.util.concurrent.CompletableFuture
1111

@@ -79,7 +79,11 @@ class ServerApiFutureImpl(
7979
}
8080
}
8181

82-
override fun stopServer(groupName: String, numericalId: Long, stopCause: ServerStopCause): CompletableFuture<Server> {
82+
override fun stopServer(
83+
groupName: String,
84+
numericalId: Long,
85+
stopCause: ServerStopCause
86+
): CompletableFuture<Server> {
8387
return serverServiceStub.stopServerByNumerical(
8488
StopServerByNumericalRequest.newBuilder()
8589
.setGroupName(groupName)
@@ -102,6 +106,33 @@ class ServerApiFutureImpl(
102106
}
103107
}
104108

109+
override fun stopServers(groupName: String, stopCause: ServerStopCause): CompletableFuture<List<Server>> {
110+
return serverServiceStub.stopServersByGroup(
111+
StopServersByGroupRequest.newBuilder()
112+
.setGroupName(groupName)
113+
.setStopCause(stopCause)
114+
.build()
115+
).toCompletable().thenApply {
116+
Server.fromDefinition(it.serversList)
117+
}
118+
}
119+
120+
override fun stopServers(
121+
groupName: String,
122+
timeoutSeconds: Int,
123+
stopCause: ServerStopCause
124+
): CompletableFuture<List<Server>> {
125+
return serverServiceStub.stopServersByGroupWithTimeout(
126+
StopServersByGroupWithTimeoutRequest.newBuilder()
127+
.setGroupName(groupName)
128+
.setStopCause(stopCause)
129+
.setTimeoutSeconds(timeoutSeconds)
130+
.build()
131+
).toCompletable().thenApply {
132+
Server.fromDefinition(it.serversList)
133+
}
134+
}
135+
105136
override fun updateServerState(id: String, state: ServerState): CompletableFuture<Server> {
106137
return serverServiceStub.updateServerState(
107138
UpdateServerStateRequest.newBuilder()

controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/oauth/AuthenticationHandler.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ class AuthenticationHandler(
130130
call.respond(HttpStatusCode.NotFound, "User not found")
131131
return
132132
}
133-
call.respond(mapOf(
133+
call.respond(
134+
mapOf(
134135
"user_id" to user.userId,
135136
"username" to user.username,
136137
"scope" to user.scopes.joinToString(" "),

controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/reconciler/GroupReconciler.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,14 @@ class GroupReconciler(
9999

100100
private suspend fun startServers() {
101101
val available = serverHostRepository.areServerHostsAvailable()
102-
if(!available) return
103-
if(isNewServerNeeded())
102+
if (!available) return
103+
group.timeout?.let {
104+
if (it.isCooldownActive()) {
105+
return
106+
}
107+
}
108+
109+
if (isNewServerNeeded())
104110
startServer()
105111
}
106112

controller-runtime/src/main/kotlin/app/simplecloud/controller/runtime/server/ServerService.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import app.simplecloud.controller.runtime.MetricsEventNames
44
import app.simplecloud.controller.runtime.group.GroupRepository
55
import app.simplecloud.controller.runtime.host.ServerHostRepository
66
import app.simplecloud.controller.shared.group.Group
7+
import app.simplecloud.controller.shared.group.GroupTimeout
78
import app.simplecloud.controller.shared.host.ServerHost
89
import app.simplecloud.controller.shared.server.Server
910
import app.simplecloud.droplet.api.auth.AuthCallCredentials
@@ -310,6 +311,43 @@ class ServerService(
310311
}
311312
}
312313

314+
override suspend fun stopServersByGroupWithTimeout(request: StopServersByGroupWithTimeoutRequest): StopServersByGroupResponse {
315+
return stopServersByGroup(request.groupName, request.timeoutSeconds, request.stopCause)
316+
}
317+
318+
override suspend fun stopServersByGroup(request: StopServersByGroupRequest): StopServersByGroupResponse {
319+
return stopServersByGroup(request.groupName, null, request.stopCause)
320+
}
321+
322+
private suspend fun stopServersByGroup(
323+
groupName: String,
324+
timeout: Int?,
325+
cause: ServerStopCause = ServerStopCause.NATURAL_STOP
326+
): StopServersByGroupResponse {
327+
val group = groupRepository.find(groupName)
328+
?: throw StatusException(Status.NOT_FOUND.withDescription("No group was found matching this name. $groupName"))
329+
val groupServers = serverRepository.findServersByGroup(group.name)
330+
if (groupServers.isEmpty()) {
331+
throw StatusException(Status.NOT_FOUND.withDescription("No server was found matching this group name. ${group.name}"))
332+
}
333+
334+
val serverDefinitionList = mutableListOf<ServerDefinition>()
335+
336+
try {
337+
timeout?.let {
338+
group.timeout = GroupTimeout(it);
339+
}
340+
341+
groupServers.forEach { server ->
342+
serverDefinitionList.add(stopServer(server.toDefinition(), cause))
343+
}
344+
345+
return stopServersByGroupResponse { servers.addAll(serverDefinitionList) }
346+
} catch (e: Exception) {
347+
throw StatusException(Status.INTERNAL.withDescription("Error whilst stopping server by group").withCause(e))
348+
}
349+
}
350+
313351
private suspend fun stopServer(
314352
server: ServerDefinition,
315353
cause: ServerStopCause = ServerStopCause.NATURAL_STOP

controller-shared/src/main/kotlin/app/simplecloud/controller/shared/group/Group.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ data class Group(
1818
val properties: Map<String, String> = mutableMapOf()
1919
) {
2020

21+
@Transient
22+
var timeout: GroupTimeout? = null
23+
2124
fun toDefinition(): GroupDefinition {
2225
return GroupDefinition.newBuilder()
2326
.setName(name)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package app.simplecloud.controller.shared.group
2+
3+
data class GroupTimeout(val timeoutDuration: Int, val timeoutBegin: Long = System.currentTimeMillis()) {
4+
5+
fun isCooldownActive(): Boolean {
6+
val cooldownEndTime = timeoutBegin + timeoutDuration * 1000L
7+
return System.currentTimeMillis() < cooldownEndTime
8+
}
9+
10+
fun remainingTimeInSeconds(): Long {
11+
val cooldownEndTime = timeoutBegin + timeoutDuration * 1000L
12+
val remainingTime = cooldownEndTime - System.currentTimeMillis()
13+
return if (remainingTime > 0) remainingTime / 1000 else 0
14+
}
15+
16+
}

controller-shared/src/main/kotlin/app/simplecloud/controller/shared/server/Server.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ import app.simplecloud.droplet.api.time.ProtobufTimestamp
44
import build.buf.gen.simplecloud.controller.v1.ServerDefinition
55
import build.buf.gen.simplecloud.controller.v1.ServerState
66
import build.buf.gen.simplecloud.controller.v1.ServerType
7-
import java.time.Instant
87
import java.time.LocalDateTime
9-
import java.time.ZoneId
108

119
data class Server(
1210
val uniqueId: String,

gradle/libs.versions.toml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ kotlin = "2.0.20"
33
kotlin-coroutines = "1.9.0"
44
shadow = "8.3.3"
55
log4j = "2.20.0"
6-
droplet-api = "0.0.1-dev.7e049d6"
6+
droplet-api = "0.0.1-dev.cf07a34"
77
simplecloud-pubsub = "1.0.5"
88
simplecloud-metrics = "1.0.0"
99
jooq = "3.19.3"
@@ -24,7 +24,6 @@ log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "lo
2424
log4j-api = { module = "org.apache.logging.log4j:log4j-api", version.ref = "log4j" }
2525
log4j-slf4j = { module = "org.apache.logging.log4j:log4j-slf4j-impl", version.ref = "log4j" }
2626

27-
2827
simplecloud-droplet-api = { module = "app.simplecloud.droplet.api:droplet-api", version.ref = "droplet-api" }
2928
simplecloud-pubsub = { module = "app.simplecloud:simplecloud-pubsub", version.ref = "simplecloud-pubsub" }
3029
simplecloud-metrics = { module = "app.simplecloud:internal-metrics-api", version.ref = "simplecloud-metrics" }

0 commit comments

Comments
 (0)