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

commonMain.com.caesarealabs.rpc4k.runtime.api.EngineUtils.kt Maven / Gradle / Ivy

package com.caesarealabs.rpc4k.runtime.api

import com.caesarealabs.logging.Logging
import com.caesarealabs.logging.PrintLogging
import com.caesarealabs.rpc4k.runtime.implementation.sendOrDrop

/**
 * Should be called by server implementations whenever a new message is received.
 * @param bytes The entire message sent by the client
 * @param connection An instance created by the server implementation that identifies the specific client that has sent the message,
 * in order to send responses back to that client.
 * @param initialLogs Allows logging once the logger is initialized
 */
public suspend fun ServerConfig.acceptEventSubscription(bytes: ByteArray, connection: EventConnection, initialLogs: Logging.() -> Unit = {}) {
    val message = try {
        C2SEventMessage.fromByteArray(bytes)
    } catch (e: InvalidRpcRequestException) {
        return config.logging.wrapCall("Other Sub Failures") {
            initialLogs()
            invalidMessage(e, connection, PrintLogging)
        }
    } catch (e: Throwable) {
        return config.logging.wrapCall("Other Internal Sub Failures") {
            initialLogs()
            serverError(e, connection, PrintLogging) { "Failed to call C2SEventMessage.fromByteArray()" }
        }
    }
    // Logging available
    return config.logging.wrapCall(message.event) {
        initialLogs()
        val logging = this@wrapCall
        try {
            // Mark what kind of event is this to make it easy to search by the specific event type
            logData("call_type") {
                when (message) {
                    is C2SEventMessage.Subscribe -> "event_sub"
                    is C2SEventMessage.Unsubscribe -> "event_unsub"
                }
            }

            when (message) {
                is C2SEventMessage.Subscribe -> config.eventManager.subscribe(message, connection)
                is C2SEventMessage.Unsubscribe -> config.eventManager.unsubscribe(message.event, message.listenerId)
            }
        } catch (e: InvalidRpcRequestException) {
            invalidMessage(e, connection, logging)
        } catch (e: Throwable) {
            serverError(e, connection, logging) { "Failed to subscribe/unsubscribe to event ${message.event}" }
        }
    }

}

private suspend fun ServerConfig.invalidMessage(e: InvalidRpcRequestException, connection: EventConnection, logging: Logging) {
    logging.logWarn(e) { "Invalid client event message" }
    // RpcServerException messages are trustworthy
    config.sendOrDrop(connection, S2CEventMessage.SubscriptionError("Invalid client event message: ${e.message}").toByteArray(), logging)
}

private suspend fun ServerConfig.serverError(e: Throwable, connection: EventConnection, logging: Logging, logMessage: () -> String) {
    logging.logError(e, logMessage)
    config.sendOrDrop(connection, S2CEventMessage.SubscriptionError("Server failed to process subscription").toByteArray(), logging)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy