Skip to content
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

prevent joining an already existed response topic #13

Merged
merged 3 commits into from
Aug 12, 2021

Conversation

merlinran
Copy link
Contributor

With re-publishing, this can be seen in bidbot frequently. This is a fix.

2021-08-04T16:37:33.488+0200  ERROR  mpeer/pubsub  pubsub/pubsub.go:283  creating response topic: joining topic: topic already exists
2021-08-04T16:38:17.039+0200  ERROR  mpeer/pubsub  pubsub/pubsub.go:283  creating response topic: joining topic: topic already exists
2021-08-04T16:38:46.664+0200  ERROR  mpeer/pubsub  pubsub/pubsub.go:283  creating response topic: joining topic: topic already exists
2021-08-04T16:40:21.257+0200  ERROR  mpeer/pubsub  pubsub/pubsub.go:283  creating response topic: joining topic: topic already exists

Signed-off-by: Merlin Ran <merlinran@gmail.com>
rpc.go Outdated
if err != nil &&
// this can happen when more than one messages are received
// from the same peer.
!strings.Contains(err.Error(), "topic already exists") {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentionally or not, the libp2p library doesn't provide a better way to check this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A decision also needs to be made here: Should we continue or simply return if topic exists? For our usage, an existing topic means duplicated message, which should simply be ignored (the only topic with more than one messages is the AuctionTopic, which doesn't watch for response), but for general user case, it should be totally fine to send many messages on a single topic and expect many responses.

I vote for correctness of this package and let the caller handle duplications

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oop continuing won't work... as top is nil for whatever err returned.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this must happen when the first response topic hasn't been closed yet. I think it's reasonable to assume only one response can be sent at a time... but many can be sent over the lifetime of the topic.

conclusion: just ignore the error and return from publishResponse.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, this relates to race condition - because publishResponse runs in a separate goroutine, what if there are actually more than one messages arrive, hence start several goroutines? All but the first one would be responded.

Even if we respond all messages, they can be out of order, hence a bigger problem: the other end gets response for a wrong message. The simplest would be to stop spawning new goroutine for response.

@merlinran
Copy link
Contributor Author

There's some previous discussion around this behaviour of Join libp2p/go-libp2p-pubsub#253

@merlinran
Copy link
Contributor Author

If we want to send multiple responses to the same host for a single topic, we need to remember the topics we already created for response - creating the response topic when a peer joins and closing when it leaves, for example. Or, we can have unique response topic for each individual message, which is too heavy I feel.

Signed-off-by: Merlin Ran <merlinran@gmail.com>
t.publishResponse(msg.ReceivedFrom, msgID, data, err)
}()
msgID := cid.NewCidV1(cid.Raw, util.Hash(msg.Data))
t.publishResponse(msg.ReceivedFrom, msgID, data, err)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ended up making publishResponse synchronous. It is actually not a blocking call as I anticipated. What it does: 1) call newTopic, which returns immediately, and 2) call topic.Publish, which blocks when calling t.p.disc.Bootstrap https://github.com/libp2p/go-libp2p-pubsub/blob/master/topic.go#L245, but only if WithReadiness is set, which we don't. So, synchronous call always close the response topic, and responses are never out of order.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, that sounds much better

rpc.go Outdated
@@ -91,6 +91,7 @@ func NewTopic(ctx context.Context, ps *pubsub.PubSub, host peer.ID, topic string
}
t.resTopic, err = newTopic(ctx, ps, host, responseTopic(topic, host), true)
if err != nil {
t.cancel()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drive-by. cleaning up goroutines in case of error.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be t.Close()?

Copy link
Contributor Author

@merlinran merlinran Aug 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right... fixed. also added some lines to properly close resources in newTopic 9176585

@merlinran
Copy link
Contributor Author

@sanderpick how do you feel about the changes now?

Copy link
Member

@sanderpick sanderpick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 💪

@merlinran merlinran changed the title do not treat topic already exists as error prevent joining an already existed response topic Aug 12, 2021
Signed-off-by: Merlin Ran <merlinran@gmail.com>
@merlinran
Copy link
Contributor Author

Merging. Thanks for the discussion here!

@merlinran merlinran merged commit 08dfe40 into main Aug 12, 2021
@merlinran merlinran deleted the merlin/topic-exists branch August 12, 2021 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants