186 lines
6.7 KiB
Nim

import std/json
import chronos, chronicles, results, ffi
import libp2p/peerid # pull PeerId pretty string formatting
import logos_delivery/waku/common/base64
import
logos_delivery,
logos_delivery/waku/node/waku_node,
logos_delivery/api/types,
logos_delivery/waku/api/events/health_events,
logos_delivery/waku/api/events/peer_events,
logos_delivery/api/conf/logos_delivery_conf_json,
../declare_lib,
../json_event
# Add JSON serialization for RequestId
proc `%`*(id: RequestId): JsonNode =
%($id)
proc logosdelivery_create_node(
configJson: string
): Future[Result[LogosDelivery, string]] {.ffiCtor.} =
let conf = parseLogosDeliveryConf(configJson).valueOr:
error "Failed to parse Logos Delivery configuration JSON",
error = error, configJson = configJson
return err("failed parseLogosDeliveryConf " & error)
let lib = (await LogosDelivery.new(conf)).valueOr:
let errMsg = $error
chronicles.error "CreateNodeRequest failed", err = errMsg
return err(errMsg)
return ok(lib)
proc logosdelivery_destroy(self: LogosDelivery) {.ffiDtor.} =
discard
proc registerFFIEventListeners(self: LogosDelivery): Result[void, string] =
## Bridges every broker event the library re-publishes onto the FFI event
## registry. Keep in step with `dropFFIEventListeners`.
MessageSentEvent.listen(
self.waku.brokerCtx,
proc(event: MessageSentEvent) {.async: (raises: []).} =
emitEvent("onMessageSent"):
$newJsonEvent("message_sent", event),
).isOkOr:
chronicles.error "MessageSentEvent.listen failed", err = $error
return err("MessageSentEvent.listen failed: " & $error)
MessageErrorEvent.listen(
self.waku.brokerCtx,
proc(event: MessageErrorEvent) {.async: (raises: []).} =
emitEvent("onMessageError"):
$newJsonEvent("message_error", event),
).isOkOr:
chronicles.error "MessageErrorEvent.listen failed", err = $error
return err("MessageErrorEvent.listen failed: " & $error)
MessagePropagatedEvent.listen(
self.waku.brokerCtx,
proc(event: MessagePropagatedEvent) {.async: (raises: []).} =
emitEvent("onMessagePropagated"):
$newJsonEvent("message_propagated", event),
).isOkOr:
chronicles.error "MessagePropagatedEvent.listen failed", err = $error
return err("MessagePropagatedEvent.listen failed: " & $error)
MessageReceivedEvent.listen(
self.waku.brokerCtx,
proc(event: MessageReceivedEvent) {.async: (raises: []).} =
emitEvent("onMessageReceived"):
$newJsonEvent("message_received", event),
).isOkOr:
chronicles.error "MessageReceivedEvent.listen failed", err = $error
return err("MessageReceivedEvent.listen failed: " & $error)
EventConnectionStatusChange.listen(
self.waku.brokerCtx,
proc(event: EventConnectionStatusChange) {.async: (raises: []).} =
emitEvent("onConnectionStatusChange"):
$newJsonEvent("connection_status_change", event),
).isOkOr:
chronicles.error "ConnectionStatusChange.listen failed", err = $error
return err("ConnectionStatusChange.listen failed: " & $error)
EventShardTopicHealthChange.listen(
self.waku.brokerCtx,
proc(event: EventShardTopicHealthChange) {.async: (raises: []).} =
emitEvent("onTopicHealthChange"):
$(
%*{
"eventType": "relay_topic_health_change",
"pubsubTopic": $event.topic,
"topicHealth": $event.health,
}
),
).isOkOr:
chronicles.error "EventShardTopicHealthChange.listen failed", err = $error
return err("EventShardTopicHealthChange.listen failed: " & $error)
WakuPeerEvent.listen(
self.waku.brokerCtx,
proc(event: WakuPeerEvent) {.async: (raises: []).} =
emitEvent("onConnectionChange"):
$(
%*{
"eventType": "connection_change",
"peerId": $event.peerId,
"peerEvent": $event.kind,
}
),
).isOkOr:
chronicles.error "WakuPeerEvent.listen failed", err = $error
return err("WakuPeerEvent.listen failed: " & $error)
ChannelMessageReceivedEvent.listen(
self.waku.brokerCtx,
proc(event: ChannelMessageReceivedEvent) {.async: (raises: []).} =
emitEvent("onChannelMessageReceived"):
$(
%*{
"eventType": "channel_message_received",
"channelId": string(event.channelId),
"senderId": $event.senderId,
"payload": string(base64.encode(event.payload)),
}
),
).isOkOr:
chronicles.error "ChannelMessageReceivedEvent.listen failed", err = $error
return err("ChannelMessageReceivedEvent.listen failed: " & $error)
ChannelMessageSentEvent.listen(
self.waku.brokerCtx,
proc(event: ChannelMessageSentEvent) {.async: (raises: []).} =
emitEvent("onChannelMessageSent"):
$newJsonEvent("channel_message_sent", event),
).isOkOr:
chronicles.error "ChannelMessageSentEvent.listen failed", err = $error
return err("ChannelMessageSentEvent.listen failed: " & $error)
ChannelMessageErrorEvent.listen(
self.waku.brokerCtx,
proc(event: ChannelMessageErrorEvent) {.async: (raises: []).} =
emitEvent("onChannelMessageError"):
$newJsonEvent("channel_message_error", event),
).isOkOr:
chronicles.error "ChannelMessageErrorEvent.listen failed", err = $error
return err("ChannelMessageErrorEvent.listen failed: " & $error)
return ok()
proc dropFFIEventListeners(self: LogosDelivery) {.async.} =
## Reverse of `registerFFIEventListeners`.
await MessageErrorEvent.dropAllListeners(self.waku.brokerCtx)
await MessageSentEvent.dropAllListeners(self.waku.brokerCtx)
await MessagePropagatedEvent.dropAllListeners(self.waku.brokerCtx)
await MessageReceivedEvent.dropAllListeners(self.waku.brokerCtx)
await EventConnectionStatusChange.dropAllListeners(self.waku.brokerCtx)
await EventShardTopicHealthChange.dropAllListeners(self.waku.brokerCtx)
await WakuPeerEvent.dropAllListeners(self.waku.brokerCtx)
await ChannelMessageReceivedEvent.dropAllListeners(self.waku.brokerCtx)
await ChannelMessageSentEvent.dropAllListeners(self.waku.brokerCtx)
await ChannelMessageErrorEvent.dropAllListeners(self.waku.brokerCtx)
proc logosdelivery_start_node(
self: LogosDelivery
): Future[Result[string, string]] {.ffi.} =
self.registerFFIEventListeners().isOkOr:
return err(error)
(await self.start()).isOkOr:
let errMsg = $error
chronicles.error "START_NODE failed", err = errMsg
return err("failed to start: " & errMsg)
return ok("")
proc logosdelivery_stop_node(
self: LogosDelivery
): Future[Result[string, string]] {.ffi.} =
await self.dropFFIEventListeners()
(await self.stop()).isOkOr:
let errMsg = $error
chronicles.error "STOP_NODE failed", err = errMsg
return err("failed to stop: " & errMsg)
return ok("")