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

feat: Allow indirect replication #1070

Merged
merged 11 commits into from
Nov 29, 2023
Merged

feat: Allow indirect replication #1070

merged 11 commits into from
Nov 29, 2023

Conversation

patriknw
Copy link
Member

Draft because requires a change in Akka first akka/akka#32233

import org.scalatest.wordspec.AnyWordSpecLike
import org.slf4j.LoggerFactory

object IndirectReplicationIntegrationSpec {
Copy link
Member Author

Choose a reason for hiding this comment

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

This is similar to existing ReplicationIntegrationSpec

# only events from the origin replica will be transferred from the origin
# replica. When each replica is connected to each other replica it's most
# efficient to disable indirect replication.
indirect-replication = on
Copy link
Member Author

Choose a reason for hiding this comment

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

default value is off, this is included in docs and maybe we should show off
however, then the test would be testing this

Copy link
Member

Choose a reason for hiding this comment

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

Make this "off" and enable it after snippet end or through config factory apis?

Copy link
Member Author

Choose a reason for hiding this comment

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

yes

if (settings.indirectReplication || meta.originReplica == settings.selfReplicaId)
Future.successful(envelope.eventOption)
else
filteredEvent // Optimization: was replicated to this replica, don't pass the payload across the wire
Copy link
Member Author

Choose a reason for hiding this comment

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

This is the reason why I haven't enabled it by default. Would have a substantial performance overhead. We'll see where it is going when we support star topologies and such.

Copy link
Member Author

Choose a reason for hiding this comment

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

It would actually be nice to configure this per replica, but here on the producer side we don't know which replica is the consumer (at least I couldn't see that)

Copy link
Member

Choose a reason for hiding this comment

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

If it was a predicate instead of a setting (or a pattern) the user could design for a star-topology-replica naming strategy and only replicate indirectly only to the edge nodes.

Copy link
Member Author

Choose a reason for hiding this comment

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

yes, need to think this through again. we want to support a full mesh in cloud where indirect-replication=off, and edge connecting in to one or a few cloud replicas. edge consumers need indirect-replication=on

Maybe we could look at the allReplicas (or otherReplicas) and use that for deciding indirect. If it's included in the defined allReplicas then off, otherwise on. However, again, here on the producer side we don't know the replicaId of the consumer. Maybe we have to add that?

Copy link
Member

Choose a reason for hiding this comment

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

We want to indirectly replicate from cloud to edge, and from edge to other cloud replicas, so maybe it is more about knowing which replication goes/comes from where when deciding (I haven't completely thought this all the way through)?

Copy link
Member Author

Choose a reason for hiding this comment

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

indirectly ... from edge to other cloud replicas

true, didn't think about that one

Copy link
Member Author

Choose a reason for hiding this comment

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

It is the consumer side that knows what other replicas it is consuming from, otherReplicas. Therefore it would be wrong to configure or decide the indirect aspect on the producer side, but we want the actual filtering of indirect events to happen on the producer side.

We could include the otherReplicas in the InitReq from the consumer. On the producer it would then use that to decide if indirect events should be included or not. If event origin is in initReq.otherReplicas then it can be filter out, otherwise included (as indirect event).

@patriknw patriknw force-pushed the wip-res-indirect-patriknw branch from aa62b55 to a9a4f1c Compare November 17, 2023 13:27
Copy link
Member Author

@patriknw patriknw left a comment

Choose a reason for hiding this comment

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

New approach, would like feedback before continuing...

// Used for Replicated Event Sourcing, the replica id of the consumer
string replica_id = 6;
// Used for Replicated Event Sourcing, other replicas that the consumer is connected to.
repeated string other_replica_ids = 7;
Copy link
Member Author

Choose a reason for hiding this comment

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

@johanandren I have tried this instead. These replica ids are included from the consumer in the InitReq. Then that is used on the producer side to decide if an event based on its origin should be emitted or handled as FilteredEvent.

Copy link
Member Author

Choose a reason for hiding this comment

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

For producer push it would be similar. These fields would be included in the ConsumerEventStart response from the consumer side and then used on the producer side.

Copy link
Member

Choose a reason for hiding this comment

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

Ok, seems reasonable.

case Some(meta: ReplicatedEventMetadata) =>
!exclude(meta.originReplica)
case _ =>
// FIXME eventMetadata isn't loaded by backtracking
Copy link
Member Author

Choose a reason for hiding this comment

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

It's working aside from this little detail. For ordinary transformation, which we used for the origin filtering, we solve it by not applying transformation for backtracking and instead do that in loadEvent. It would be difficult to do the same for this, because then we would need the replica ids also in the load event request.

Do you think it's fine to change the r2dbc query to always load metadata, also for backtracking?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sleeping on this. Feels fragile to not use the same origin filter from loadEvent also. Even though we only use loadEvent from backtracking events I think it should have the same transformation and filtering mechanism. I think it's best to include those additional replica id fields also in the loadEvent request.

It would be difficult to do the same for this

no, that shouldn't be difficult

Copy link
Member

Choose a reason for hiding this comment

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

I agree, let's go with always passing metadata and applying the same transform/filter.

@patriknw patriknw marked this pull request as ready for review November 21, 2023 13:37
@patriknw
Copy link
Member Author

Incorporated the filter changes from #1072 because there were too many changes in same place. Also added test for such filters.

@patriknw patriknw mentioned this pull request Nov 21, 2023
1 task
@johanandren johanandren force-pushed the wip-res-indirect-patriknw branch from 55b02cc to d4cf2a8 Compare November 29, 2023 09:52
@johanandren
Copy link
Member

Rebased and bumped Akka to get this ready for merge

@patriknw patriknw force-pushed the wip-res-indirect-patriknw branch from d4cf2a8 to 41147c8 Compare November 29, 2023 12:02
@patriknw patriknw force-pushed the wip-res-indirect-patriknw branch from 41147c8 to c6f523c Compare November 29, 2023 12:15
@patriknw
Copy link
Member Author

Don't know what happened, but this didn't contain my latest work. Restored from history so now this should be ready.

@johanandren
Copy link
Member

Maybe I missed pulling the latest before rebasing, sorry!

@@ -59,6 +59,7 @@ message ConsumerEventInit {

message ConsumerEventStart {
repeated FilterCriteria filter = 1;
ReplicaInfo replica_info = 6;
Copy link
Member Author

Choose a reason for hiding this comment

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

added also to ConsumerEventStart but setting it and implementing corresponding filter on the producer side for RES must be done in @johanandren 's #1073 (or after that)

Copy link
Member

Choose a reason for hiding this comment

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

I'll do that in that PR once rebased on top of this after merged

Copy link
Member

@johanandren johanandren left a comment

Choose a reason for hiding this comment

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

LGTM

@patriknw
Copy link
Member Author

Test fail was in IntegrationSpec, which I think is unrelated. #905
However, I see it failing consistently locally, but not in main.

@patriknw
Copy link
Member Author

ah, that was because I changed log level. Some tests needed trace level. Should work now. 🤞

@johanandren johanandren merged commit 3670804 into main Nov 29, 2023
20 checks passed
@johanandren johanandren deleted the wip-res-indirect-patriknw branch November 29, 2023 13:58
@johanandren johanandren added this to the 1.5.1 milestone Nov 29, 2023
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.

2 participants