fix race condition by setting the peers on init

This commit is contained in:
Richard Ramos 2021-08-31 18:51:37 -04:00 committed by Iuri Matias
parent d0514f366d
commit 350472ed03
6 changed files with 46 additions and 102 deletions

View File

@ -21,7 +21,7 @@ proc handleSignals(self: ChatController) =
self.status.events.on(SignalType.PeerStats.event) do(e:Args):
var data = PeerStatsSignal(e)
let
mailserverWorker = self.status.tasks.marathon[MailserverWorker().name]
mailserverWorker = self.appService.marathon[MailserverWorker().name]
task = PeerSummaryChangeTaskArg(
`method`: "peerSummaryChange",
peers: data.peers

View File

@ -1,5 +1,5 @@
import NimQml, chronicles
import status/[signals, status, node, network]
import status/[signals, status, node, network, settings]
import ../../app_service/[main]
import eventemitter
import view
@ -13,6 +13,7 @@ type NodeController* = ref object
view*: NodeView
variant*: QVariant
networkAccessMananger*: QNetworkAccessManager
isWakuV2: bool
proc newController*(status: Status, appService: AppService, nam: QNetworkAccessManager): NodeController =
result = NodeController()
@ -26,25 +27,30 @@ proc delete*(self: NodeController) =
delete self.variant
delete self.view
proc setPeers(self: NodeController, peers: seq[string]) =
self.status.network.peerSummaryChange(peers)
self.view.setPeerSize(peers.len)
proc init*(self: NodeController) =
self.isWakuV2 = self.status.settings.getWakuVersion() == 2
self.status.events.on(SignalType.Wallet.event) do(e:Args):
self.view.setLastMessage($WalletSignal(e).blockNumber)
self.status.events.on(SignalType.DiscoverySummary.event) do(e:Args):
var data = DiscoverySummarySignal(e)
self.status.network.peerSummaryChange(data.enodes)
self.view.setPeerSize(data.enodes.len)
self.setPeers(data.enodes)
self.status.events.on(SignalType.PeerStats.event) do(e:Args):
var data = PeerStatsSignal(e)
self.status.network.peerSummaryChange(data.peers)
self.view.setPeerSize(data.peers.len)
self.setPeers(data.peers)
self.status.events.on(SignalType.Stats.event) do (e:Args):
self.view.setStats(StatsSignal(e).stats)
self.view.fetchBitsSet()
if not self.isWakuV2: self.view.fetchBitsSet()
self.status.events.on(SignalType.ChroniclesLogs.event) do(e:Args):
self.view.log(ChroniclesLogsSignal(e).content)
self.view.init()
self.setPeers(self.status.network.fetchPeers())

View File

@ -64,7 +64,7 @@ proc init*(self: ProfileController, account: Account) =
self.view.ens.init()
self.view.initialized()
for name, endpoint in self.status.fleet.config.getMailservers(self.status.settings.getFleet()).pairs():
for name, endpoint in self.status.fleet.config.getMailservers(self.status.settings.getFleet(), self.status.settings.getWakuVersion() == 2).pairs():
let mailserver = MailServer(name: name, endpoint: endpoint)
self.view.mailservers.add(mailserver)

View File

@ -1,6 +1,6 @@
import
algorithm, chronos, chronicles, json, math, os, random, sequtils, sets,
tables
tables, strutils
from times import cpuTime
import
@ -39,6 +39,7 @@ type
activeMailserver*: string
lastConnectionAttempt*: float
fleet*: FleetModel
wakuVersion*: int
MailserverStatus* = enum
Unknown = -1,
@ -46,6 +47,10 @@ type
Connecting = 1
Connected = 2,
proc peerIdFromMultiAddress(nodeAddr: string): string =
let multiAddressParts = nodeAddr.split("/")
return multiAddressParts[multiAddressParts.len - 1]
proc cmpMailserverReply(x, y: (string, int)): int =
if x[1] > y[1]: 1
elif x[1] == y[1]: 0
@ -68,7 +73,8 @@ proc init*(self: MailserverModel) =
"/../fleets.json"
let fleetConfig = readFile(joinPath(getAppDir(), fleets))
self.fleet = newFleetModel(fleetConfig)
self.mailservers = toSeq(self.fleet.config.getMailservers(status_settings.getFleet()).values)
self.wakuVersion = status_settings.getWakuVersion()
self.mailservers = toSeq(self.fleet.config.getMailservers(status_settings.getFleet(), self.wakuVersion == 2).values)
for mailserver in status_settings.getMailservers().getElems():
self.mailservers.add(mailserver["address"].getStr())
@ -80,33 +86,39 @@ proc isActiveMailserverAvailable*(self: MailserverModel): bool =
else:
result = self.nodes[self.activeMailserver] == MailserverStatus.Connected
proc connect(self: MailserverModel, enode: string) =
info "Connecting to mailserver", enode=enode.substr[enode.len-40..enode.len-1]
proc connect(self: MailserverModel, nodeAddr: string) =
debug "Connecting to mailserver", nodeAddr
var connected = false
# TODO: this should come from settings
var knownMailservers = initHashSet[string]()
for m in self.mailservers:
knownMailservers.incl m
if not knownMailservers.contains(enode):
warn "Mailserver not known", enode
if not knownMailservers.contains(nodeAddr):
warn "Mailserver not known", nodeAddr
return
self.activeMailserver = enode
info "Mailserver changed", enode
self.events.emit("mailserver:changed", MailserverArgs(peer: enode))
self.activeMailserver = if self.wakuVersion == 2: peerIdFromMultiAddress(nodeAddr) else: nodeAddr
self.events.emit("mailserver:changed", MailserverArgs(peer: nodeAddr))
# Adding a peer and marking it as connected can't be executed sync, because
# Adding a peer and marking it as connected can't be executed sync in WakuV1, because
# There's a delay between requesting a peer being added, and a signal being
# received after the peer was added. So we first set the peer status as
# Connecting and once a peerConnected signal is received, we mark it as
# Connected
if self.nodes.hasKey(enode) and self.nodes[enode] == MailserverStatus.Connected:
if self.nodes.hasKey(self.activeMailserver) and self.nodes[self.activeMailserver] == MailserverStatus.Connected:
connected = true
else:
# Attempt to connect to mailserver by adding it as a peer
status_mailservers.update(enode)
self.nodes[enode] = MailserverStatus.Connecting
if self.wakuVersion == 2:
if status_core.dialPeer(nodeAddr): # WakuV2 dial is sync (should it be async?)
discard status_mailservers.setMailserver(self.activeMailserver)
self.nodes[self.activeMailserver] = MailserverStatus.Connected
connected = true
else:
status_mailservers.update(nodeAddr)
self.nodes[nodeAddr] = MailserverStatus.Connecting
self.lastConnectionAttempt = cpuTime()
if connected:
@ -165,7 +177,7 @@ proc fillGaps*(self: MailserverModel, chatId: string, messageIds: seq[string]) =
proc findNewMailserver(self: MailserverModel) =
warn "Finding a new mailserver..."
let mailserversReply = parseJson(status_mailservers.ping(self.mailservers, 500))["result"]
let mailserversReply = parseJson(status_mailservers.ping(self.mailservers, 500, self.wakuVersion == 2))["result"]
var availableMailservers:seq[(string, int)] = @[]
for reply in mailserversReply:
@ -191,7 +203,10 @@ proc cycleMailservers(self: MailserverModel) =
if self.activeMailserver != "":
info "Disconnecting active mailserver", peer=self.activeMailserver
self.nodes[self.activeMailserver] = MailserverStatus.Disconnected
removePeer(self.activeMailserver)
if self.wakuVersion == 2:
dropPeerByID(self.activeMailserver)
else:
removePeer(self.activeMailserver)
self.activeMailserver = ""
self.findNewMailserver()
@ -199,7 +214,7 @@ proc checkConnection*(self: MailserverModel) {.async.} =
while true:
info "Verifying mailserver connection state..."
let pinnedMailserver = status_settings.getPinnedMailserver()
if pinnedMailserver != "" and self.activeMailserver != pinnedMailserver:
if self.wakuVersion == 1 and pinnedMailserver != "" and self.activeMailserver != pinnedMailserver:
# connect to current mailserver from the settings
self.mailservers.add(pinnedMailserver)
self.connect(pinnedMailserver)

View File

@ -1,77 +0,0 @@
import NimQml, tables, json, chronicles, strutils, json_serialization
import ../types as status_types
import types, messages, discovery, whisperFilter, envelopes, expired, wallet, mailserver, communities, stats, peerstats
import ../status
import ../../eventemitter
logScope:
topics = "signals"
QtObject:
type SignalsController* = ref object of QObject
variant*: QVariant
status*: Status
proc newController*(status: Status): SignalsController =
new(result)
result.status = status
result.setup()
result.variant = newQVariant(result)
proc setup(self: SignalsController) =
self.QObject.setup
proc delete*(self: SignalsController) =
self.variant.delete
self.QObject.delete
proc processSignal(self: SignalsController, statusSignal: string) =
var jsonSignal: JsonNode
try:
jsonSignal = statusSignal.parseJson
except:
error "Invalid signal received", data = statusSignal
return
let signalString = jsonSignal["type"].getStr
trace "Raw signal data", data = $jsonSignal
var signalType: SignalType
try:
signalType = parseEnum[SignalType](signalString)
except:
warn "Unknown signal received", type = signalString
signalType = SignalType.Unknown
return
var signal: Signal = case signalType:
of SignalType.Message: messages.fromEvent(jsonSignal)
of SignalType.EnvelopeSent: envelopes.fromEvent(jsonSignal)
of SignalType.EnvelopeExpired: expired.fromEvent(jsonSignal)
of SignalType.WhisperFilterAdded: whisperFilter.fromEvent(jsonSignal)
of SignalType.Wallet: wallet.fromEvent(jsonSignal)
of SignalType.NodeLogin: Json.decode($jsonSignal, NodeSignal)
of SignalType.PeerStats: peerStats.fromEvent(jsonSignal)
of SignalType.DiscoverySummary: discovery.fromEvent(jsonSignal)
of SignalType.MailserverRequestCompleted: mailserver.fromCompletedEvent(jsonSignal)
of SignalType.MailserverRequestExpired: mailserver.fromExpiredEvent(jsonSignal)
of SignalType.CommunityFound: communities.fromEvent(jsonSignal)
of SignalType.Stats: stats.fromEvent(jsonSignal)
else: Signal()
if(signalType == SignalType.NodeLogin):
if(NodeSignal(signal).event.error != ""):
error "node.login", error=NodeSignal(signal).event.error
if(signalType == SignalType.NodeCrashed):
error "node.crashed", error=statusSignal
self.status.events.emit(signalType.event, signal)
proc signalReceived*(self: SignalsController, signal: string) {.signal.}
proc receiveSignal(self: SignalsController, signal: string) {.slot.} =
self.processSignal(signal)
self.signalReceived(signal)

2
vendor/status-lib vendored

@ -1 +1 @@
Subproject commit e29ba9c9faa391ec6c4c504edc37e044c8ff4736
Subproject commit a80869872d822bdc239cc67f98c6fb3a7f54febe