mirror of
https://github.com/logos-messaging/logos-messaging-nim.git
synced 2026-01-04 06:53:12 +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>
261 lines
8.6 KiB
Nim
261 lines
8.6 KiB
Nim
import
|
|
std/[strformat, sysrand, random, strutils, sequtils],
|
|
system/ansi_c,
|
|
chronicles,
|
|
chronos,
|
|
chronos/timer as chtimer,
|
|
stew/byteutils,
|
|
results,
|
|
json_serialization as js
|
|
import
|
|
waku/[
|
|
common/logging,
|
|
waku_node,
|
|
node/peer_manager,
|
|
waku_core,
|
|
waku_lightpush/client,
|
|
waku_lightpush/common,
|
|
common/utils/parse_size_units,
|
|
],
|
|
./tester_config,
|
|
./tester_message,
|
|
./lpt_metrics,
|
|
./diagnose_connections,
|
|
./service_peer_management
|
|
|
|
randomize()
|
|
|
|
type SizeRange* = tuple[min: uint64, max: uint64]
|
|
|
|
var RANDOM_PALYLOAD {.threadvar.}: seq[byte]
|
|
RANDOM_PALYLOAD = urandom(1024 * 1024)
|
|
# 1MiB of random payload to be used to extend message
|
|
|
|
proc prepareMessage(
|
|
sender: string,
|
|
messageIndex, numMessages: uint32,
|
|
startedAt: TimeStamp,
|
|
prevMessageAt: var Timestamp,
|
|
contentTopic: ContentTopic,
|
|
size: SizeRange,
|
|
): (WakuMessage, uint64) =
|
|
var renderSize = rand(size.min .. size.max)
|
|
let current = getNowInNanosecondTime()
|
|
let payload = ProtocolTesterMessage(
|
|
sender: sender,
|
|
index: messageIndex,
|
|
count: numMessages,
|
|
startedAt: startedAt,
|
|
sinceStart: current - startedAt,
|
|
sincePrev: current - prevMessageAt,
|
|
size: renderSize,
|
|
)
|
|
|
|
prevMessageAt = current
|
|
|
|
let text = js.Json.encode(payload)
|
|
let contentPayload = toBytes(text & " \0")
|
|
|
|
if renderSize < len(contentPayload).uint64:
|
|
renderSize = len(contentPayload).uint64
|
|
|
|
let finalPayload = concat(
|
|
contentPayload, RANDOM_PALYLOAD[0 .. renderSize - len(contentPayload).uint64]
|
|
)
|
|
let message = WakuMessage(
|
|
payload: finalPayload, # content of the message
|
|
contentTopic: contentTopic, # content topic to publish to
|
|
ephemeral: true, # tell store nodes to not store it
|
|
timestamp: current, # current timestamp
|
|
)
|
|
|
|
return (message, renderSize)
|
|
|
|
var sentMessages {.threadvar.}: OrderedTable[uint32, tuple[hash: string, relayed: bool]]
|
|
var failedToSendCause {.threadvar.}: Table[string, uint32]
|
|
var failedToSendCount {.threadvar.}: uint32
|
|
var numMessagesToSend {.threadvar.}: uint32
|
|
var messagesSent {.threadvar.}: uint32
|
|
var noOfServicePeerSwitches {.threadvar.}: uint32
|
|
|
|
proc reportSentMessages() =
|
|
let report = catch:
|
|
"""*----------------------------------------*
|
|
| Service Peer Switches: {noOfServicePeerSwitches:>15} |
|
|
*----------------------------------------*
|
|
| Expected | Sent | Failed |
|
|
|{numMessagesToSend+failedToSendCount:>11} |{messagesSent:>11} |{failedToSendCount:>11} |
|
|
*----------------------------------------*""".fmt()
|
|
|
|
if report.isErr:
|
|
echo "Error while printing statistics"
|
|
else:
|
|
echo report.get()
|
|
|
|
echo "*--------------------------------------------------------------------------------------------------*"
|
|
echo "| Failure cause | count |"
|
|
for (cause, count) in failedToSendCause.pairs:
|
|
echo fmt"|{cause:<87}|{count:>10}|"
|
|
echo "*--------------------------------------------------------------------------------------------------*"
|
|
|
|
echo "*--------------------------------------------------------------------------------------------------*"
|
|
echo "| Index | Relayed | Hash |"
|
|
for (index, info) in sentMessages.pairs:
|
|
echo fmt"|{index+1:>10}|{info.relayed:<9}| {info.hash:<76}|"
|
|
echo "*--------------------------------------------------------------------------------------------------*"
|
|
# evere sent message hash should logged once
|
|
sentMessages.clear()
|
|
|
|
proc publishMessages(
|
|
wakuNode: WakuNode,
|
|
servicePeer: RemotePeerInfo,
|
|
lightpushPubsubTopic: PubsubTopic,
|
|
lightpushContentTopic: ContentTopic,
|
|
numMessages: uint32,
|
|
messageSizeRange: SizeRange,
|
|
messageInterval: Duration,
|
|
preventPeerSwitch: bool,
|
|
) {.async.} =
|
|
var actualServicePeer = servicePeer
|
|
let startedAt = getNowInNanosecondTime()
|
|
var prevMessageAt = startedAt
|
|
var renderMsgSize = messageSizeRange
|
|
# sets some default of min max message size to avoid conflict with meaningful payload size
|
|
renderMsgSize.min = max(1024.uint64, renderMsgSize.min) # do not use less than 1KB
|
|
renderMsgSize.max = max(2048.uint64, renderMsgSize.max) # minimum of max is 2KB
|
|
renderMsgSize.min = min(renderMsgSize.min, renderMsgSize.max)
|
|
renderMsgSize.max = max(renderMsgSize.min, renderMsgSize.max)
|
|
|
|
const maxFailedPush = 3
|
|
var noFailedPush = 0
|
|
var noFailedServiceNodeSwitches = 0
|
|
|
|
let selfPeerId = $wakuNode.switch.peerInfo.peerId
|
|
failedToSendCount = 0
|
|
numMessagesToSend = if numMessages == 0: uint32.high else: numMessages
|
|
messagesSent = 0
|
|
|
|
while messagesSent < numMessagesToSend:
|
|
let (message, msgSize) = prepareMessage(
|
|
selfPeerId,
|
|
messagesSent + 1,
|
|
numMessagesToSend,
|
|
startedAt,
|
|
prevMessageAt,
|
|
lightpushContentTopic,
|
|
renderMsgSize,
|
|
)
|
|
let wlpRes = await wakuNode.legacyLightpushPublish(
|
|
some(lightpushPubsubTopic), message, actualServicePeer
|
|
)
|
|
|
|
let msgHash = computeMessageHash(lightpushPubsubTopic, message).to0xHex
|
|
|
|
if wlpRes.isOk():
|
|
sentMessages[messagesSent] = (hash: msgHash, relayed: true)
|
|
notice "published message using lightpush",
|
|
index = messagesSent + 1,
|
|
count = numMessagesToSend,
|
|
size = msgSize,
|
|
pubsubTopic = lightpushPubsubTopic,
|
|
hash = msgHash
|
|
inc(messagesSent)
|
|
lpt_publisher_sent_messages_count.inc()
|
|
lpt_publisher_sent_bytes.inc(amount = msgSize.int64)
|
|
if noFailedPush > 0:
|
|
noFailedPush -= 1
|
|
else:
|
|
sentMessages[messagesSent] = (hash: msgHash, relayed: false)
|
|
failedToSendCause.mgetOrPut(wlpRes.error, 1).inc()
|
|
error "failed to publish message using lightpush",
|
|
err = wlpRes.error, hash = msgHash
|
|
inc(failedToSendCount)
|
|
lpt_publisher_failed_messages_count.inc(labelValues = [wlpRes.error])
|
|
if not wlpRes.error.toLower().contains("dial"):
|
|
# retry sending after shorter wait
|
|
await sleepAsync(2.seconds)
|
|
continue
|
|
else:
|
|
noFailedPush += 1
|
|
lpt_service_peer_failure_count.inc(
|
|
labelValues = ["publisher", actualServicePeer.getAgent()]
|
|
)
|
|
if not preventPeerSwitch and noFailedPush > maxFailedPush:
|
|
info "Max push failure limit reached, Try switching peer."
|
|
let peerOpt = selectRandomServicePeer(
|
|
wakuNode.peerManager, some(actualServicePeer), WakuLightPushCodec
|
|
)
|
|
if peerOpt.isOk():
|
|
actualServicePeer = peerOpt.get()
|
|
|
|
info "New service peer in use",
|
|
codec = lightpushPubsubTopic,
|
|
peer = constructMultiaddrStr(actualServicePeer)
|
|
|
|
noFailedPush = 0
|
|
noOfServicePeerSwitches += 1
|
|
lpt_change_service_peer_count.inc(labelValues = ["publisher"])
|
|
continue # try again with new peer without delay
|
|
else:
|
|
error "Failed to find new service peer. Exiting."
|
|
noFailedServiceNodeSwitches += 1
|
|
break
|
|
|
|
await sleepAsync(messageInterval)
|
|
|
|
proc setupAndPublish*(
|
|
wakuNode: WakuNode, conf: LiteProtocolTesterConf, servicePeer: RemotePeerInfo
|
|
) =
|
|
if isNil(wakuNode.wakuLightpushClient):
|
|
# if we have not yet initialized lightpush client, then do it as the only way we can get here is
|
|
# by having a service peer discovered.
|
|
wakuNode.mountLegacyLightPushClient()
|
|
|
|
# give some time to receiver side to set up
|
|
let waitTillStartTesting = conf.startPublishingAfter.seconds
|
|
|
|
let parsedMinMsgSize = parseMsgSize(conf.minTestMessageSize).valueOr:
|
|
error "failed to parse 'min-test-msg-size' param: ", error = error
|
|
return
|
|
|
|
let parsedMaxMsgSize = parseMsgSize(conf.maxTestMessageSize).valueOr:
|
|
error "failed to parse 'max-test-msg-size' param: ", error = error
|
|
return
|
|
|
|
info "Sending test messages in", wait = waitTillStartTesting
|
|
waitFor sleepAsync(waitTillStartTesting)
|
|
|
|
info "Start sending messages to service node using lightpush"
|
|
|
|
sentMessages.sort(system.cmp)
|
|
|
|
let interval = secs(60)
|
|
var printStats: CallbackFunc
|
|
|
|
printStats = CallbackFunc(
|
|
proc(udata: pointer) {.gcsafe.} =
|
|
reportSentMessages()
|
|
|
|
if messagesSent >= numMessagesToSend:
|
|
info "All messages are sent. Exiting."
|
|
|
|
## for gracefull shutdown through signal hooks
|
|
discard c_raise(ansi_c.SIGTERM)
|
|
else:
|
|
discard setTimer(Moment.fromNow(interval), printStats)
|
|
)
|
|
|
|
discard setTimer(Moment.fromNow(interval), printStats)
|
|
|
|
# Start maintaining subscription
|
|
asyncSpawn publishMessages(
|
|
wakuNode,
|
|
servicePeer,
|
|
conf.pubsubTopics[0],
|
|
conf.contentTopics[0],
|
|
conf.numMessages,
|
|
(min: parsedMinMsgSize, max: parsedMaxMsgSize),
|
|
conf.messageInterval.milliseconds,
|
|
conf.fixedServicePeer,
|
|
)
|