tech.pylons.ipc.IPCLayer.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of libpylons Show documentation
Show all versions of libpylons Show documentation
Library providing common functionality for interacting with the Pylons ecosystem
The newest version!
package tech.pylons.ipc
import java.lang.reflect.Method
import kotlin.random.Random
abstract class IPCLayer(val permitUnboundOperations : Boolean) {
var clientId : Int = 0
var walletId : Int = Random.nextInt()
var messageId : Int = 0
class NoClientException : Exception() { }
class ConnectionBrokenException : Exception() { }
enum class ConnectionState {
NoClient,
Connected,
ConnectionBroken
}
annotation class OnGetNext
protected open fun initIpcChannel() { if (!permitUnboundOperations) establishConnection(); initialized = true }
protected abstract fun getNextJson(callback: (String) -> Unit)
protected open fun preprocessResponse(r : Response,
callback: (Response) -> Unit) {callback(r)}
protected open fun cleanup() {}
abstract fun establishConnection()
abstract fun checkConnectionStatus() : ConnectionState
abstract fun connectionBroken()
abstract fun submit (r : Response)
abstract fun reject (json : String)
var connectionState : ConnectionState = ConnectionState.NoClient
private set
protected var initialized = false
fun onMessage (msg : Message) {
msg.ui()
}
fun onUiConfirmed (uiHook: Message.UiHook) {
uiHook.response = uiHook.msg.resolve()
handleResponse(uiHook.response!!)
}
fun onUiRejected (uiHook: Message.UiHook) {
uiHook.response = Response.emit(uiHook.msg, false)
handleResponse(uiHook.response!!)
}
fun onUiReleased (uiHook: Message.UiHook) {
// Unclear on what if anything needs to be done here rn
}
companion object {
var implementation : IPCLayer? = null
set(value) { field = value; init() }
private lateinit var onGetNextList : List
private fun init () {
onGetNextList = findAllOnGetNextMethods()
}
private fun updateConnectionState() {
implementation!!.connectionState = implementation!!.checkConnectionStatus()
if (implementation!!.connectionState == ConnectionState.NoClient && !implementation!!.permitUnboundOperations)
throw NoClientException()
else if (implementation!!.connectionState == ConnectionState.ConnectionBroken && !implementation!!.permitUnboundOperations)
throw ConnectionBrokenException()
}
private fun findAllOnGetNextMethods () : List {
val ls = mutableListOf()
implementation!!::class.java.declaredMethods.forEach {
if (it.getAnnotation(OnGetNext::class.java) != null)
ls.add(it)
}
return ls
}
fun getNextMessage(callback : (Message) -> Unit) {
safelyDoIpcOperation {
implementation?.getNextJson {
println("got: \n$it")
val msg = Message.match(it)
println("matched!")
when (msg) {
null -> implementation!!.reject(it)
else -> {
onGetNextList.forEach { method ->
method.invoke(implementation, msg)
}
implementation!!.onMessage(msg)
println("trying to do callback")
callback(msg)
}
}
}
}
}
fun handleResponse(r : Response) {
println("handleResponse safelyDoIpcOperation")
safelyDoIpcOperation {
println("preprocessResponse")
implementation!!.preprocessResponse(r) {
implementation!!.submit(r)
implementation!!.cleanup()
}
}
}
private fun safelyDoIpcOperation (action : () -> Unit) {
if (!implementation!!.initialized) implementation!!.initIpcChannel()
try {
updateConnectionState()
action()
} catch (e : Exception) {
when (e) {
is NoClientException -> {
implementation!!.establishConnection()
}
is ConnectionBrokenException -> {
implementation!!.connectionBroken()
}
else -> throw e // todo: this should do some logging before it dies
}
}
}
}
}