Add ReplicationScheduledEvent to indicate ref replication is scheduled. Assure that event is posted only once each time a ref is scheduled. Covers the corner case when the ref is added to already scheduled push. Change-Id: I175940f8d4c6b9164c41bbec8c52d221ec30001b Signed-off-by: Eryk Szymanski <eryksz@gmail.com>
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java index b20f8eb..5e9f01c 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/Destination.java
@@ -14,15 +14,20 @@ package com.googlesource.gerrit.plugins.replication; +import static com.googlesource.gerrit.plugins.replication.PushResultProcessing.resolveNodeName; + import com.google.common.base.Throwables; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.Lists; +import com.google.gerrit.common.EventDispatcher; import com.google.gerrit.common.data.GroupReference; import com.google.gerrit.extensions.config.FactoryModule; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.reviewdb.client.AccountGroup; +import com.google.gerrit.reviewdb.client.Branch; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.reviewdb.server.ReviewDb; @@ -76,6 +81,7 @@ private volatile WorkQueue.Executor pool; private final PerThreadRequestScope.Scoper threadScoper; private final DestinationConfiguration config; + private final DynamicItem<EventDispatcher> eventDispatcher; protected enum RetryReason { TRANSPORT_ERROR, COLLISION, REPOSITORY_MISSING; @@ -99,8 +105,10 @@ GitRepositoryManager gitRepositoryManager, GroupBackend groupBackend, ReplicationStateListener stateLog, - GroupIncludeCache groupIncludeCache) { + GroupIncludeCache groupIncludeCache, + DynamicItem<EventDispatcher> eventDispatcher) { config = cfg; + this.eventDispatcher = eventDispatcher; gitManager = gitRepositoryManager; this.stateLog = stateLog; @@ -283,10 +291,12 @@ PushOne e = pending.get(uri); if (e == null) { e = opFactory.create(project, uri); + addRef(e, ref); pool.schedule(e, config.getDelay(), TimeUnit.SECONDS); pending.put(uri, e); + } else if (!e.getRefs().contains(ref)) { + addRef(e, ref); } - e.addRef(ref); state.increasePushTaskCount(project.get(), ref); e.addState(ref, state); repLog.info("scheduled {}:{} => {} to run after {}s", project, ref, @@ -301,6 +311,11 @@ } } + private void addRef(PushOne e, String ref) { + e.addRef(ref); + postEvent(e, ref); + } + /** * It schedules again a PushOp instance. * <p> @@ -556,4 +571,12 @@ } return uri.toString().contains(urlMatch); } + + private void postEvent(PushOne pushOp, String ref) { + Project.NameKey project = pushOp.getProjectNameKey(); + String targetNode = resolveNodeName(pushOp.getURI()); + ReplicationScheduledEvent event = + new ReplicationScheduledEvent(project.get(), ref, targetNode); + eventDispatcher.get().postEvent(new Branch.NameKey(project, ref), event); + } }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/DestinationFactory.java b/src/main/java/com/googlesource/gerrit/plugins/replication/DestinationFactory.java index dd82aa0..970a018 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/DestinationFactory.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/DestinationFactory.java
@@ -14,6 +14,8 @@ package com.googlesource.gerrit.plugins.replication; +import com.google.gerrit.common.EventDispatcher; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.server.PluginUser; import com.google.gerrit.server.account.GroupBackend; import com.google.gerrit.server.account.GroupIncludeCache; @@ -31,6 +33,7 @@ private final GroupBackend groupBackend; private final ReplicationStateListener stateLog; private final GroupIncludeCache groupIncludeCache; + private final DynamicItem<EventDispatcher> eventDispatcher; @Inject public DestinationFactory(Injector injector, @@ -39,7 +42,8 @@ GitRepositoryManager gitRepositoryManager, GroupBackend groupBackend, ReplicationStateListener stateLog, - GroupIncludeCache groupIncludeCache) { + GroupIncludeCache groupIncludeCache, + DynamicItem<EventDispatcher> eventDispatcher) { this.injector = injector; this.replicationUserFactory = replicationUserFactory; this.pluginUser = pluginUser; @@ -47,10 +51,12 @@ this.groupBackend = groupBackend; this.stateLog = stateLog; this.groupIncludeCache = groupIncludeCache; + this.eventDispatcher = eventDispatcher; } Destination create(DestinationConfiguration config) { return new Destination(injector, config, replicationUserFactory, pluginUser, - gitRepositoryManager, groupBackend, stateLog, groupIncludeCache); + gitRepositoryManager, groupBackend, stateLog, groupIncludeCache, + eventDispatcher); } -} \ No newline at end of file +}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/PushResultProcessing.java b/src/main/java/com/googlesource/gerrit/plugins/replication/PushResultProcessing.java index 6717660..8df1c1c 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/PushResultProcessing.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/PushResultProcessing.java
@@ -55,7 +55,7 @@ // Default doing nothing } - private static String resolveNodeName(URIish uri) { + static String resolveNodeName(URIish uri) { StringBuilder sb = new StringBuilder(); if (uri.isRemote()) { sb.append(uri.getHost());
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java index 5434619..c8957e7 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationModule.java
@@ -67,6 +67,8 @@ EventTypes.register(RefReplicatedEvent.TYPE, RefReplicatedEvent.class); EventTypes.register(RefReplicationDoneEvent.TYPE, RefReplicationDoneEvent.class); + EventTypes.register( + ReplicationScheduledEvent.TYPE, ReplicationScheduledEvent.class); bind(SshSessionFactory.class).toProvider( ReplicationSshSessionFactoryProvider.class); }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationScheduledEvent.java b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationScheduledEvent.java new file mode 100644 index 0000000..d24fbb5 --- /dev/null +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/ReplicationScheduledEvent.java
@@ -0,0 +1,45 @@ +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.googlesource.gerrit.plugins.replication; + +import com.google.gerrit.reviewdb.client.Project; +import com.google.gerrit.reviewdb.client.Project.NameKey; +import com.google.gerrit.server.events.RefEvent; + +public class ReplicationScheduledEvent extends RefEvent { + static final String TYPE = "ref-replication-scheduled"; + + final String project; + final String ref; + final String targetNode; + + public ReplicationScheduledEvent(String project, String ref, + String targetNode) { + super(TYPE); + this.project = project; + this.ref = ref; + this.targetNode = targetNode; + } + + @Override + public String getRefName() { + return ref; + } + + @Override + public NameKey getProjectNameKey() { + return new Project.NameKey(project); + } +}