All Downloads are FREE. Search and download functionalities are using the official Maven repository.

orbit.server.mesh.LocalNodeInfo.kt Maven / Gradle / Ivy

There is a newer version: 2.0.0a19
Show newest version
/*
 Copyright (C) 2015 - 2019 Electronic Arts Inc.  All rights reserved.
 This file is part of the Orbit Project .
 See license in LICENSE.
 */

package orbit.server.mesh

import mu.KotlinLogging
import orbit.server.service.HealthCheck
import orbit.shared.exception.InvalidNodeId
import orbit.shared.mesh.NodeCapabilities
import orbit.shared.mesh.NodeId
import orbit.shared.mesh.NodeInfo
import orbit.shared.mesh.NodeStatus
import orbit.util.time.Clock
import java.util.concurrent.atomic.AtomicReference

const val MANAGEMENT_NAMESPACE = "management"

class LocalNodeInfo(
    private val clusterManager: ClusterManager,
    private val clock: Clock,
    private val serverInfo: LocalServerInfo
) : HealthCheck {
    override suspend fun isHealthy(): Boolean {
        return this.info.nodeStatus == NodeStatus.ACTIVE
    }

    private val logger = KotlinLogging.logger {}

    val info: NodeInfo
        get() = infoRef.get().also {
            checkNotNull(it) { "LocalNodeInfo not initialized. " }
        }

    private val infoRef = AtomicReference()

    suspend fun updateInfo(body: (NodeInfo) -> NodeInfo) {
        clusterManager.updateNode(info.id) {
            checkNotNull(it) { "LocalNodeInfo not present in directory. ${info.id}" }
            body(it)
        }.also {
            infoRef.set(it)
        }
    }

    suspend fun start() {
        join()
    }

    suspend fun join(nodeId: NodeId? = null, nodeStatus: NodeStatus = NodeStatus.STARTING) {
        clusterManager.joinCluster(MANAGEMENT_NAMESPACE, NodeCapabilities(), this.serverInfo.url, nodeStatus, nodeId)
            .also {
                logger.info("Joined cluster as (${it.id})")
                infoRef.set(it)
            }
    }

    suspend fun tick() {
        if (clock.inPast(info.lease.renewAt)) {
            try {
                clusterManager.renewLease(info.id, info.lease.challengeToken, info.capabilities).also {
                    infoRef.set(it)
                }
            } catch (e: InvalidNodeId) {
                logger.info("Failed to renew lease, rejoining cluster.")
                join(nodeId = info.id, nodeStatus = NodeStatus.ACTIVE)
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy