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

orbit.client.net.ConnectionHandler.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.client.net

import io.rouz.grpc.ManyToManyCall
import kotlinx.coroutines.launch
import mu.KotlinLogging
import orbit.client.OrbitClientConfig
import orbit.shared.net.Message
import orbit.shared.proto.ConnectionGrpc
import orbit.shared.proto.Messages
import orbit.shared.proto.openStream
import orbit.shared.proto.toMessage
import orbit.shared.proto.toMessageProto
import orbit.util.concurrent.RailWorker
import orbit.util.concurrent.SupervisorScope
import orbit.util.di.ComponentContainer

internal class ConnectionHandler(
    config: OrbitClientConfig,
    grpcClient: GrpcClient,
    private val scope: SupervisorScope,
    componentContainer: ComponentContainer
) {
    private val logger = KotlinLogging.logger { }
    private val messagesStub = ConnectionGrpc.newStub(grpcClient.channel)
    private val messageHandler by componentContainer.inject()

    private val messageRails = RailWorker(
        scope = scope,
        buffer = config.bufferCount,
        railCount = config.railCount,
        logger = logger,
        onMessage = this::onMessage
    )

    private lateinit var connectionChannel: ManyToManyCall

    fun connect() {
        messageRails.startWorkers()
        connectionChannel = messagesStub.openStream()

        scope.launch {
            for (msg in connectionChannel) {
                messageRails.send(msg.toMessage())
            }
        }
    }

    fun tick() {
        testConnection()
    }

    fun disconnect() {
        if (::connectionChannel.isInitialized) {
            connectionChannel.cancel()
            messageRails.stopWorkers()
        }
    }

    fun send(msg: Message) {
        testConnection();

        synchronized(connectionChannel) {
            connectionChannel.send(msg.toMessageProto())
        }
    }


    private suspend fun onMessage(message: Message) {
        messageHandler.onMessage(message)
    }

    private fun testConnection() {
        if (::connectionChannel.isInitialized) {
            if (connectionChannel.isClosedForReceive) {
                logger.warn { "The stream connection is closed. Reopening..." }
                disconnect()
                connect()
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy