mirror of
https://github.com/logos-messaging/logos-delivery.git
synced 2026-06-04 13:09:32 +00:00
118 lines
4.0 KiB
Nim
118 lines
4.0 KiB
Nim
{.push raises: [].}
|
|
|
|
import chronos, chronicles, results
|
|
import brokers/broker_context
|
|
|
|
import waku/factory/waku
|
|
import layers/mounts
|
|
import messaging/messaging_client
|
|
import tools/confutils/cli_args
|
|
|
|
export messaging_client
|
|
|
|
logScope:
|
|
topics = "logos-delivery"
|
|
|
|
type LogosDelivery* = ref object
|
|
brokerCtx*: BrokerContext
|
|
waku*: Waku
|
|
## Kernel layer. Always present.
|
|
messaging*: MessagingClient
|
|
## Messaging layer. `nil` in the kernel-only composition.
|
|
|
|
# The composition is selected by the primary layer typedesc:
|
|
# `new(Waku, ...)` is kernel-only, `new(MessagingClient, ...)` is the full stack.
|
|
|
|
proc new*(
|
|
T: type LogosDelivery, primary: typedesc[Waku], node: Waku
|
|
): Result[LogosDelivery, string] =
|
|
## Kernel-only. Waku is the primary.
|
|
if node.isNil():
|
|
return err("LogosDelivery.new(Waku): node is nil")
|
|
mountLayer(Waku, node.brokerCtx).isOkOr:
|
|
return err("mount Waku layer failed: " & error)
|
|
ok(LogosDelivery(brokerCtx: node.brokerCtx, waku: node, messaging: nil))
|
|
|
|
proc new*(
|
|
T: type LogosDelivery, primary: typedesc[MessagingClient], node: Waku
|
|
): Result[LogosDelivery, string] =
|
|
## Messaging primary. Mounts the kernel, then the messaging layer on top;
|
|
## rolls back the kernel gate if messaging fails to mount.
|
|
if node.isNil():
|
|
return err("LogosDelivery.new(MessagingClient): node is nil")
|
|
mountLayer(Waku, node.brokerCtx).isOkOr:
|
|
return err("mount Waku layer failed: " & error)
|
|
let messaging = MessagingClient.new(node.brokerCtx, node.conf.p2pReliability)
|
|
mountLayer(MessagingClient, messaging.brokerCtx).isOkOr:
|
|
discard unmountLayer(Waku, node.brokerCtx)
|
|
return err("mount MessagingClient layer failed: " & error)
|
|
ok(LogosDelivery(brokerCtx: node.brokerCtx, waku: node, messaging: messaging))
|
|
|
|
proc new*(
|
|
T: type LogosDelivery,
|
|
primary: typedesc[MessagingClient],
|
|
preset: string,
|
|
mode: WakuMode,
|
|
): Future[Result[LogosDelivery, string]] {.async: (raises: []).} =
|
|
## Messaging primary, kernel built from `(preset, mode)` defaults.
|
|
var conf = defaultWakuNodeConf().valueOr:
|
|
return err("defaultWakuNodeConf failed: " & error)
|
|
conf.preset = preset
|
|
conf.mode = mode
|
|
|
|
let wakuConf = conf.toWakuConf().valueOr:
|
|
return err("toWakuConf failed: " & error)
|
|
|
|
let w =
|
|
try:
|
|
(await Waku.new(wakuConf)).valueOr:
|
|
return err("Waku.new failed: " & $error)
|
|
except CatchableError as e:
|
|
return err("Waku.new raised: " & e.msg)
|
|
|
|
return LogosDelivery.new(MessagingClient, w)
|
|
|
|
proc start*(self: LogosDelivery): Future[Result[void, string]] {.async: (raises: []).} =
|
|
## Kernel first (its broker providers must be live before messaging queries
|
|
## protocol-mount status), then the messaging layer if present.
|
|
if self.isNil() or self.waku.isNil():
|
|
return err("LogosDelivery.start: delivery/waku is nil")
|
|
|
|
(await startWaku(addr self.waku)).isOkOr:
|
|
return err("startWaku failed: " & error)
|
|
|
|
if not self.messaging.isNil():
|
|
(await self.messaging.start()).isOkOr:
|
|
return err("MessagingClient.start failed: " & error)
|
|
|
|
ok()
|
|
|
|
proc stop*(self: LogosDelivery): Future[Result[void, string]] {.async: (raises: []).} =
|
|
## Tear down in reverse: messaging (if present) then the kernel, releasing
|
|
## each layer's gate. Best-effort: reports the first error.
|
|
if self.isNil():
|
|
return err("LogosDelivery.stop: delivery is nil")
|
|
|
|
var firstErr = ""
|
|
|
|
if not self.messaging.isNil():
|
|
(await self.messaging.stop()).isOkOr:
|
|
firstErr = "MessagingClient.stop failed: " & error
|
|
let unmountMsgRes = unmountLayer(MessagingClient, self.messaging.brokerCtx)
|
|
if unmountMsgRes.isErr() and firstErr.len == 0:
|
|
firstErr = "unmount MessagingClient layer failed: " & unmountMsgRes.error
|
|
|
|
if not self.waku.isNil():
|
|
let stopRes = await self.waku.stop()
|
|
if stopRes.isErr() and firstErr.len == 0:
|
|
firstErr = "Waku.stop failed: " & stopRes.error
|
|
let unmountRes = unmountLayer(Waku, self.waku.brokerCtx)
|
|
if unmountRes.isErr() and firstErr.len == 0:
|
|
firstErr = "unmount Waku layer failed: " & unmountRes.error
|
|
|
|
if firstErr.len > 0:
|
|
return err(firstErr)
|
|
ok()
|
|
|
|
{.pop.}
|