-
Notifications
You must be signed in to change notification settings - Fork 8
[BE2] Fix gossip relay #1900
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BE2] Fix gossip relay #1900
Changes from 12 commits
0ba609c
fec2e4d
4b43707
dc91d4f
92ac531
07b1541
511c321
c461210
d04ebb5
b57260a
c230c68
adb065b
1240afe
d3cc018
a52f9cd
a875411
646717c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,34 +2,34 @@ package ch.epfl.pop.decentralized | |||||
|
||||||
import akka.NotUsed | ||||||
import akka.actor.{Actor, ActorLogging, ActorRef, Props} | ||||||
import akka.pattern.AskableActorRef | ||||||
import akka.pattern.{AskableActorRef, ask} | ||||||
import akka.stream.scaladsl.Flow | ||||||
import ch.epfl.pop.model.network.method.Rumor | ||||||
import ch.epfl.pop.model.network.method.message.Message | ||||||
import ch.epfl.pop.model.network.method.{GreetServer, Rumor} | ||||||
import ch.epfl.pop.model.network.{JsonRpcRequest, JsonRpcResponse, MethodType} | ||||||
import ch.epfl.pop.model.objects.{Channel, PublicKey, RumorData} | ||||||
import ch.epfl.pop.pubsub.AskPatternConstants | ||||||
import ch.epfl.pop.pubsub.ClientActor.ClientAnswer | ||||||
import ch.epfl.pop.pubsub.graph.validators.RpcValidator | ||||||
import ch.epfl.pop.pubsub.graph.{ErrorCodes, GraphMessage, PipelineError} | ||||||
import ch.epfl.pop.storage.DbActor | ||||||
import ch.epfl.pop.storage.DbActor.{DbActorAck, DbActorReadRumorData} | ||||||
import ch.epfl.pop.storage.DbActor.{DbActorAck, DbActorGetRumorStateAck, DbActorReadRumorData, GetRumorState} | ||||||
|
||||||
import scala.concurrent.Await | ||||||
import scala.util.Random | ||||||
|
||||||
final case class GossipManager( | ||||||
dbActorRef: AskableActorRef, | ||||||
monitorRef: ActorRef, | ||||||
connectionMediator: AskableActorRef, | ||||||
stopProbability: Double = 0.5 | ||||||
) extends Actor with AskPatternConstants with ActorLogging { | ||||||
/** This class is responsible of managing the gossiping of rumors across the network | ||||||
* @param dbActorRef | ||||||
* reference to the database actor | ||||||
* @param stopProbability | ||||||
* probability with which we stop the gossipping in case of error response | ||||||
*/ | ||||||
final case class GossipManager(dbActorRef: AskableActorRef, stopProbability: Double = 0.5) extends Actor with AskPatternConstants with ActorLogging { | ||||||
|
||||||
private type ServerInfos = (ActorRef, GreetServer) | ||||||
private var activeGossipProtocol: Map[JsonRpcRequest, List[ServerInfos]] = Map.empty | ||||||
private var activeGossipProtocol: Map[JsonRpcRequest, Set[ActorRef]] = Map.empty | ||||||
private var jsonId = 0 | ||||||
private var rumorId = 0 | ||||||
private var publicKey: Option[PublicKey] = None | ||||||
private var connectionMediatorRef: AskableActorRef = _ | ||||||
|
||||||
publicKey = { | ||||||
val readPk = dbActorRef ? DbActor.ReadServerPublicKey() | ||||||
|
@@ -40,48 +40,20 @@ final case class GossipManager( | |||||
None | ||||||
} | ||||||
|
||||||
rumorId = | ||||||
publicKey match | ||||||
case Some(pk: PublicKey) => | ||||||
val readRumorData = dbActorRef ? DbActor.ReadRumorData(pk) | ||||||
Await.result(readRumorData, duration) match | ||||||
case DbActorReadRumorData(foundRumorIds: RumorData) => foundRumorIds.lastRumorId() + 1 | ||||||
case failure => 0 | ||||||
case None => 0 | ||||||
|
||||||
monitorRef ! GossipManager.Ping() | ||||||
connectionMediator ? GossipManager.Ping() | ||||||
|
||||||
private def getPeersForRumor(jsonRpcRequest: JsonRpcRequest): List[ServerInfos] = { | ||||||
val activeGossip = activeGossipProtocol.get(jsonRpcRequest) | ||||||
activeGossip match | ||||||
case Some(peersInfosList) => peersInfosList | ||||||
case None => List.empty | ||||||
} | ||||||
|
||||||
private def prepareRumor(rumor: Rumor): JsonRpcRequest = { | ||||||
val request = JsonRpcRequest( | ||||||
RpcValidator.JSON_RPC_VERSION, | ||||||
MethodType.rumor, | ||||||
rumor, | ||||||
Some(jsonId) | ||||||
) | ||||||
jsonId += 1 | ||||||
request | ||||||
} | ||||||
|
||||||
/** Does a step of gossipping protocol for given rpc. Tries to find a random peer that hasn't already received this msg If such a peer is found, sends message and updates table accordingly. If no peer is found, ends the protocol. | ||||||
* @param rumorRpc | ||||||
* Rpc that must be spreac | ||||||
*/ | ||||||
private def updateGossip(rumorRpc: JsonRpcRequest): Unit = { | ||||||
// checks the peers to which we already forwarded the message | ||||||
val activeGossip: List[ServerInfos] = getPeersForRumor(rumorRpc) | ||||||
// get senderpk to avoid sending rumor back | ||||||
val senderPk: PublicKey = rumorRpc.getParams.asInstanceOf[Rumor].senderPk | ||||||
val activeGossip: Set[ActorRef] = peersAlreadyReceived(rumorRpc) | ||||||
// selects a random peer from remaining peers | ||||||
val randomPeer = connectionMediator ? ConnectionMediator.GetRandomPeer(activeGossip.map(_._2.publicKey).appended(senderPk)) | ||||||
val randomPeer = connectionMediatorRef ? ConnectionMediator.GetRandomPeer(activeGossip) | ||||||
Await.result(randomPeer, duration) match { | ||||||
// updates the list based on response | ||||||
// if some peers are available we send | ||||||
case ConnectionMediator.GetRandomPeerAck(serverRef, greetServer) => | ||||||
val alreadySent: List[ServerInfos] = activeGossip :+ (serverRef -> greetServer) | ||||||
val alreadySent: Set[ActorRef] = activeGossip + serverRef | ||||||
activeGossipProtocol += (rumorRpc -> alreadySent) | ||||||
log.info(s"rumorSent > dest : ${greetServer.clientAddress}, rumor : $rumorRpc") | ||||||
serverRef ! ClientAnswer( | ||||||
|
@@ -95,15 +67,22 @@ final case class GossipManager( | |||||
} | ||||||
} | ||||||
|
||||||
private def handleRumor(request: JsonRpcRequest): Unit = { | ||||||
/** When receiving a rumor that must be relayed, empacks a rumor in a new jsonRPC and tries to do a step of gossipping protocol | ||||||
* @param request | ||||||
*/ | ||||||
|
||||||
private def handleRumor(request: JsonRpcRequest, serverActorRef: ActorRef): Unit = { | ||||||
val rcvRumor = request.getParams.asInstanceOf[Rumor] | ||||||
val newRumorRequest = prepareRumor(rcvRumor) | ||||||
activeGossipProtocol += (newRumorRequest -> Set(serverActorRef)) | ||||||
updateGossip(newRumorRequest) | ||||||
} | ||||||
|
||||||
/** Processes a response. If a response matches a active gossip protocol, uses the reponse to decide how to continue gossipping If response is Positive (Result(0)), tries to do another step of gossipping If response is Negative (Error(-3)), considers stop gossiping | ||||||
|
/** Processes a response. If a response matches a active gossip protocol, uses the reponse to decide how to continue gossipping If response is Positive (Result(0)), tries to do another step of gossipping If response is Negative (Error(-3)), considers stop gossiping | |
/** Processes a response. If a response matches an active gossip protocol, uses the response to decide how to continue gosipping If response is Positive (Result(0)), tries to do another step of gosipping If response is Negative (Error(-3)), considers stop gossiping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually double checked online and "gossipping" is correct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
my bad, shouldn't have blindly trusted intellij !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/** When receives a new publish, empacks messages in a new rumor and starts gossipping it in the network | |
/** When receives a new publish, packs messages in a new rumor and starts gossiping it in the network |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,8 +3,8 @@ package ch.epfl.pop.pubsub.graph | |
import akka.NotUsed | ||
import akka.pattern.AskableActorRef | ||
import akka.stream.scaladsl.Flow | ||
import ch.epfl.pop.model.network.method.{Broadcast, Catchup, GetMessagesById} | ||
import ch.epfl.pop.model.network._ | ||
import ch.epfl.pop.model.network.method.{Broadcast, Catchup, GetMessagesById, Rumor} | ||
|
||
import ch.epfl.pop.model.network.* | ||
import ch.epfl.pop.model.objects.DbActorNAckException | ||
import ch.epfl.pop.pubsub.AskPatternConstants | ||
import ch.epfl.pop.pubsub.graph.validators.RpcValidator | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.