Skip to content

Commit

Permalink
Refactor DownloadManager and UpdateManager
Browse files Browse the repository at this point in the history
Move corresponding authorization requests to Download and Update manager
To handle them in their own actor
Check if the artifacts are already downloaded before asking for
authorization or even starting the download again

Signed-off-by: Saeed Rezaee <saeed.rezaee@kynetics.it>
  • Loading branch information
SaeedRe committed Dec 13, 2023
1 parent 5463049 commit f9add5e
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 214 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,143 +19,37 @@ import org.eclipse.hara.ddiclient.api.actors.ActionManager.Companion.Message.Upd
import org.eclipse.hara.ddiclient.api.actors.ConnectionManager.Companion.Message.Out.DeploymentCancelInfo
import org.eclipse.hara.ddiclient.api.actors.ConnectionManager.Companion.Message.Out.DeploymentInfo
import org.eclipse.hara.ddiclient.api.MessageListener
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.ObsoleteCoroutinesApi
import kotlinx.coroutines.launch
import org.eclipse.hara.ddiclient.api.DeploymentPermitProvider

@OptIn(ObsoleteCoroutinesApi::class, kotlinx.coroutines.ExperimentalCoroutinesApi::class)
class DeploymentManager
private constructor(scope: ActorScope) : AbstractActor(scope) {

private val registry = coroutineContext[HaraClientContext]!!.registry
private val softRequest: DeploymentPermitProvider = coroutineContext[HaraClientContext]!!.softDeploymentPermitProvider
private val forceRequest: DeploymentPermitProvider = coroutineContext[HaraClientContext]!!.forceDeploymentPermitProvider
private val connectionManager = coroutineContext[CMActor]!!.ref
private val notificationManager = coroutineContext[NMActor]!!.ref
private var waitingAuthJob: Job? = null
private fun beginningReceive(state: State): Receive = { msg ->
when {

msg is DeploymentInfo && msg.downloadIs(ProvisioningType.forced) -> {
forceDownloadTheArtifact(state, msg, forceRequest)
}

msg is DeploymentInfo && msg.downloadIs(ProvisioningType.attempt) -> {
attemptDownloadingTheArtifact(state, msg, softRequest)
}

msg is DeploymentInfo && msg.downloadIs(ProvisioningType.skip) -> {
// todo implement download skip option
LOG.warn("skip download not yet implemented (used attempt)")
attemptDownloadingTheArtifact(state, msg, softRequest)
}

msg is DeploymentCancelInfo -> {
stopUpdateAndNotify(msg)
}

else -> unhandled(msg)
}
}

private suspend fun forceDownloadTheArtifact(state: State,
msg: DeploymentInfo,
deploymentPermitProvider: DeploymentPermitProvider) {
val message = "Start downloading artifacts"
LOG.info(message)
sendFeedback(message)
val result = deploymentPermitProvider.downloadAllowed().await()
if (result) {
become(downloadingReceive(state.copy(deplBaseResp = msg.info)))
child("downloadManager")!!.send(msg)
} else {
LOG.info("Authorization denied for download files")
}
}

private suspend fun attemptDownloadingTheArtifact(state: State,
msg: DeploymentInfo,
deploymentPermitProvider: DeploymentPermitProvider) {
val message = "Waiting authorization to download"
LOG.info(message)
sendFeedback(message)
become(waitingDownloadAuthorization(state.copy(deplBaseResp = msg.info)))
notificationManager.send(MessageListener.Message.State
.WaitingDownloadAuthorization(false))
waitingAuthJob?.cancel()
waitingAuthJob = launch {
val result = deploymentPermitProvider.downloadAllowed().await()
if (result) {
channel.send(Message.DownloadGranted)
} else {
LOG.info("Authorization denied for download files")
}
waitingAuthJob = null
}
}

private fun waitingDownloadAuthorization(state: State): Receive = { msg ->
when (msg) {
when(msg) {
is DeploymentInfo -> {
when {

msg.downloadIs(ProvisioningType.attempt) && !msg.forceAuthRequest -> {}

else -> {
become(beginningReceive(state))
channel.send(msg)
}
}
}

is Message.DownloadGranted -> {
val message = "Authorization granted for downloading files"
LOG.info(message)
sendFeedback(message)
become(downloadingReceive(state))
child("downloadManager")!!.send(DeploymentInfo(state.deplBaseResp!!))
become(downloadingReceive(state.copy(deplBaseResp = msg.info)))
child("downloadManager")!!.send(msg)
}

is DeploymentCancelInfo -> {
stopUpdateAndNotify(msg)
}

is CancelForced -> {
stopUpdate()
}

else -> unhandled(msg)
}
}

private fun downloadingReceive(state: State): Receive = { msg ->
when (msg) {
is Message.DownloadFinished -> {
val message: String
if (state.updateIs(ProvisioningType.forced)) {
message = "Start updating the device"
waitingAuthJob = launch(Dispatchers.IO) {
if(forceRequest.updateAllowed().await()){
become(updatingReceive())
child("updateManager")!!.send(DeploymentInfo(state.deplBaseResp!!))
} else {
LOG.info("Authorization denied for update")
}
waitingAuthJob = null
}
} else {
message = "Waiting authorization to update"
become(waitingUpdateAuthorization(state))
notificationManager.send(MessageListener.Message.State.WaitingUpdateAuthorization(state.updateIs(ProvisioningType.forced)))
waitingAuthJob = launch(Dispatchers.IO) {
onAuthorizationReceive(softRequest)
waitingAuthJob = null
}
}
LOG.info(message)
sendFeedback(message)
become(updatingReceive())
child("updateManager")!!.send(DeploymentInfo(state.deplBaseResp!!))

}
is Message.DownloadFailed -> {
LOG.error("download failed")
Expand All @@ -171,42 +65,6 @@ private constructor(scope: ActorScope) : AbstractActor(scope) {
}
}

private suspend fun onAuthorizationReceive(deploymentPermitProvider: DeploymentPermitProvider){
if(deploymentPermitProvider.updateAllowed().await()){
channel.send(Message.UpdateGranted)
} else {
LOG.info("Authorization denied for update")
}
}

private fun waitingUpdateAuthorization(state: State): Receive = { msg ->
when (msg) {

is DeploymentInfo -> {
become(downloadingReceive(state.copy(deplBaseResp = msg.info)))
channel.send(Message.DownloadFinished)
}

is Message.UpdateGranted -> {
val message = "Authorization granted for update"
LOG.info(message)
sendFeedback(message)
become(updatingReceive())
child("updateManager")!!.send(DeploymentInfo(state.deplBaseResp!!))
}

is DeploymentCancelInfo -> {
stopUpdateAndNotify(msg)
}

is CancelForced -> {
stopUpdate()
}

else -> unhandled(msg)
}
}

private fun updatingReceive(): Receive = { msg ->
when (msg) {

Expand Down Expand Up @@ -284,8 +142,6 @@ private constructor(scope: ActorScope) : AbstractActor(scope) {
}

sealed class Message {
object DownloadGranted : Message()
object UpdateGranted : Message()
object DownloadFinished : Message()
data class DownloadFailed(val details: List<String>) : Message()
object UpdateFailed : Message()
Expand Down
Loading

0 comments on commit f9add5e

Please sign in to comment.