mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-03 06:23:10 +00:00
* Separate new lightpush protocol New RPC defined Rename al occurence of old lightpush to legacy lightpush, fix rest tests of lightpush New lightpush protocol added back Setup new lightpush protocol, mounting and rest api for it modified: apps/chat2/chat2.nim modified: tests/node/test_wakunode_lightpush.nim modified: tests/node/test_wakunode_sharding.nim modified: tests/test_peer_manager.nim modified: tests/test_wakunode_lightpush.nim renamed: tests/waku_lightpush/lightpush_utils.nim -> tests/waku_lightpush_legacy/lightpush_utils.nim renamed: tests/waku_lightpush/test_all.nim -> tests/waku_lightpush_legacy/test_all.nim renamed: tests/waku_lightpush/test_client.nim -> tests/waku_lightpush_legacy/test_client.nim renamed: tests/waku_lightpush/test_ratelimit.nim -> tests/waku_lightpush_legacy/test_ratelimit.nim modified: tests/wakunode_rest/test_all.nim renamed: tests/wakunode_rest/test_rest_lightpush.nim -> tests/wakunode_rest/test_rest_lightpush_legacy.nim modified: waku/factory/node_factory.nim modified: waku/node/waku_node.nim modified: waku/waku_api/rest/admin/handlers.nim modified: waku/waku_api/rest/builder.nim new file: waku/waku_api/rest/legacy_lightpush/client.nim new file: waku/waku_api/rest/legacy_lightpush/handlers.nim new file: waku/waku_api/rest/legacy_lightpush/types.nim modified: waku/waku_api/rest/lightpush/client.nim modified: waku/waku_api/rest/lightpush/handlers.nim modified: waku/waku_api/rest/lightpush/types.nim modified: waku/waku_core/codecs.nim modified: waku/waku_lightpush.nim modified: waku/waku_lightpush/callbacks.nim modified: waku/waku_lightpush/client.nim modified: waku/waku_lightpush/common.nim modified: waku/waku_lightpush/protocol.nim modified: waku/waku_lightpush/rpc.nim modified: waku/waku_lightpush/rpc_codec.nim modified: waku/waku_lightpush/self_req_handler.nim new file: waku/waku_lightpush_legacy.nim renamed: waku/waku_lightpush/README.md -> waku/waku_lightpush_legacy/README.md new file: waku/waku_lightpush_legacy/callbacks.nim new file: waku/waku_lightpush_legacy/client.nim new file: waku/waku_lightpush_legacy/common.nim new file: waku/waku_lightpush_legacy/protocol.nim new file: waku/waku_lightpush_legacy/protocol_metrics.nim new file: waku/waku_lightpush_legacy/rpc.nim new file: waku/waku_lightpush_legacy/rpc_codec.nim new file: waku/waku_lightpush_legacy/self_req_handler.nim Adapt to non-invasive libp2p observers cherry pick latest lightpush (v1) changes into legacy lightpush code after rebase to latest master Fix vendor dependencies from origin/master after failed rebase of them Adjust examples, test to new lightpush - keep using of legacy Fixup error code mappings Fix REST admin interface with distinct legacy and new lightpush Fix lightpush v2 tests * Utilize new publishEx interface of pubsub libp2p * Adapt to latest libp2p pubslih design changes. publish returns an outcome as Result error. * Fix review findings * Fix tests, re-added lost one * Fix rebase * Apply suggestions from code review Co-authored-by: Ivan FB <128452529+Ivansete-status@users.noreply.github.com> * Addressing review comments * Fix incentivization tests * Fix build failed on libwaku * Change new lightpush endpoint version to 3 instead of 2. Noticed that old and new lightpush metrics can cause trouble in monitoring dashboards so decided to give new name as v3 for the new lightpush metrics and change legacy ones back - temporarly till old lightpush will be decommissioned * Fixing flaky test with rate limit timing * Fixing logscope of lightpush and legacy lightpush --------- Co-authored-by: Ivan FB <128452529+Ivansete-status@users.noreply.github.com>
213 lines
7.4 KiB
Nim
213 lines
7.4 KiB
Nim
## This module reinforces the publish operation with regular store-v3 requests.
|
|
##
|
|
|
|
import std/sequtils
|
|
import chronos, chronicles, libp2p/utility
|
|
import
|
|
./delivery_callback,
|
|
./publish_observer,
|
|
../../waku_core,
|
|
./not_delivered_storage/not_delivered_storage,
|
|
../../waku_store/[client, common],
|
|
../../waku_archive/archive,
|
|
../../waku_relay/protocol,
|
|
../../waku_lightpush/client
|
|
|
|
const MaxTimeInCache* = chronos.minutes(1)
|
|
## Messages older than this time will get completely forgotten on publication and a
|
|
## feedback will be given when that happens
|
|
|
|
const SendCheckInterval* = chronos.seconds(3)
|
|
## Interval at which we check that messages have been properly received by a store node
|
|
|
|
const MaxMessagesToCheckAtOnce = 100
|
|
## Max number of messages to check if they were properly archived by a store node
|
|
|
|
const ArchiveTime = chronos.seconds(3)
|
|
## Estimation of the time we wait until we start confirming that a message has been properly
|
|
## received and archived by a store node
|
|
|
|
type DeliveryInfo = object
|
|
pubsubTopic: string
|
|
msg: WakuMessage
|
|
|
|
type SendMonitor* = ref object of PublishObserver
|
|
publishedMessages: Table[WakuMessageHash, DeliveryInfo]
|
|
## Cache that contains the delivery info per message hash.
|
|
## This is needed to make sure the published messages are properly published
|
|
|
|
msgStoredCheckerHandle: Future[void] ## handle that allows to stop the async task
|
|
|
|
notDeliveredStorage: NotDeliveredStorage
|
|
## NOTE: this is not fully used because that might be tackled by higher abstraction layers
|
|
|
|
storeClient: WakuStoreClient
|
|
deliveryCb: DeliveryFeedbackCallback
|
|
|
|
wakuRelay: protocol.WakuRelay
|
|
wakuLightpushClient: WakuLightPushClient
|
|
|
|
proc new*(
|
|
T: type SendMonitor,
|
|
storeClient: WakuStoreClient,
|
|
wakuRelay: protocol.WakuRelay,
|
|
wakuLightpushClient: WakuLightPushClient,
|
|
): Result[T, string] =
|
|
if wakuRelay.isNil() and wakuLightpushClient.isNil():
|
|
return err(
|
|
"Could not create SendMonitor. wakuRelay or wakuLightpushClient should be set"
|
|
)
|
|
|
|
let notDeliveredStorage = ?NotDeliveredStorage.new()
|
|
|
|
let sendMonitor = SendMonitor(
|
|
notDeliveredStorage: notDeliveredStorage,
|
|
storeClient: storeClient,
|
|
wakuRelay: wakuRelay,
|
|
wakuLightpushClient: wakuLightPushClient,
|
|
)
|
|
|
|
if not wakuRelay.isNil():
|
|
wakuRelay.addPublishObserver(sendMonitor)
|
|
|
|
if not wakuLightpushClient.isNil():
|
|
wakuLightpushClient.addPublishObserver(sendMonitor)
|
|
|
|
return ok(sendMonitor)
|
|
|
|
proc performFeedbackAndCleanup(
|
|
self: SendMonitor,
|
|
msgsToDiscard: Table[WakuMessageHash, DeliveryInfo],
|
|
success: DeliverySuccess,
|
|
dir: DeliveryDirection,
|
|
comment: string,
|
|
) =
|
|
## This procs allows to bring delivery feedback to the API client
|
|
## It requires a 'deliveryCb' to be registered beforehand.
|
|
if self.deliveryCb.isNil():
|
|
error "deliveryCb is nil in performFeedbackAndCleanup",
|
|
success, dir, comment, hashes = toSeq(msgsToDiscard.keys).mapIt(shortLog(it))
|
|
return
|
|
|
|
for hash, deliveryInfo in msgsToDiscard:
|
|
debug "send monitor performFeedbackAndCleanup",
|
|
success, dir, comment, msg_hash = shortLog(hash)
|
|
|
|
self.deliveryCb(success, dir, comment, hash, deliveryInfo.msg)
|
|
self.publishedMessages.del(hash)
|
|
|
|
proc checkMsgsInStore(
|
|
self: SendMonitor, msgsToValidate: Table[WakuMessageHash, DeliveryInfo]
|
|
): Future[
|
|
Result[
|
|
tuple[
|
|
publishedCorrectly: Table[WakuMessageHash, DeliveryInfo],
|
|
notYetPublished: Table[WakuMessageHash, DeliveryInfo],
|
|
],
|
|
void,
|
|
]
|
|
] {.async.} =
|
|
let hashesToValidate = toSeq(msgsToValidate.keys)
|
|
|
|
let storeResp: StoreQueryResponse = (
|
|
await self.storeClient.queryToAny(
|
|
StoreQueryRequest(includeData: false, messageHashes: hashesToValidate)
|
|
)
|
|
).valueOr:
|
|
error "checkMsgsInStore failed to get remote msgHashes",
|
|
hashes = hashesToValidate.mapIt(shortLog(it)), error = $error
|
|
return err()
|
|
|
|
let publishedHashes = storeResp.messages.mapIt(it.messageHash)
|
|
|
|
var notYetPublished: Table[WakuMessageHash, DeliveryInfo]
|
|
var publishedCorrectly: Table[WakuMessageHash, DeliveryInfo]
|
|
|
|
for msgHash, deliveryInfo in msgsToValidate.pairs:
|
|
if publishedHashes.contains(msgHash):
|
|
publishedCorrectly[msgHash] = deliveryInfo
|
|
self.publishedMessages.del(msgHash) ## we will no longer track that message
|
|
else:
|
|
notYetPublished[msgHash] = deliveryInfo
|
|
|
|
return ok((publishedCorrectly: publishedCorrectly, notYetPublished: notYetPublished))
|
|
|
|
proc processMessages(self: SendMonitor) {.async.} =
|
|
var msgsToValidate: Table[WakuMessageHash, DeliveryInfo]
|
|
var msgsToDiscard: Table[WakuMessageHash, DeliveryInfo]
|
|
|
|
let now = getNowInNanosecondTime()
|
|
let timeToCheckThreshold = now - ArchiveTime.nanos
|
|
let maxLifeTime = now - MaxTimeInCache.nanos
|
|
|
|
for hash, deliveryInfo in self.publishedMessages.pairs:
|
|
if deliveryInfo.msg.timestamp < maxLifeTime:
|
|
## message is too old
|
|
msgsToDiscard[hash] = deliveryInfo
|
|
|
|
if deliveryInfo.msg.timestamp < timeToCheckThreshold:
|
|
msgsToValidate[hash] = deliveryInfo
|
|
|
|
## Discard the messages that are too old
|
|
self.performFeedbackAndCleanup(
|
|
msgsToDiscard, DeliverySuccess.UNSUCCESSFUL, DeliveryDirection.PUBLISHING,
|
|
"Could not publish messages. Please try again.",
|
|
)
|
|
|
|
let (publishedCorrectly, notYetPublished) = (
|
|
await self.checkMsgsInStore(msgsToValidate)
|
|
).valueOr:
|
|
return ## the error log is printed in checkMsgsInStore
|
|
|
|
## Give positive feedback for the correctly published messages
|
|
self.performFeedbackAndCleanup(
|
|
publishedCorrectly, DeliverySuccess.SUCCESSFUL, DeliveryDirection.PUBLISHING,
|
|
"messages published correctly",
|
|
)
|
|
|
|
## Try to publish again
|
|
for msgHash, deliveryInfo in notYetPublished.pairs:
|
|
let pubsubTopic = deliveryInfo.pubsubTopic
|
|
let msg = deliveryInfo.msg
|
|
if not self.wakuRelay.isNil():
|
|
debug "trying to publish again with wakuRelay", msgHash, pubsubTopic
|
|
(await self.wakuRelay.publish(pubsubTopic, msg)).isOkOr:
|
|
error "could not publish with wakuRelay.publish",
|
|
msgHash, pubsubTopic, error = $error
|
|
continue
|
|
|
|
if not self.wakuLightpushClient.isNil():
|
|
debug "trying to publish again with wakuLightpushClient", msgHash, pubsubTopic
|
|
(await self.wakuLightpushClient.publishToAny(pubsubTopic, msg)).isOkOr:
|
|
error "could not publish with publishToAny", error = $error
|
|
continue
|
|
|
|
proc checkIfMessagesStored(self: SendMonitor) {.async.} =
|
|
## Continuously monitors that the sent messages have been received by a store node
|
|
while true:
|
|
await self.processMessages()
|
|
await sleepAsync(SendCheckInterval)
|
|
|
|
method onMessagePublished(
|
|
self: SendMonitor, pubsubTopic: string, msg: WakuMessage
|
|
) {.gcsafe, raises: [].} =
|
|
## Implementation of the PublishObserver interface.
|
|
##
|
|
## When publishing a message either through relay or lightpush, we want to add some extra effort
|
|
## to make sure it is received to one store node. Hence, keep track of those published messages.
|
|
|
|
debug "onMessagePublished"
|
|
let msgHash = computeMessageHash(pubSubTopic, msg)
|
|
|
|
if not self.publishedMessages.hasKey(msgHash):
|
|
self.publishedMessages[msgHash] = DeliveryInfo(pubsubTopic: pubsubTopic, msg: msg)
|
|
|
|
proc startSendMonitor*(self: SendMonitor) =
|
|
self.msgStoredCheckerHandle = self.checkIfMessagesStored()
|
|
|
|
proc stopSendMonitor*(self: SendMonitor) =
|
|
discard self.msgStoredCheckerHandle.cancelAndWait()
|
|
|
|
proc setDeliveryCallback*(self: SendMonitor, deliveryCb: DeliveryFeedbackCallback) =
|
|
self.deliveryCb = deliveryCb
|