Merge branch 'stable-2.16' into stable-3.0
* stable-2.16:
Exclude web_sessions cache from cache-eviction events propagation
Change-Id: I3ded37b0e12062d112a974c44a0cecb240aa8949
diff --git a/BUILD b/BUILD
index c933c98..ec555d5 100644
--- a/BUILD
+++ b/BUILD
@@ -17,12 +17,9 @@
],
resources = glob(["src/main/resources/**/*"]),
deps = [
+ "@global-refdb//jar",
+ "@events-broker//jar",
":replication-neverlink",
- "@curator-client//jar",
- "@curator-framework//jar",
- "@curator-recipes//jar",
- "@kafka-client//jar",
- "@zookeeper//jar",
],
)
@@ -51,13 +48,9 @@
visibility = ["//visibility:public"],
exports = PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
":multi-site__plugin",
- "@curator-client//jar",
- "@curator-framework//jar",
- "@curator-test//jar",
- "@mockito//jar",
- "@testcontainers-kafka//jar",
"@wiremock//jar",
- "//lib/testcontainers",
+ "@global-refdb//jar",
+ "@events-broker//jar",
"//plugins/replication",
],
)
diff --git a/README.md b/README.md
index 49e96df..0bf8486 100644
--- a/README.md
+++ b/README.md
@@ -78,29 +78,10 @@
```
[gerrit]
+ installDbModule = com.googlesource.gerrit.plugins.multisite.GitModule
installModule = com.googlesource.gerrit.plugins.multisite.Module
```
-Create the `$GERRIT_SITE/etc/multi-site.config` on all Gerrit servers with the
-following basic settings:
-
-```
-[kafka]
- bootstrapServers = <kafka-host>:<kafka-port>
-
-[kafka "publisher"]
- enabled = true
-
-[kafka "subscriber"]
- enabled = true
-
-[ref-database]
- enabled = true
-
-[ref-database "zookeeper"]
- connectString = "localhost:2181"
-```
-
For more details on the configuration settings, please refer to the
[multi-site configuration documentation](src/main/resources/Documentation/config.md).
diff --git a/dockerised_local_env/gerrit-common/multi-site.config b/dockerised_local_env/gerrit-common/multi-site.config
index 04b9c2c..deec00f 100644
--- a/dockerised_local_env/gerrit-common/multi-site.config
+++ b/dockerised_local_env/gerrit-common/multi-site.config
@@ -12,14 +12,10 @@
cacheEventTopic = gerrit_cache_eviction
[kafka "subscriber"]
- enabled = true
pollingIntervalMs = 1000
KafkaProp-enableAutoCommit = true
KafkaProp-autoCommitIntervalMs = 1000
KafkaProp-autoOffsetReset = latest
-[kafka "publisher"]
- enabled = true
-
[ref-database "zookeeper"]
connectString = "zookeeper:2181"
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index 369f6e0..6e95e66 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -8,76 +8,13 @@
)
maven_jar(
- name = "mockito",
- artifact = "org.mockito:mockito-core:2.27.0",
- sha1 = "835fc3283b481f4758b8ef464cd560c649c08b00",
- deps = [
- "@byte-buddy//jar",
- "@byte-buddy-agent//jar",
- "@objenesis//jar",
- ],
- )
-
- BYTE_BUDDY_VER = "1.9.10"
-
- maven_jar(
- name = "byte-buddy",
- artifact = "net.bytebuddy:byte-buddy:" + BYTE_BUDDY_VER,
- sha1 = "211a2b4d3df1eeef2a6cacf78d74a1f725e7a840",
+ name = "global-refdb",
+ artifact = "com.gerritforge:global-refdb:0.1.1",
+ sha1 = "d6ab59906db7b20a52c8994502780b2a6ab23872",
)
maven_jar(
- name = "byte-buddy-agent",
- artifact = "net.bytebuddy:byte-buddy-agent:" + BYTE_BUDDY_VER,
- sha1 = "9674aba5ee793e54b864952b001166848da0f26b",
- )
-
- maven_jar(
- name = "objenesis",
- artifact = "org.objenesis:objenesis:2.6",
- sha1 = "639033469776fd37c08358c6b92a4761feb2af4b",
- )
-
- maven_jar(
- name = "kafka-client",
- artifact = "org.apache.kafka:kafka-clients:2.1.0",
- sha1 = "34d9983705c953b97abb01e1cd04647f47272fe5",
- )
-
- maven_jar(
- name = "testcontainers-kafka",
- artifact = "org.testcontainers:kafka:1.11.3",
- sha1 = "932d1baa2541f218b1b44a0546ae83d530011468",
- )
-
- CURATOR_VER = "4.2.0"
-
- maven_jar(
- name = "curator-test",
- artifact = "org.apache.curator:curator-test:" + CURATOR_VER,
- sha1 = "98ac2dd69b8c07dcaab5e5473f93fdb9e320cd73",
- )
-
- maven_jar(
- name = "curator-framework",
- artifact = "org.apache.curator:curator-framework:" + CURATOR_VER,
- sha1 = "5b1cc87e17b8fe4219b057f6025662a693538861",
- )
-
- maven_jar(
- name = "curator-recipes",
- artifact = "org.apache.curator:curator-recipes:" + CURATOR_VER,
- sha1 = "7f775be5a7062c2477c51533b9d008f70411ba8e",
- )
-
- maven_jar(
- name = "curator-client",
- artifact = "org.apache.curator:curator-client:" + CURATOR_VER,
- sha1 = "d5d50930b8dd189f92c40258a6ba97675fea3e15",
- )
-
- maven_jar(
- name = "zookeeper",
- artifact = "org.apache.zookeeper:zookeeper:3.4.14",
- sha1 = "c114c1e1c8172a7cd3f6ae39209a635f7a06c1a1",
+ name = "events-broker",
+ artifact = "com.gerritforge:events-broker:3.0.5",
+ sha1 = "7abf72d2252f975baff666fbbf28b7036767aa81",
)
diff --git a/setup_local_env/configs/gerrit.config b/setup_local_env/configs/gerrit.config
index 18eeca4..6092cc1 100644
--- a/setup_local_env/configs/gerrit.config
+++ b/setup_local_env/configs/gerrit.config
@@ -2,8 +2,9 @@
basePath = git
serverId = 69ec38f0-350e-4d9c-96d4-bc956f2faaac
canonicalWebUrl = $GERRIT_CANONICAL_WEB_URL
+ installModule = com.gerritforge.gerrit.eventbroker.BrokerApiModule # events-broker module to setup BrokerApi dynamic item
installModule = com.googlesource.gerrit.plugins.multisite.Module # multi-site needs to be a gerrit lib
-
+ installDbModule = com.googlesource.gerrit.plugins.multisite.GitModule
[database]
type = h2
database = $LOCATION_TEST_SITE/db/ReviewDB
@@ -37,3 +38,12 @@
allowRemoteAdmin = true
[plugin "websession-flatfile"]
directory = $FAKE_NFS
+[plugin "kafka-events"]
+ bootstrapServers = localhost:$KAFKA_PORT
+ groupId = $KAFKA_GROUP_ID
+ numberOfSubscribers = 5
+ securityProtocol = PLAINTEXT
+ pollingIntervalMs = 1000
+ enableAutoCommit = true
+ autoCommitIntervalMs = 1000
+ autoOffsetReset = latest
diff --git a/setup_local_env/configs/multi-site.config b/setup_local_env/configs/multi-site.config
index ed9e6ad..442c37e 100644
--- a/setup_local_env/configs/multi-site.config
+++ b/setup_local_env/configs/multi-site.config
@@ -1,20 +1,9 @@
[index]
maxTries = 50
retryInterval = 30000
-[kafka]
- bootstrapServers = localhost:$KAFKA_PORT
- securityProtocol = PLAINTEXT
- indexEventTopic = gerrit_index
- streamEventTopic = gerrit_stream
- projectListEventTopic = gerrit_list_project
- cacheEventTopic = gerrit_cache_eviction
-[kafka "subscriber"]
- enabled = true
- pollingIntervalMs = 1000
- KafkaProp-enableAutoCommit = true
- KafkaProp-autoCommitIntervalMs = 1000
- KafkaProp-autoOffsetReset = latest
-[kafka "publisher"]
- enabled = true
-[ref-database "zookeeper"]
- connectString = localhost:$ZK_PORT
+
+[broker]
+ indexEventTopic = gerrit_index
+ streamEventTopic = gerrit_stream
+ projectListEventTopic = gerrit_list_project
+ cacheEventTopic = gerrit_cache_eviction
diff --git a/setup_local_env/configs/zookeeper.config b/setup_local_env/configs/zookeeper.config
new file mode 100644
index 0000000..2c84a05
--- /dev/null
+++ b/setup_local_env/configs/zookeeper.config
@@ -0,0 +1,2 @@
+[ref-database "zookeeper"]
+ connectString = localhost:$ZK_PORT
\ No newline at end of file
diff --git a/setup_local_env/setup.sh b/setup_local_env/setup.sh
index 94443df..2125614 100755
--- a/setup_local_env/setup.sh
+++ b/setup_local_env/setup.sh
@@ -18,250 +18,253 @@
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
function check_application_requirements {
- type haproxy >/dev/null 2>&1 || { echo >&2 "Require haproxy but it's not installed. Aborting."; exit 1; }
- type java >/dev/null 2>&1 || { echo >&2 "Require java but it's not installed. Aborting."; exit 1; }
- type docker >/dev/null 2>&1 || { echo >&2 "Require docker but it's not installed. Aborting."; exit 1; }
- type docker-compose >/dev/null 2>&1 || { echo >&2 "Require docker-compose but it's not installed. Aborting."; exit 1; }
- type wget >/dev/null 2>&1 || { echo >&2 "Require wget but it's not installed. Aborting."; exit 1; }
- type envsubst >/dev/null 2>&1 || { echo >&2 "Require envsubst but it's not installed. Aborting."; exit 1; }
- type openssl >/dev/null 2>&1 || { echo >&2 "Require openssl but it's not installed. Aborting."; exit 1; }
+ type haproxy >/dev/null 2>&1 || { echo >&2 "Require haproxy but it's not installed. Aborting."; exit 1; }
+ type java >/dev/null 2>&1 || { echo >&2 "Require java but it's not installed. Aborting."; exit 1; }
+ type docker >/dev/null 2>&1 || { echo >&2 "Require docker but it's not installed. Aborting."; exit 1; }
+ type docker-compose >/dev/null 2>&1 || { echo >&2 "Require docker-compose but it's not installed. Aborting."; exit 1; }
+ type wget >/dev/null 2>&1 || { echo >&2 "Require wget but it's not installed. Aborting."; exit 1; }
+ type envsubst >/dev/null 2>&1 || { echo >&2 "Require envsubst but it's not installed. Aborting."; exit 1; }
+ type openssl >/dev/null 2>&1 || { echo >&2 "Require openssl but it's not installed. Aborting."; exit 1; }
}
function get_replication_url {
- REPLICATION_LOCATION_TEST_SITE=$1
- REPLICATION_HOSTNAME=$2
- USER=$REPLICATION_SSH_USER
+ REPLICATION_LOCATION_TEST_SITE=$1
+ REPLICATION_HOSTNAME=$2
+ USER=$REPLICATION_SSH_USER
- if [ "$REPLICATION_TYPE" = "file" ];then
- echo "url = file://$REPLICATION_LOCATION_TEST_SITE/git/#{name}#.git"
- elif [ "$REPLICATION_TYPE" = "ssh" ];then
- echo "url = ssh://$USER@$REPLICATION_HOSTNAME:$REPLICATION_LOCATION_TEST_SITE/git/#{name}#.git"
- fi
+ if [ "$REPLICATION_TYPE" = "file" ];then
+ echo "url = file://$REPLICATION_LOCATION_TEST_SITE/git/#{name}#.git"
+ elif [ "$REPLICATION_TYPE" = "ssh" ];then
+ echo "url = ssh://$USER@$REPLICATION_HOSTNAME:$REPLICATION_LOCATION_TEST_SITE/git/#{name}#.git"
+ fi
}
function deploy_tls_certificates {
- echo "Deplying certificates in $HA_PROXY_CERTIFICATES_DIR..."
- openssl req -new -newkey rsa:2048 -x509 -sha256 -days 365 -nodes \
- -out $HA_PROXY_CERTIFICATES_DIR/MyCertificate.crt \
- -keyout $HA_PROXY_CERTIFICATES_DIR/GerritLocalKey.key \
- -subj "/C=GB/ST=London/L=London/O=Gerrit Org/OU=IT Department/CN=localhost"
- cat $HA_PROXY_CERTIFICATES_DIR/MyCertificate.crt $HA_PROXY_CERTIFICATES_DIR/GerritLocalKey.key | tee $HA_PROXY_CERTIFICATES_DIR/GerritLocalKey.pem
+ echo "Deplying certificates in $HA_PROXY_CERTIFICATES_DIR..."
+ openssl req -new -newkey rsa:2048 -x509 -sha256 -days 365 -nodes \
+ -out $HA_PROXY_CERTIFICATES_DIR/MyCertificate.crt \
+ -keyout $HA_PROXY_CERTIFICATES_DIR/GerritLocalKey.key \
+ -subj "/C=GB/ST=London/L=London/O=Gerrit Org/OU=IT Department/CN=localhost"
+ cat $HA_PROXY_CERTIFICATES_DIR/MyCertificate.crt $HA_PROXY_CERTIFICATES_DIR/GerritLocalKey.key | tee $HA_PROXY_CERTIFICATES_DIR/GerritLocalKey.pem
}
function copy_config_files {
- for file in `ls $SCRIPT_DIR/configs/*.config`
- do
- file_name=`basename $file`
+ for file in `ls $SCRIPT_DIR/configs/*.config`
+ do
+ file_name=`basename $file`
- CONFIG_TEST_SITE=$1
- export GERRIT_HTTPD_PORT=$2
- export LOCATION_TEST_SITE=$3
- export GERRIT_SSHD_PORT=$4
- export REPLICATION_HTTPD_PORT=$5
- export REPLICATION_LOCATION_TEST_SITE=$6
- export GERRIT_HOSTNAME=$7
- export REPLICATION_HOSTNAME=$8
- export REMOTE_DEBUG_PORT=$9
- export REPLICATION_URL=$(get_replication_url $REPLICATION_LOCATION_TEST_SITE $REPLICATION_HOSTNAME)
+ CONFIG_TEST_SITE=$1
+ export GERRIT_HTTPD_PORT=$2
+ export LOCATION_TEST_SITE=$3
+ export GERRIT_SSHD_PORT=$4
+ export REPLICATION_HTTPD_PORT=$5
+ export REPLICATION_LOCATION_TEST_SITE=$6
+ export GERRIT_HOSTNAME=$7
+ export REPLICATION_HOSTNAME=$8
+ export REMOTE_DEBUG_PORT=$9
+ export KAFKA_GROUP_ID=${10}
+ export REPLICATION_URL=$(get_replication_url $REPLICATION_LOCATION_TEST_SITE $REPLICATION_HOSTNAME)
- echo "Replacing variables for file $file and copying to $CONFIG_TEST_SITE/$file_name"
+ echo "Replacing variables for file $file and copying to $CONFIG_TEST_SITE/$file_name"
- cat $file | envsubst | sed 's/#{name}#/${name}/g' > $CONFIG_TEST_SITE/$file_name
- done
+ cat $file | envsubst | sed 's/#{name}#/${name}/g' > $CONFIG_TEST_SITE/$file_name
+ done
}
function start_ha_proxy {
- export HA_GERRIT_CANONICAL_HOSTNAME=$GERRIT_CANONICAL_HOSTNAME
- export HA_GERRIT_CANONICAL_PORT=$GERRIT_CANONICAL_PORT
+ export HA_GERRIT_CANONICAL_HOSTNAME=$GERRIT_CANONICAL_HOSTNAME
+ export HA_GERRIT_CANONICAL_PORT=$GERRIT_CANONICAL_PORT
- export HA_HTTPS_BIND=$HTTPS_BIND
+ export HA_HTTPS_BIND=$HTTPS_BIND
- export HA_GERRIT_SITE1_HOSTNAME=$GERRIT_1_HOSTNAME
- export HA_GERRIT_SITE2_HOSTNAME=$GERRIT_2_HOSTNAME
- export HA_GERRIT_SITE1_HTTPD_PORT=$GERRIT_1_HTTPD_PORT
- export HA_GERRIT_SITE2_HTTPD_PORT=$GERRIT_2_HTTPD_PORT
+ export HA_GERRIT_SITE1_HOSTNAME=$GERRIT_1_HOSTNAME
+ export HA_GERRIT_SITE2_HOSTNAME=$GERRIT_2_HOSTNAME
+ export HA_GERRIT_SITE1_HTTPD_PORT=$GERRIT_1_HTTPD_PORT
+ export HA_GERRIT_SITE2_HTTPD_PORT=$GERRIT_2_HTTPD_PORT
- export HA_GERRIT_SITE1_SSHD_PORT=$GERRIT_1_SSHD_PORT
- export HA_GERRIT_SITE2_SSHD_PORT=$GERRIT_2_SSHD_PORT
+ export HA_GERRIT_SITE1_SSHD_PORT=$GERRIT_1_SSHD_PORT
+ export HA_GERRIT_SITE2_SSHD_PORT=$GERRIT_2_SSHD_PORT
- cat $SCRIPT_DIR/haproxy-config/haproxy.cfg | envsubst > $HA_PROXY_CONFIG_DIR/haproxy.cfg
+ cat $SCRIPT_DIR/haproxy-config/haproxy.cfg | envsubst > $HA_PROXY_CONFIG_DIR/haproxy.cfg
- echo "Starting HA-PROXY..."
- echo "THE SCRIPT LOCATION $SCRIPT_DIR"
- echo "THE HA SCRIPT_LOCATION $HA_SCRIPT_DIR"
- haproxy -f $HA_PROXY_CONFIG_DIR/haproxy.cfg &
+ echo "Starting HA-PROXY..."
+ echo "THE SCRIPT LOCATION $SCRIPT_DIR"
+ echo "THE HA SCRIPT_LOCATION $HA_SCRIPT_DIR"
+ haproxy -f $HA_PROXY_CONFIG_DIR/haproxy.cfg &
}
function deploy_config_files {
- # KAFKA configuration
- export KAFKA_PORT=9092
+ # KAFKA configuration
+ export KAFKA_PORT=9092
- # ZK configuration
- export ZK_PORT=2181
+ # ZK configuration
+ export ZK_PORT=2181
- # SITE 1
- GERRIT_SITE1_HOSTNAME=$1
- GERRIT_SITE1_HTTPD_PORT=$2
- GERRIT_SITE1_SSHD_PORT=$3
- CONFIG_TEST_SITE_1=$LOCATION_TEST_SITE_1/etc
- GERRIT_SITE1_REMOTE_DEBUG_PORT="5005"
- # SITE 2
- GERRIT_SITE2_HOSTNAME=$4
- GERRIT_SITE2_HTTPD_PORT=$5
- GERRIT_SITE2_SSHD_PORT=$6
- CONFIG_TEST_SITE_2=$LOCATION_TEST_SITE_2/etc
- GERRIT_SITE2_REMOTE_DEBUG_PORT="5006"
+ # SITE 1
+ GERRIT_SITE1_HOSTNAME=$1
+ GERRIT_SITE1_HTTPD_PORT=$2
+ GERRIT_SITE1_SSHD_PORT=$3
+ CONFIG_TEST_SITE_1=$LOCATION_TEST_SITE_1/etc
+ GERRIT_SITE1_REMOTE_DEBUG_PORT="5005"
+ GERRIT_SITE1_KAFKA_GROUP_ID="instance-1"
+ # SITE 2
+ GERRIT_SITE2_HOSTNAME=$4
+ GERRIT_SITE2_HTTPD_PORT=$5
+ GERRIT_SITE2_SSHD_PORT=$6
+ CONFIG_TEST_SITE_2=$LOCATION_TEST_SITE_2/etc
+ GERRIT_SITE2_REMOTE_DEBUG_PORT="5006"
+ GERRIT_SITE2_KAFKA_GROUP_ID="instance-2"
- # Set config SITE1
- copy_config_files $CONFIG_TEST_SITE_1 $GERRIT_SITE1_HTTPD_PORT $LOCATION_TEST_SITE_1 $GERRIT_SITE1_SSHD_PORT $GERRIT_SITE2_HTTPD_PORT $LOCATION_TEST_SITE_2 $GERRIT_SITE1_HOSTNAME $GERRIT_SITE2_HOSTNAME $GERRIT_SITE1_REMOTE_DEBUG_PORT
+ # Set config SITE1
+ copy_config_files $CONFIG_TEST_SITE_1 $GERRIT_SITE1_HTTPD_PORT $LOCATION_TEST_SITE_1 $GERRIT_SITE1_SSHD_PORT $GERRIT_SITE2_HTTPD_PORT $LOCATION_TEST_SITE_2 $GERRIT_SITE1_HOSTNAME $GERRIT_SITE2_HOSTNAME $GERRIT_SITE1_REMOTE_DEBUG_PORT $GERRIT_SITE1_KAFKA_GROUP_ID
- # Set config SITE2
- copy_config_files $CONFIG_TEST_SITE_2 $GERRIT_SITE2_HTTPD_PORT $LOCATION_TEST_SITE_2 $GERRIT_SITE2_SSHD_PORT $GERRIT_SITE1_HTTPD_PORT $LOCATION_TEST_SITE_1 $GERRIT_SITE1_HOSTNAME $GERRIT_SITE2_HOSTNAME $GERRIT_SITE2_REMOTE_DEBUG_PORT
+ # Set config SITE2
+ copy_config_files $CONFIG_TEST_SITE_2 $GERRIT_SITE2_HTTPD_PORT $LOCATION_TEST_SITE_2 $GERRIT_SITE2_SSHD_PORT $GERRIT_SITE1_HTTPD_PORT $LOCATION_TEST_SITE_1 $GERRIT_SITE1_HOSTNAME $GERRIT_SITE2_HOSTNAME $GERRIT_SITE2_REMOTE_DEBUG_PORT $GERRIT_SITE2_KAFKA_GROUP_ID
}
function cleanup_environment {
- echo "Killing existing HA-PROXY setup"
- kill $(ps -ax | grep haproxy | grep "gerrit_setup/ha-proxy-config" | awk '{print $1}') 2> /dev/null
- echo "Stoping kafka and zk"
- docker-compose -f $SCRIPT_DIR/docker-compose.kafka-broker.yaml down 2> /dev/null
+ echo "Killing existing HA-PROXY setup"
+ kill $(ps -ax | grep haproxy | grep "gerrit_setup/ha-proxy-config" | awk '{print $1}') 2> /dev/null
+ echo "Stoping kafka and zk"
+ docker-compose -f $SCRIPT_DIR/docker-compose.kafka-broker.yaml down 2> /dev/null
- echo "Stoping GERRIT instances"
- $1/bin/gerrit.sh stop 2> /dev/null
- $2/bin/gerrit.sh stop 2> /dev/null
+ echo "Stoping GERRIT instances"
+ $1/bin/gerrit.sh stop 2> /dev/null
+ $2/bin/gerrit.sh stop 2> /dev/null
- echo "REMOVING setup directory $3"
- rm -rf $3 2> /dev/null
+ echo "REMOVING setup directory $3"
+ rm -rf $3 2> /dev/null
}
function check_if_kafka_is_running {
- echo $(docker inspect kafka_test_node 2> /dev/null | grep '"Running": true' | wc -l)
+ echo $(docker inspect kafka_test_node 2> /dev/null | grep '"Running": true' | wc -l)
}
while [ $# -ne 0 ]
do
case "$1" in
"--help" )
- echo "Usage: sh $0 [--option $value]"
- echo
- echo "[--release-war-file] Location to release.war file"
- echo "[--multisite-lib-file] Location to lib multi-site.jar file"
- echo
- echo "[--new-deployment] Cleans up previous gerrit deployment and re-installs it. default true"
- echo "[--get-websession-plugin] Download websession-flatfile plugin from CI lastSuccessfulBuild; default true"
- echo "[--deployment-location] Base location for the test deployment; default /tmp"
- echo
- echo "[--gerrit-canonical-host] The default host for Gerrit to be accessed through; default localhost"
- echo "[--gerrit-canonical-port] The default port for Gerrit to be accessed throug; default 8080"
- echo
- echo "[--gerrit-ssh-advertised-port] Gerrit Instance 1 sshd port; default 29418"
- echo
- echo "[--gerrit1-httpd-port] Gerrit Instance 1 http port; default 18080"
- echo "[--gerrit1-sshd-port] Gerrit Instance 1 sshd port; default 39418"
- echo
- echo "[--gerrit2-httpd-port] Gerrit Instance 2 http port; default 18081"
- echo "[--gerrit2-sshd-port] Gerrit Instance 2 sshd port; default 49418"
- echo
- echo "[--replication-type] Options [file,ssh]; default ssh"
- echo "[--replication-ssh-user] SSH user for the replication plugin; default $(whoami)"
- echo "[--replication-delay] Replication delay across the two instances in seconds"
- echo
- echo "[--just-cleanup-env] Cleans up previous deployment; default false"
- echo
- echo "[--enabled-https] Enabled https; default true"
- echo
- exit 0
+ echo "Usage: sh $0 [--option $value]"
+ echo
+ echo "[--release-war-file] Location to release.war file"
+ echo "[--multisite-lib-file] Location to lib multi-site.jar file"
+ echo
+ echo "[--new-deployment] Cleans up previous gerrit deployment and re-installs it. default true"
+ echo "[--get-websession-plugin] Download websession-broker plugin from CI lastSuccessfulBuild; default true"
+ echo "[--deployment-location] Base location for the test deployment; default /tmp"
+ echo
+ echo "[--gerrit-canonical-host] The default host for Gerrit to be accessed through; default localhost"
+ echo "[--gerrit-canonical-port] The default port for Gerrit to be accessed throug; default 8080"
+ echo
+ echo "[--gerrit-ssh-advertised-port] Gerrit Instance 1 sshd port; default 29418"
+ echo
+ echo "[--gerrit1-httpd-port] Gerrit Instance 1 http port; default 18080"
+ echo "[--gerrit1-sshd-port] Gerrit Instance 1 sshd port; default 39418"
+ echo
+ echo "[--gerrit2-httpd-port] Gerrit Instance 2 http port; default 18081"
+ echo "[--gerrit2-sshd-port] Gerrit Instance 2 sshd port; default 49418"
+ echo
+ echo "[--replication-type] Options [file,ssh]; default ssh"
+ echo "[--replication-ssh-user] SSH user for the replication plugin; default $(whoami)"
+ echo "[--replication-delay] Replication delay across the two instances in seconds"
+ echo
+ echo "[--just-cleanup-env] Cleans up previous deployment; default false"
+ echo
+ echo "[--enabled-https] Enabled https; default true"
+ echo
+ exit 0
;;
"--new-deployment")
NEW_INSTALLATION=$2
- shift
- shift
+ shift
+ shift
;;
"--get-websession-plugin")
- DOWNLOAD_WEBSESSION_FLATFILE=$2
- shift
- shift
+ DOWNLOAD_WEBSESSION_PLUGIN=$2
+ shift
+ shift
;;
"--deployment-location" )
- DEPLOYMENT_LOCATION=$2
- shift
- shift
+ DEPLOYMENT_LOCATION=$2
+ shift
+ shift
;;
"--release-war-file" )
- RELEASE_WAR_FILE_LOCATION=$2
- shift
- shift
+ RELEASE_WAR_FILE_LOCATION=$2
+ shift
+ shift
;;
"--multisite-lib-file" )
- MULTISITE_LIB_LOCATION=$2
- shift
- shift
+ MULTISITE_LIB_LOCATION=$2
+ shift
+ shift
;;
"--gerrit-canonical-host" )
- export GERRIT_CANONICAL_HOSTNAME=$2
- shift
- shift
+ export GERRIT_CANONICAL_HOSTNAME=$2
+ shift
+ shift
;;
"--gerrit-canonical-port" )
- export GERRIT_CANONICAL_PORT=$2
- shift
- shift
+ export GERRIT_CANONICAL_PORT=$2
+ shift
+ shift
;;
"--gerrit-ssh-advertised-port" )
- export SSH_ADVERTISED_PORT=$2
- shift
- shift
+ export SSH_ADVERTISED_PORT=$2
+ shift
+ shift
;;
"--gerrit1-httpd-port" )
- GERRIT_1_HTTPD_PORT=$2
- shift
- shift
+ GERRIT_1_HTTPD_PORT=$2
+ shift
+ shift
;;
"--gerrit2-httpd-port" )
- GERRIT_2_HTTPD_PORT=$2
- shift
- shift
+ GERRIT_2_HTTPD_PORT=$2
+ shift
+ shift
;;
"--gerrit1-sshd-port" )
- GERRIT_1_SSHD_PORT=$2
- shift
- shift
+ GERRIT_1_SSHD_PORT=$2
+ shift
+ shift
;;
"--gerrit2-sshd-port" )
- GERRIT_2_SSHD_PORT=$2
- shift
- shift
+ GERRIT_2_SSHD_PORT=$2
+ shift
+ shift
;;
"--replication-ssh-user" )
- export REPLICATION_SSH_USER=$2
- shift
- shift
+ export REPLICATION_SSH_USER=$2
+ shift
+ shift
;;
"--replication-type")
- export REPLICATION_TYPE=$2
- shift
- shift
+ export REPLICATION_TYPE=$2
+ shift
+ shift
;;
"--replication-delay")
- export REPLICATION_DELAY_SEC=$2
- shift
- shift
+ export REPLICATION_DELAY_SEC=$2
+ shift
+ shift
;;
"--just-cleanup-env" )
- JUST_CLEANUP_ENV=$2
- shift
- shift
+ JUST_CLEANUP_ENV=$2
+ shift
+ shift
;;
"--enabled-https" )
- HTTPS_ENABLED=$2
- shift
- shift
+ HTTPS_ENABLED=$2
+ shift
+ shift
;;
- * )
- echo "Unknown option argument: $1"
- shift
- shift
+ * )
+ echo "Unknown option argument: $1"
+ shift
+ shift
;;
esac
done
@@ -271,7 +274,7 @@
# Defaults
NEW_INSTALLATION=${NEW_INSTALLATION:-"true"}
-DOWNLOAD_WEBSESSION_FLATFILE=${DOWNLOAD_WEBSESSION_FLATFILE:-"true"}
+DOWNLOAD_WEBSESSION_PLUGIN=${DOWNLOAD_WEBSESSION_PLUGIN:-"true"}
DEPLOYMENT_LOCATION=${DEPLOYMENT_LOCATION:-"/tmp"}
export GERRIT_CANONICAL_HOSTNAME=${GERRIT_CANONICAL_HOSTNAME:-"localhost"}
export GERRIT_CANONICAL_PORT=${GERRIT_CANONICAL_PORT:-"8080"}
@@ -300,93 +303,117 @@
export FAKE_NFS=$COMMON_LOCATION/fake_nfs
if [ "$JUST_CLEANUP_ENV" = "true" ];then
- cleanup_environment $LOCATION_TEST_SITE_1 $LOCATION_TEST_SITE_2 $COMMON_LOCATION
- exit 0
+ cleanup_environment $LOCATION_TEST_SITE_1 $LOCATION_TEST_SITE_2 $COMMON_LOCATION
+ exit 0
fi
if [ -z $RELEASE_WAR_FILE_LOCATION ];then
- echo "A release.war file is required. Usage: sh $0 --release-war-file /path/to/release.war"
- exit 1
+ echo "A release.war file is required. Usage: sh $0 --release-war-file /path/to/release.war"
+ exit 1
else
- cp -f $RELEASE_WAR_FILE_LOCATION $DEPLOYMENT_LOCATION/gerrit.war >/dev/null 2>&1 || { echo >&2 "$RELEASE_WAR_FILE_LOCATION: Not able to copy the file. Aborting"; exit 1; }
+ cp -f $RELEASE_WAR_FILE_LOCATION $DEPLOYMENT_LOCATION/gerrit.war >/dev/null 2>&1 || { echo >&2 "$RELEASE_WAR_FILE_LOCATION: Not able to copy the file. Aborting"; exit 1; }
fi
if [ -z $MULTISITE_LIB_LOCATION ];then
- echo "The multi-site library is required. Usage: sh $0 --multisite-lib-file /path/to/multi-site.jar"
- exit 1
+ echo "The multi-site library is required. Usage: sh $0 --multisite-lib-file /path/to/multi-site.jar"
+ exit 1
else
- cp -f $MULTISITE_LIB_LOCATION $DEPLOYMENT_LOCATION/multi-site.jar >/dev/null 2>&1 || { echo >&2 "$MULTISITE_LIB_LOCATION: Not able to copy the file. Aborting"; exit 1; }
+ cp -f $MULTISITE_LIB_LOCATION $DEPLOYMENT_LOCATION/multi-site.jar >/dev/null 2>&1 || { echo >&2 "$MULTISITE_LIB_LOCATION: Not able to copy the file. Aborting"; exit 1; }
fi
-if [ $DOWNLOAD_WEBSESSION_FLATFILE = "true" ];then
- echo "Downloading websession-flatfile plugin stable 2.16"
- wget https://gerrit-ci.gerritforge.com/view/Plugins-stable-2.16/job/plugin-websession-flatfile-bazel-master-stable-2.16/lastSuccessfulBuild/artifact/bazel-bin/plugins/websession-flatfile/websession-flatfile.jar \
- -O $DEPLOYMENT_LOCATION/websession-flatfile.jar || { echo >&2 "Cannot download websession-flatfile plugin: Check internet connection. Abort\
+if [ $DOWNLOAD_WEBSESSION_PLUGIN = "true" ];then
+ echo "Downloading websession-broker plugin stable 3.0"
+ wget https://gerrit-ci.gerritforge.com/view/Plugins-stable-3.0/job/plugin-websession-broker-bazel-stable-3.0/lastSuccessfulBuild/artifact/bazel-bin/plugins/websession-broker/websession-broker.jar \
+ -O $DEPLOYMENT_LOCATION/websession-broker.jar || { echo >&2 "Cannot download websession-broker plugin: Check internet connection. Abort\
ing"; exit 1; }
- wget https://gerrit-ci.gerritforge.com/view/Plugins-stable-2.16/job/plugin-healthcheck-bazel-stable-2.16/lastSuccessfulBuild/artifact/bazel-bin/plugins/healthcheck/healthcheck.jar \
- -O $DEPLOYMENT_LOCATION/healthcheck.jar || { echo >&2 "Cannot download healthcheck plugin: Check internet connection. Abort\
+ wget https://gerrit-ci.gerritforge.com/view/Plugins-stable-3.0/job/plugin-healthcheck-bazel-stable-3.0/lastSuccessfulBuild/artifact/bazel-bin/plugins/healthcheck/healthcheck.jar \
+ -O $DEPLOYMENT_LOCATION/healthcheck.jar || { echo >&2 "Cannot download healthcheck plugin: Check internet connection. Abort\
ing"; exit 1; }
else
- echo "Without the websession-flatfile; user login via haproxy will fail."
+ echo "Without the websession-broker; user login via haproxy will fail."
fi
+echo "Downloading zookeeper plugin stable 3.0"
+ wget https://gerrit-ci.gerritforge.com/view/Plugins-stable-3.0/job/plugin-zookeeper-gh-bazel-stable-3.0/lastSuccessfulBuild/artifact/bazel-bin/plugins/zookeeper/zookeeper.jar \
+ -O $DEPLOYMENT_LOCATION/zookeeper.jar || { echo >&2 "Cannot download zookeeper plugin: Check internet connection. Abort\
+ing"; exit 1; }
+
+echo "Downloading events-broker library stable 3.0"
+ wget https://repo1.maven.org/maven2/com/gerritforge/events-broker/3.0.5/events-broker-3.0.5.jar \
+ -O $DEPLOYMENT_LOCATION/events-broker.jar || { echo >&2 "Cannot download events-broker library: Check internet connection. Abort\
+ing"; exit 1; }
+
+echo "Downloading kafka-events plugin stable 3.0"
+ wget https://gerrit-ci.gerritforge.com/view/Plugins-stable-3.0/job/plugin-kafka-events-bazel-stable-3.0/lastSuccessfulBuild/artifact/bazel-bin/plugins/kafka-events/kafka-events.jar \
+ -O $DEPLOYMENT_LOCATION/kafka-events.jar || { echo >&2 "Cannot download kafka-events plugin: Check internet connection. Abort\
+ing"; exit 1; }
+
if [ "$REPLICATION_TYPE" = "ssh" ];then
- echo "Using 'SSH' replication type"
- echo "Make sure ~/.ssh/authorized_keys and ~/.ssh/known_hosts are configured correctly"
+ echo "Using 'SSH' replication type"
+ echo "Make sure ~/.ssh/authorized_keys and ~/.ssh/known_hosts are configured correctly"
fi
if [ "$HTTPS_ENABLED" = "true" ];then
- export HTTP_PROTOCOL="https"
- export GERRIT_CANONICAL_WEB_URL="$HTTP_PROTOCOL://$GERRIT_CANONICAL_HOSTNAME/"
- export HTTPS_BIND="bind *:443 ssl crt $HA_PROXY_CONFIG_DIR/certificates/GerritLocalKey.pem"
- HTTPS_CLONE_MSG="Using self-signed certificates, to clone via https - 'git config --global http.sslVerify false'"
+ export HTTP_PROTOCOL="https"
+ export GERRIT_CANONICAL_WEB_URL="$HTTP_PROTOCOL://$GERRIT_CANONICAL_HOSTNAME/"
+ export HTTPS_BIND="bind *:443 ssl crt $HA_PROXY_CONFIG_DIR/certificates/GerritLocalKey.pem"
+ HTTPS_CLONE_MSG="Using self-signed certificates, to clone via https - 'git config --global http.sslVerify false'"
else
- export HTTP_PROTOCOL="http"
- export GERRIT_CANONICAL_WEB_URL="$HTTP_PROTOCOL://$GERRIT_CANONICAL_HOSTNAME:$GERRIT_CANONICAL_PORT/"
+ export HTTP_PROTOCOL="http"
+ export GERRIT_CANONICAL_WEB_URL="$HTTP_PROTOCOL://$GERRIT_CANONICAL_HOSTNAME:$GERRIT_CANONICAL_PORT/"
fi
# New installation
if [ $NEW_INSTALLATION = "true" ]; then
- cleanup_environment $LOCATION_TEST_SITE_1 $LOCATION_TEST_SITE_2 $COMMON_LOCATION
+ cleanup_environment $LOCATION_TEST_SITE_1 $LOCATION_TEST_SITE_2 $COMMON_LOCATION
- echo "Setting up directories"
- mkdir -p $LOCATION_TEST_SITE_1 $LOCATION_TEST_SITE_2 $HA_PROXY_CERTIFICATES_DIR $FAKE_NFS
- java -jar $DEPLOYMENT_LOCATION/gerrit.war init --batch --no-auto-start --install-all-plugins --dev -d $LOCATION_TEST_SITE_1
+ echo "Setting up directories"
+ mkdir -p $LOCATION_TEST_SITE_1 $LOCATION_TEST_SITE_2 $HA_PROXY_CERTIFICATES_DIR $FAKE_NFS
+ java -jar $DEPLOYMENT_LOCATION/gerrit.war init --batch --no-auto-start --install-all-plugins --dev -d $LOCATION_TEST_SITE_1
- # Deploying TLS certificates
- if [ "$HTTPS_ENABLED" = "true" ];then deploy_tls_certificates;fi
+ # Deploying TLS certificates
+ if [ "$HTTPS_ENABLED" = "true" ];then deploy_tls_certificates;fi
- echo "Copy multi-site library to lib directory"
- cp -f $DEPLOYMENT_LOCATION/multi-site.jar $LOCATION_TEST_SITE_1/lib/multi-site.jar
+ echo "Copy multi-site library to lib directory"
+ cp -f $DEPLOYMENT_LOCATION/multi-site.jar $LOCATION_TEST_SITE_1/lib/multi-site.jar
- echo "Copy websession-flatfile plugin"
- cp -f $DEPLOYMENT_LOCATION/websession-flatfile.jar $LOCATION_TEST_SITE_1/plugins/websession-flatfile.jar
+ echo "Copy websession-broker plugin"
+ cp -f $DEPLOYMENT_LOCATION/websession-broker.jar $LOCATION_TEST_SITE_1/plugins/websession-broker.jar
- echo "Copy healthcheck plugin"
- cp -f $DEPLOYMENT_LOCATION/healthcheck.jar $LOCATION_TEST_SITE_1/plugins/healthcheck.jar
+ echo "Copy healthcheck plugin"
+ cp -f $DEPLOYMENT_LOCATION/healthcheck.jar $LOCATION_TEST_SITE_1/plugins/healthcheck.jar
- echo "Re-indexing"
- java -jar $DEPLOYMENT_LOCATION/gerrit.war reindex -d $LOCATION_TEST_SITE_1
- # Replicating environment
- echo "Replicating environment"
- cp -fR $LOCATION_TEST_SITE_1/* $LOCATION_TEST_SITE_2
+ echo "Copy zookeeper plugin"
+ cp -f $DEPLOYMENT_LOCATION/zookeeper.jar $LOCATION_TEST_SITE_1/plugins/zookeeper.jar
- echo "Link replication plugin"
- ln -s $LOCATION_TEST_SITE_1/plugins/replication.jar $LOCATION_TEST_SITE_1/lib/replication.jar
- ln -s $LOCATION_TEST_SITE_2/plugins/replication.jar $LOCATION_TEST_SITE_2/lib/replication.jar
+ echo "Copy events broker library"
+ cp -f $DEPLOYMENT_LOCATION/events-broker.jar $LOCATION_TEST_SITE_1/lib/events-broker.jar
- echo "Link multi-site library to plugin directory"
- ln -s $LOCATION_TEST_SITE_1/lib/multi-site.jar $LOCATION_TEST_SITE_1/plugins/multi-site.jar
- ln -s $LOCATION_TEST_SITE_2/lib/multi-site.jar $LOCATION_TEST_SITE_2/plugins/multi-site.jar
+ echo "Copy kafka events plugin"
+ cp -f $DEPLOYMENT_LOCATION/kafka-events.jar $LOCATION_TEST_SITE_1/plugins/kafka-events.jar
+
+ echo "Re-indexing"
+ java -jar $DEPLOYMENT_LOCATION/gerrit.war reindex -d $LOCATION_TEST_SITE_1
+ # Replicating environment
+ echo "Replicating environment"
+ cp -fR $LOCATION_TEST_SITE_1/* $LOCATION_TEST_SITE_2
+
+ echo "Link replication plugin"
+ ln -s $LOCATION_TEST_SITE_1/plugins/replication.jar $LOCATION_TEST_SITE_1/lib/replication.jar
+ ln -s $LOCATION_TEST_SITE_2/plugins/replication.jar $LOCATION_TEST_SITE_2/lib/replication.jar
+
+ echo "Link multi-site library to plugin directory"
+ ln -s $LOCATION_TEST_SITE_1/lib/multi-site.jar $LOCATION_TEST_SITE_1/plugins/multi-site.jar
+ ln -s $LOCATION_TEST_SITE_2/lib/multi-site.jar $LOCATION_TEST_SITE_2/plugins/multi-site.jar
fi
IS_KAFKA_RUNNING=$(check_if_kafka_is_running)
if [ $IS_KAFKA_RUNNING -lt 1 ];then
- echo "Starting zk and kafka"
- docker-compose -f $SCRIPT_DIR/docker-compose.kafka-broker.yaml up -d
- echo "Waiting for kafka to start..."
- while [[ $(check_if_kafka_is_running) -lt 1 ]];do sleep 10s; done
+ echo "Starting zk and kafka"
+ docker-compose -f $SCRIPT_DIR/docker-compose.kafka-broker.yaml up -d
+ echo "Waiting for kafka to start..."
+ while [[ $(check_if_kafka_is_running) -lt 1 ]];do sleep 10s; done
fi
echo "Re-deploying configuration files"
@@ -398,8 +425,8 @@
if [[ $(ps -ax | grep haproxy | grep "gerrit_setup/ha-proxy-config" | awk '{print $1}' | wc -l) -lt 1 ]];then
- echo "Starting haproxy"
- start_ha_proxy
+ echo "Starting haproxy"
+ start_ha_proxy
fi
echo "==============================="
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/Configuration.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/Configuration.java
index ca01471..ebe28d4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/Configuration.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/Configuration.java
@@ -18,6 +18,7 @@
import static com.google.common.base.Suppliers.ofInstance;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.MoreObjects;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
@@ -49,7 +50,6 @@
static final String INSTANCE_ID_FILE = "instanceId.data";
static final String THREAD_POOL_SIZE_KEY = "threadPoolSize";
static final int DEFAULT_THREAD_POOL_SIZE = 4;
- static final String ENABLE_KEY = "enabled";
private static final String REPLICATION_CONFIG = "replication.config";
// common parameters to cache and index sections
@@ -63,6 +63,7 @@
private final Supplier<Index> index;
private final Supplier<SharedRefDatabase> sharedRefDb;
private final Supplier<Collection<Message>> replicationConfigValidation;
+ private final Supplier<Broker> broker;
private final Config multiSiteConfig;
@Inject
@@ -79,6 +80,7 @@
event = memoize(() -> new Event(lazyMultiSiteCfg));
index = memoize(() -> new Index(lazyMultiSiteCfg));
sharedRefDb = memoize(() -> new SharedRefDatabase(lazyMultiSiteCfg));
+ broker = memoize(() -> new Broker(lazyMultiSiteCfg));
}
public Config getMultiSiteConfig() {
@@ -101,6 +103,10 @@
return index.get();
}
+ public Broker broker() {
+ return broker.get();
+ }
+
public Collection<Message> validate() {
return replicationConfigValidation.get();
}
@@ -162,6 +168,7 @@
public static class SharedRefDatabase {
public static final String SECTION = "ref-database";
+ public static final String ENABLE_KEY = "enabled";
public static final String SUBSECTION_ENFORCEMENT_RULES = "enforcementRules";
private final boolean enabled;
@@ -278,6 +285,19 @@
}
}
+ public static class Broker {
+ static final String BROKER_SECTION = "broker";
+ private final Config cfg;
+
+ Broker(Supplier<Config> cfgSupplier) {
+ cfg = cfgSupplier.get();
+ }
+
+ public String getTopic(String topicKey, String defValue) {
+ return MoreObjects.firstNonNull(cfg.getString(BROKER_SECTION, null, topicKey), defValue);
+ }
+ }
+
static boolean getBoolean(
Supplier<Config> cfg, String section, String subsection, String name, boolean defaultValue) {
try {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/GerritNoteDbStatus.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/GitModule.java
similarity index 64%
rename from src/main/java/com/googlesource/gerrit/plugins/multisite/GerritNoteDbStatus.java
rename to src/main/java/com/googlesource/gerrit/plugins/multisite/GitModule.java
index ff932da..4f7205d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/GerritNoteDbStatus.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/GitModule.java
@@ -14,21 +14,22 @@
package com.googlesource.gerrit.plugins.multisite;
-import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.inject.AbstractModule;
import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.multisite.validation.ValidationModule;
-@Singleton
-public class GerritNoteDbStatus implements NoteDbStatus {
- private final NotesMigration notesMigration;
+public class GitModule extends AbstractModule {
+ private final Configuration config;
@Inject
- public GerritNoteDbStatus(NotesMigration notesMigration) {
- this.notesMigration = notesMigration;
+ public GitModule(Configuration config) {
+ this.config = config;
}
@Override
- public boolean enabled() {
- return notesMigration.commitChangeWrites();
+ protected void configure() {
+ if (config.getSharedRefDb().isEnabled()) {
+ install(new ValidationModule(config));
+ }
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jMessageLogger.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jMessageLogger.java
index db7dd63..7c88655 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jMessageLogger.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jMessageLogger.java
@@ -14,12 +14,14 @@
package com.googlesource.gerrit.plugins.multisite;
+import com.gerritforge.gerrit.eventbroker.EventGsonProvider;
+import com.gerritforge.gerrit.eventbroker.EventMessage;
import com.google.gerrit.extensions.systemstatus.ServerInformation;
import com.google.gerrit.server.util.PluginLogFile;
import com.google.gerrit.server.util.SystemLog;
+import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
import org.apache.log4j.PatternLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,15 +30,18 @@
public class Log4jMessageLogger extends PluginLogFile implements MessageLogger {
private static final String LOG_NAME = "message_log";
private final Logger msgLog;
+ private final Gson gson;
@Inject
- public Log4jMessageLogger(SystemLog systemLog, ServerInformation serverInfo) {
+ public Log4jMessageLogger(
+ SystemLog systemLog, ServerInformation serverInfo, EventGsonProvider gsonProvider) {
super(systemLog, serverInfo, LOG_NAME, new PatternLayout("[%d{ISO8601}] [%t] %-5p : %m%n"));
- msgLog = LoggerFactory.getLogger(LOG_NAME);
+ this.msgLog = LoggerFactory.getLogger(LOG_NAME);
+ this.gson = gsonProvider.get();
}
@Override
- public void log(Direction direction, SourceAwareEventWrapper event) {
- msgLog.info("{} Header[{}] Body[{}]", direction, event.getHeader(), event.getBody());
+ public void log(Direction direction, String topic, EventMessage event) {
+ msgLog.info("{} {} {}", direction, topic, gson.toJson(event));
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java
index 8830e19..4a844f7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/Log4jSharedRefLogger.java
@@ -20,9 +20,9 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.common.GitPerson;
+import com.google.gerrit.json.OutputFormat;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CommonConverters;
-import com.google.gerrit.server.OutputFormat;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.util.SystemLog;
import com.google.gson.Gson;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/MessageLogger.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/MessageLogger.java
index 8b07115..b1f3e79 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/MessageLogger.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/MessageLogger.java
@@ -14,7 +14,7 @@
package com.googlesource.gerrit.plugins.multisite;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
+import com.gerritforge.gerrit.eventbroker.EventMessage;
public interface MessageLogger {
@@ -23,5 +23,5 @@
CONSUME;
}
- public void log(Direction direction, SourceAwareEventWrapper event);
+ public void log(Direction direction, String topic, EventMessage event);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/Module.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/Module.java
index 5f4f635..708e707 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/Module.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/Module.java
@@ -14,25 +14,22 @@
package com.googlesource.gerrit.plugins.multisite;
-import com.google.common.annotations.VisibleForTesting;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDatabase;
+import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.server.config.SitePaths;
-import com.google.gson.Gson;
import com.google.inject.CreationException;
import com.google.inject.Inject;
import com.google.inject.Provides;
-import com.google.inject.ProvisionException;
+import com.google.inject.Scopes;
import com.google.inject.Singleton;
import com.google.inject.spi.Message;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerModule;
-import com.googlesource.gerrit.plugins.multisite.broker.GsonProvider;
import com.googlesource.gerrit.plugins.multisite.cache.CacheModule;
import com.googlesource.gerrit.plugins.multisite.event.EventModule;
import com.googlesource.gerrit.plugins.multisite.forwarder.ForwarderModule;
import com.googlesource.gerrit.plugins.multisite.forwarder.router.RouterModule;
import com.googlesource.gerrit.plugins.multisite.index.IndexModule;
-import com.googlesource.gerrit.plugins.multisite.validation.ValidationModule;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.NoopSharedRefDatabase;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
@@ -47,44 +44,26 @@
public class Module extends LifecycleModule {
private static final Logger log = LoggerFactory.getLogger(Module.class);
private Configuration config;
- private NoteDbStatus noteDb;
- private BrokerModule brokerModule;
- private final boolean disableGitRepositoryValidation;
@Inject
- public Module(Configuration config, NoteDbStatus noteDb, BrokerModule brokerModule) {
- this(config, noteDb, brokerModule, false);
- }
-
- // TODO: It is not possible to properly test the libModules in Gerrit.
- // Disable the Git repository validation during integration test and then build the necessary
- // support
- // in Gerrit for it.
- @VisibleForTesting
- public Module(
- Configuration config,
- NoteDbStatus noteDb,
- BrokerModule brokerModule,
- boolean disableGitRepositoryValidation) {
+ public Module(Configuration config) {
this.config = config;
- this.noteDb = noteDb;
- this.brokerModule = brokerModule;
- this.disableGitRepositoryValidation = disableGitRepositoryValidation;
}
@Override
protected void configure() {
- if (!noteDb.enabled()) {
- throw new ProvisionException(
- "Gerrit is still running on ReviewDb: please migrate to NoteDb "
- + "and then reload the multi-site plugin.");
- }
Collection<Message> validationErrors = config.validate();
if (!validationErrors.isEmpty()) {
throw new CreationException(validationErrors);
}
+ DynamicItem.itemOf(binder(), GlobalRefDatabase.class);
+ DynamicItem.bind(binder(), GlobalRefDatabase.class)
+ .to(NoopSharedRefDatabase.class)
+ .in(Scopes.SINGLETON);
+ log.info("Shared ref-db engine: none");
+
listener().to(Log4jMessageLogger.class);
bind(MessageLogger.class).to(Log4jMessageLogger.class);
@@ -100,18 +79,7 @@
install(new IndexModule());
}
- install(brokerModule);
-
install(new RouterModule());
-
- install(
- new ValidationModule(
- config, disableGitRepositoryValidation || !config.getSharedRefDb().isEnabled()));
-
- bind(Gson.class)
- .annotatedWith(BrokerGson.class)
- .toProvider(GsonProvider.class)
- .in(Singleton.class);
}
@Provides
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/NoteDbStatus.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/NoteDbStatus.java
deleted file mode 100644
index f47e503..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/NoteDbStatus.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2019 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.multisite;
-
-import com.google.inject.ImplementedBy;
-
-/** Returns the status of changes migration. */
-@ImplementedBy(GerritNoteDbStatus.class)
-public interface NoteDbStatus {
-
- /**
- * Status of NoteDb migration.
- *
- * @return true if Gerrit has been migrated to NoteDb
- */
- boolean enabled();
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginModule.java
index d445251..2eaa5d9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginModule.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2015 The Android Open Source Project
+// Copyright (C) 2019 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.
@@ -14,43 +14,37 @@
package com.googlesource.gerrit.plugins.multisite;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.extensions.events.ProjectDeletedListener;
+import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.inject.Inject;
import com.google.inject.Scopes;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApi;
-import com.googlesource.gerrit.plugins.multisite.kafka.KafkaBrokerApi;
-import com.googlesource.gerrit.plugins.multisite.kafka.KafkaBrokerModule;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.ZkValidationModule;
+import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
+import com.googlesource.gerrit.plugins.multisite.consumer.MultiSiteConsumerRunner;
+import com.googlesource.gerrit.plugins.multisite.consumer.SubscriberModule;
+import com.googlesource.gerrit.plugins.multisite.forwarder.broker.BrokerForwarderModule;
+import com.googlesource.gerrit.plugins.multisite.validation.ProjectDeletedSharedDbCleanup;
public class PluginModule extends LifecycleModule {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
private Configuration config;
- private ZkValidationModule zkValidationModule;
- private KafkaBrokerModule kafkaBrokerModule;
@Inject
- public PluginModule(
- Configuration config,
- ZkValidationModule zkValidationModule,
- KafkaBrokerModule kafkaBrokerModule) {
+ public PluginModule(Configuration config) {
this.config = config;
- this.zkValidationModule = zkValidationModule;
- this.kafkaBrokerModule = kafkaBrokerModule;
}
@Override
protected void configure() {
+ bind(BrokerApiWrapper.class).in(Scopes.SINGLETON);
+ install(new SubscriberModule());
+
+ install(new BrokerForwarderModule());
+ listener().to(MultiSiteConsumerRunner.class);
+
if (config.getSharedRefDb().isEnabled()) {
- logger.atInfo().log("Shared ref-db engine: Zookeeper");
- install(zkValidationModule);
+ listener().to(PluginStartup.class);
+ DynamicSet.bind(binder(), ProjectDeletedListener.class)
+ .to(ProjectDeletedSharedDbCleanup.class);
}
-
- DynamicItem.bind(binder(), BrokerApi.class).to(KafkaBrokerApi.class).in(Scopes.SINGLETON);
- listener().to(KafkaBrokerApi.class);
-
- install(kafkaBrokerModule);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/GerritNoteDbStatus.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginStartup.java
similarity index 60%
copy from src/main/java/com/googlesource/gerrit/plugins/multisite/GerritNoteDbStatus.java
copy to src/main/java/com/googlesource/gerrit/plugins/multisite/PluginStartup.java
index ff932da..33b54d2 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/GerritNoteDbStatus.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/PluginStartup.java
@@ -14,21 +14,25 @@
package com.googlesource.gerrit.plugins.multisite;
-import com.google.gerrit.server.notedb.NotesMigration;
+import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import com.google.inject.Injector;
-@Singleton
-public class GerritNoteDbStatus implements NoteDbStatus {
- private final NotesMigration notesMigration;
+public class PluginStartup implements LifecycleListener {
+ private SharedRefDatabaseWrapper sharedRefDb;
+ private Injector injector;
@Inject
- public GerritNoteDbStatus(NotesMigration notesMigration) {
- this.notesMigration = notesMigration;
+ public PluginStartup(SharedRefDatabaseWrapper sharedRefDb, Injector injector) {
+ this.sharedRefDb = sharedRefDb;
+ this.injector = injector;
}
@Override
- public boolean enabled() {
- return notesMigration.commitChangeWrites();
+ public void start() {
+ injector.injectMembers(sharedRefDb);
}
+
+ @Override
+ public void stop() {}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java
index e6ebc08..9d55e43 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/SharedRefDatabaseWrapper.java
@@ -14,60 +14,70 @@
package com.googlesource.gerrit.plugins.multisite;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDatabase;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
+import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedLockException;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
-import java.io.IOException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
-public class SharedRefDatabaseWrapper implements SharedRefDatabase {
+public class SharedRefDatabaseWrapper implements GlobalRefDatabase {
- private final DynamicItem<SharedRefDatabase> sharedRefDbDynamicItem;
+ @Inject(optional = true)
+ private DynamicItem<GlobalRefDatabase> sharedRefDbDynamicItem;
+
private final SharedRefLogger sharedRefLogger;
@Inject
- public SharedRefDatabaseWrapper(
- DynamicItem<SharedRefDatabase> sharedRefDbDynamicItem, SharedRefLogger sharedRefLogger) {
- this.sharedRefDbDynamicItem = sharedRefDbDynamicItem;
+ public SharedRefDatabaseWrapper(SharedRefLogger sharedRefLogger) {
this.sharedRefLogger = sharedRefLogger;
}
+ @VisibleForTesting
+ public SharedRefDatabaseWrapper(
+ DynamicItem<GlobalRefDatabase> sharedRefDbDynamicItem, SharedRefLogger sharedRefLogger) {
+ this.sharedRefLogger = sharedRefLogger;
+ this.sharedRefDbDynamicItem = sharedRefDbDynamicItem;
+ }
+
@Override
- public boolean isUpToDate(String project, Ref ref) throws SharedLockException {
+ public boolean isUpToDate(Project.NameKey project, Ref ref) throws GlobalRefDbLockException {
return sharedRefDb().isUpToDate(project, ref);
}
@Override
- public boolean compareAndPut(String project, Ref currRef, ObjectId newRefValue)
- throws IOException {
+ public boolean compareAndPut(Project.NameKey project, Ref currRef, ObjectId newRefValue)
+ throws GlobalRefDbSystemError {
boolean succeeded = sharedRefDb().compareAndPut(project, currRef, newRefValue);
if (succeeded) {
- sharedRefLogger.logRefUpdate(project, currRef, newRefValue);
+ sharedRefLogger.logRefUpdate(project.get(), currRef, newRefValue);
}
return succeeded;
}
@Override
- public AutoCloseable lockRef(String project, String refName) throws SharedLockException {
+ public AutoCloseable lockRef(Project.NameKey project, String refName)
+ throws GlobalRefDbLockException {
AutoCloseable locker = sharedRefDb().lockRef(project, refName);
- sharedRefLogger.logLockAcquisition(project, refName);
+ sharedRefLogger.logLockAcquisition(project.get(), refName);
return locker;
}
@Override
- public boolean exists(String project, String refName) {
+ public boolean exists(Project.NameKey project, String refName) {
return sharedRefDb().exists(project, refName);
}
@Override
- public void removeProject(String project) throws IOException {
- sharedRefDb().removeProject(project);
- sharedRefLogger.logProjectDelete(project);
+ public void remove(Project.NameKey project) throws GlobalRefDbSystemError {
+ sharedRefDb().remove(project);
+ sharedRefLogger.logProjectDelete(project.get());
}
- private SharedRefDatabase sharedRefDb() {
+ private GlobalRefDatabase sharedRefDb() {
return sharedRefDbDynamicItem.get();
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/ZookeeperConfig.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/ZookeeperConfig.java
deleted file mode 100644
index 35471fa..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/ZookeeperConfig.java
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright (C) 2019 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.multisite;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Suppliers.memoize;
-import static com.google.common.base.Suppliers.ofInstance;
-
-import com.google.common.base.Strings;
-import com.google.common.base.Supplier;
-import com.google.gerrit.server.config.SitePaths;
-import java.io.IOException;
-import org.apache.commons.lang.StringUtils;
-import org.apache.curator.RetryPolicy;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.CuratorFrameworkFactory;
-import org.apache.curator.retry.BoundedExponentialBackoffRetry;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ZookeeperConfig {
- private static final Logger log = LoggerFactory.getLogger(ZookeeperConfig.class);
- public static final int defaultSessionTimeoutMs;
- public static final int defaultConnectionTimeoutMs;
- public static final String DEFAULT_ZK_CONNECT = "localhost:2181";
- private final int DEFAULT_RETRY_POLICY_BASE_SLEEP_TIME_MS = 1000;
- private final int DEFAULT_RETRY_POLICY_MAX_SLEEP_TIME_MS = 3000;
- private final int DEFAULT_RETRY_POLICY_MAX_RETRIES = 3;
- private final int DEFAULT_CAS_RETRY_POLICY_BASE_SLEEP_TIME_MS = 100;
- private final int DEFAULT_CAS_RETRY_POLICY_MAX_SLEEP_TIME_MS = 300;
- private final int DEFAULT_CAS_RETRY_POLICY_MAX_RETRIES = 3;
- private final int DEFAULT_TRANSACTION_LOCK_TIMEOUT = 1000;
-
- static {
- CuratorFrameworkFactory.Builder b = CuratorFrameworkFactory.builder();
- defaultSessionTimeoutMs = b.getSessionTimeoutMs();
- defaultConnectionTimeoutMs = b.getConnectionTimeoutMs();
- }
-
- public static final String SUBSECTION = "zookeeper";
- public static final String KEY_CONNECT_STRING = "connectString";
- public static final String KEY_SESSION_TIMEOUT_MS = "sessionTimeoutMs";
- public static final String KEY_CONNECTION_TIMEOUT_MS = "connectionTimeoutMs";
- public static final String KEY_RETRY_POLICY_BASE_SLEEP_TIME_MS = "retryPolicyBaseSleepTimeMs";
- public static final String KEY_RETRY_POLICY_MAX_SLEEP_TIME_MS = "retryPolicyMaxSleepTimeMs";
- public static final String KEY_RETRY_POLICY_MAX_RETRIES = "retryPolicyMaxRetries";
- public static final String KEY_ROOT_NODE = "rootNode";
- public final String KEY_CAS_RETRY_POLICY_BASE_SLEEP_TIME_MS = "casRetryPolicyBaseSleepTimeMs";
- public final String KEY_CAS_RETRY_POLICY_MAX_SLEEP_TIME_MS = "casRetryPolicyMaxSleepTimeMs";
- public final String KEY_CAS_RETRY_POLICY_MAX_RETRIES = "casRetryPolicyMaxRetries";
- public final String TRANSACTION_LOCK_TIMEOUT_KEY = "transactionLockTimeoutMs";
-
- private final String connectionString;
- private final String root;
- private final int sessionTimeoutMs;
- private final int connectionTimeoutMs;
- private final int baseSleepTimeMs;
- private final int maxSleepTimeMs;
- private final int maxRetries;
- private final int casBaseSleepTimeMs;
- private final int casMaxSleepTimeMs;
- private final int casMaxRetries;
-
- public static final String SECTION = "ref-database";
- private final Long transactionLockTimeOut;
-
- private CuratorFramework build;
-
- public ZookeeperConfig(Config zkCfg) {
- Supplier<Config> lazyZkConfig = lazyLoad(zkCfg);
- connectionString =
- getString(lazyZkConfig, SECTION, SUBSECTION, KEY_CONNECT_STRING, DEFAULT_ZK_CONNECT);
- root = getString(lazyZkConfig, SECTION, SUBSECTION, KEY_ROOT_NODE, "gerrit/multi-site");
- sessionTimeoutMs =
- getInt(lazyZkConfig, SECTION, SUBSECTION, KEY_SESSION_TIMEOUT_MS, defaultSessionTimeoutMs);
- connectionTimeoutMs =
- getInt(
- lazyZkConfig,
- SECTION,
- SUBSECTION,
- KEY_CONNECTION_TIMEOUT_MS,
- defaultConnectionTimeoutMs);
-
- baseSleepTimeMs =
- getInt(
- lazyZkConfig,
- SECTION,
- SUBSECTION,
- KEY_RETRY_POLICY_BASE_SLEEP_TIME_MS,
- DEFAULT_RETRY_POLICY_BASE_SLEEP_TIME_MS);
-
- maxSleepTimeMs =
- getInt(
- lazyZkConfig,
- SECTION,
- SUBSECTION,
- KEY_RETRY_POLICY_MAX_SLEEP_TIME_MS,
- DEFAULT_RETRY_POLICY_MAX_SLEEP_TIME_MS);
-
- maxRetries =
- getInt(
- lazyZkConfig,
- SECTION,
- SUBSECTION,
- KEY_RETRY_POLICY_MAX_RETRIES,
- DEFAULT_RETRY_POLICY_MAX_RETRIES);
-
- casBaseSleepTimeMs =
- getInt(
- lazyZkConfig,
- SECTION,
- SUBSECTION,
- KEY_CAS_RETRY_POLICY_BASE_SLEEP_TIME_MS,
- DEFAULT_CAS_RETRY_POLICY_BASE_SLEEP_TIME_MS);
-
- casMaxSleepTimeMs =
- getInt(
- lazyZkConfig,
- SECTION,
- SUBSECTION,
- KEY_CAS_RETRY_POLICY_MAX_SLEEP_TIME_MS,
- DEFAULT_CAS_RETRY_POLICY_MAX_SLEEP_TIME_MS);
-
- casMaxRetries =
- getInt(
- lazyZkConfig,
- SECTION,
- SUBSECTION,
- KEY_CAS_RETRY_POLICY_MAX_RETRIES,
- DEFAULT_CAS_RETRY_POLICY_MAX_RETRIES);
-
- transactionLockTimeOut =
- getLong(
- lazyZkConfig,
- SECTION,
- SUBSECTION,
- TRANSACTION_LOCK_TIMEOUT_KEY,
- DEFAULT_TRANSACTION_LOCK_TIMEOUT);
-
- checkArgument(StringUtils.isNotEmpty(connectionString), "zookeeper.%s contains no servers");
- }
-
- public CuratorFramework buildCurator() {
- if (build == null) {
- this.build =
- CuratorFrameworkFactory.builder()
- .connectString(connectionString)
- .sessionTimeoutMs(sessionTimeoutMs)
- .connectionTimeoutMs(connectionTimeoutMs)
- .retryPolicy(
- new BoundedExponentialBackoffRetry(baseSleepTimeMs, maxSleepTimeMs, maxRetries))
- .namespace(root)
- .build();
- this.build.start();
- }
-
- return this.build;
- }
-
- public Long getZkInterProcessLockTimeOut() {
- return transactionLockTimeOut;
- }
-
- public RetryPolicy buildCasRetryPolicy() {
- return new BoundedExponentialBackoffRetry(casBaseSleepTimeMs, casMaxSleepTimeMs, casMaxRetries);
- }
-
- private static FileBasedConfig getConfigFile(SitePaths sitePaths, String configFileName) {
- return new FileBasedConfig(sitePaths.etc_dir.resolve(configFileName).toFile(), FS.DETECTED);
- }
-
- private long getLong(
- Supplier<Config> cfg, String section, String subSection, String name, long defaultValue) {
- try {
- return cfg.get().getLong(section, subSection, name, defaultValue);
- } catch (IllegalArgumentException e) {
- log.error("invalid value for {}; using default value {}", name, defaultValue);
- log.debug("Failed to retrieve long value: {}", e.getMessage(), e);
- return defaultValue;
- }
- }
-
- private int getInt(
- Supplier<Config> cfg, String section, String subSection, String name, int defaultValue) {
- try {
- return cfg.get().getInt(section, subSection, name, defaultValue);
- } catch (IllegalArgumentException e) {
- log.error("invalid value for {}; using default value {}", name, defaultValue);
- log.debug("Failed to retrieve integer value: {}", e.getMessage(), e);
- return defaultValue;
- }
- }
-
- private Supplier<Config> lazyLoad(Config config) {
- if (config instanceof FileBasedConfig) {
- return memoize(
- () -> {
- FileBasedConfig fileConfig = (FileBasedConfig) config;
- String fileConfigFileName = fileConfig.getFile().getPath();
- try {
- log.info("Loading configuration from {}", fileConfigFileName);
- fileConfig.load();
- } catch (IOException | ConfigInvalidException e) {
- log.error("Unable to load configuration from " + fileConfigFileName, e);
- }
- return fileConfig;
- });
- }
- return ofInstance(config);
- }
-
- private boolean getBoolean(
- Supplier<Config> cfg, String section, String subsection, String name, boolean defaultValue) {
- try {
- return cfg.get().getBoolean(section, subsection, name, defaultValue);
- } catch (IllegalArgumentException e) {
- log.error("invalid value for {}; using default value {}", name, defaultValue);
- log.debug("Failed to retrieve boolean value: {}", e.getMessage(), e);
- return defaultValue;
- }
- }
-
- private String getString(
- Supplier<Config> cfg, String section, String subsection, String name, String defaultValue) {
- String value = cfg.get().getString(section, subsection, name);
- if (!Strings.isNullOrEmpty(value)) {
- return value;
- }
- return defaultValue;
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApi.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApi.java
deleted file mode 100644
index 35350e9..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApi.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker;
-
-import com.google.gerrit.server.events.Event;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import java.util.function.Consumer;
-
-/** API for sending/receiving events through a message Broker. */
-public interface BrokerApi {
-
- /**
- * Send an event to a topic.
- *
- * @param topic
- * @param event
- * @return true if the event was successfully sent. False otherwise.
- */
- boolean send(String topic, Event event);
-
- /**
- * Receive asynchronously events from a topic.
- *
- * @param topic
- * @param eventConsumer
- */
- void receiveAync(String topic, Consumer<SourceAwareEventWrapper> eventConsumer);
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiNoOp.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiNoOp.java
deleted file mode 100644
index 19cf0f7..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiNoOp.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker;
-
-import com.google.gerrit.server.events.Event;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import java.util.function.Consumer;
-
-public class BrokerApiNoOp implements BrokerApi {
-
- @Override
- public boolean send(String topic, Event event) {
- return true;
- }
-
- @Override
- public void receiveAync(String topic, Consumer<SourceAwareEventWrapper> eventConsumer) {}
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiWrapper.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiWrapper.java
index e83fe53..71be5e6 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiWrapper.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiWrapper.java
@@ -14,29 +14,53 @@
package com.googlesource.gerrit.plugins.multisite.broker;
+import com.gerritforge.gerrit.eventbroker.BrokerApi;
+import com.gerritforge.gerrit.eventbroker.EventMessage;
+import com.gerritforge.gerrit.eventbroker.TopicSubscriber;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.server.events.Event;
import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
+import com.googlesource.gerrit.plugins.multisite.InstanceId;
+import com.googlesource.gerrit.plugins.multisite.MessageLogger;
+import com.googlesource.gerrit.plugins.multisite.MessageLogger.Direction;
+import com.googlesource.gerrit.plugins.multisite.forwarder.Context;
+import java.util.Set;
+import java.util.UUID;
import java.util.function.Consumer;
public class BrokerApiWrapper implements BrokerApi {
private final DynamicItem<BrokerApi> apiDelegate;
private final BrokerMetrics metrics;
+ private final MessageLogger msgLog;
+ private final UUID instanceId;
@Inject
- public BrokerApiWrapper(DynamicItem<BrokerApi> apiDelegate, BrokerMetrics metrics) {
+ public BrokerApiWrapper(
+ DynamicItem<BrokerApi> apiDelegate,
+ BrokerMetrics metrics,
+ MessageLogger msgLog,
+ @InstanceId UUID instanceId) {
this.apiDelegate = apiDelegate;
this.metrics = metrics;
+ this.msgLog = msgLog;
+ this.instanceId = instanceId;
+ }
+
+ public boolean send(String topic, Event event) {
+ return send(topic, apiDelegate.get().newMessage(instanceId, event));
}
@Override
- public boolean send(String topic, Event event) {
+ public boolean send(String topic, EventMessage message) {
+ if (Context.isForwardedEvent()) {
+ return true;
+ }
boolean succeeded = false;
try {
- succeeded = apiDelegate.get().send(topic, event);
+ succeeded = apiDelegate.get().send(topic, message);
} finally {
if (succeeded) {
+ msgLog.log(Direction.PUBLISH, topic, message);
metrics.incrementBrokerPublishedMessage();
} else {
metrics.incrementBrokerFailedToPublishMessage();
@@ -46,7 +70,22 @@
}
@Override
- public void receiveAync(String topic, Consumer<SourceAwareEventWrapper> eventConsumer) {
- apiDelegate.get().receiveAync(topic, eventConsumer);
+ public void receiveAsync(String topic, Consumer<EventMessage> messageConsumer) {
+ apiDelegate.get().receiveAsync(topic, messageConsumer);
+ }
+
+ @Override
+ public void disconnect() {
+ apiDelegate.get().disconnect();
+ }
+
+ @Override
+ public Set<TopicSubscriber> topicSubscribers() {
+ return apiDelegate.get().topicSubscribers();
+ }
+
+ @Override
+ public void replayAllEvents(String topic) {
+ apiDelegate.get().replayAllEvents(topic);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerGson.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerGson.java
deleted file mode 100644
index 219aa96..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerGson.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker;
-
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import com.google.inject.BindingAnnotation;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-@Retention(RUNTIME)
-@Target(PARAMETER)
-@BindingAnnotation
-public @interface BrokerGson {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerModule.java
deleted file mode 100644
index 6983984..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerModule.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker;
-
-import com.google.gerrit.extensions.registration.DynamicItem;
-import com.google.inject.AbstractModule;
-import com.google.inject.Scopes;
-import com.googlesource.gerrit.plugins.multisite.consumer.SubscriberModule;
-
-public class BrokerModule extends AbstractModule {
-
- @Override
- protected void configure() {
- DynamicItem.itemOf(binder(), BrokerApi.class);
- DynamicItem.bind(binder(), BrokerApi.class).to(BrokerApiNoOp.class).in(Scopes.SINGLETON);
-
- bind(BrokerApiWrapper.class).in(Scopes.SINGLETON);
-
- install(new SubscriberModule());
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerSession.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerSession.java
deleted file mode 100644
index b04fbff..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerSession.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker;
-
-public interface BrokerSession {
-
- boolean isOpen();
-
- void connect();
-
- void disconnect();
-
- boolean publish(String topic, String payload);
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/GsonProvider.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/GsonProvider.java
deleted file mode 100644
index 0791e6a..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/GsonProvider.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker;
-
-import com.google.common.base.Supplier;
-import com.google.gerrit.server.events.Event;
-import com.google.gerrit.server.events.EventDeserializer;
-import com.google.gerrit.server.events.SupplierDeserializer;
-import com.google.gerrit.server.events.SupplierSerializer;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.inject.Provider;
-
-public class GsonProvider implements Provider<Gson> {
- @Override
- public Gson get() {
- return new GsonBuilder()
- .registerTypeAdapter(Event.class, new EventDeserializer())
- .registerTypeAdapter(Supplier.class, new SupplierSerializer())
- .registerTypeAdapter(Supplier.class, new SupplierDeserializer())
- .create();
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/BrokerPublisher.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/BrokerPublisher.java
deleted file mode 100644
index ba5b532..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/BrokerPublisher.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker.kafka;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.server.events.Event;
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.multisite.InstanceId;
-import com.googlesource.gerrit.plugins.multisite.MessageLogger;
-import com.googlesource.gerrit.plugins.multisite.MessageLogger.Direction;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerSession;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import com.googlesource.gerrit.plugins.multisite.forwarder.Context;
-import java.util.UUID;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Singleton
-public class BrokerPublisher implements LifecycleListener {
- protected final Logger log = LoggerFactory.getLogger(getClass());
-
- private final BrokerSession session;
- private final Gson gson;
- private final UUID instanceId;
- private final MessageLogger msgLog;
-
- @Inject
- public BrokerPublisher(
- BrokerSession session,
- @BrokerGson Gson gson,
- @InstanceId UUID instanceId,
- MessageLogger msgLog) {
- this.session = session;
- this.gson = gson;
- this.instanceId = instanceId;
- this.msgLog = msgLog;
- }
-
- @Override
- public void start() {
- if (!session.isOpen()) {
- session.connect();
- }
- }
-
- @Override
- public void stop() {
- if (session.isOpen()) {
- session.disconnect();
- }
- }
-
- public boolean publish(String topic, Event event) {
- if (Context.isForwardedEvent()) {
- return true;
- }
-
- SourceAwareEventWrapper brokerEvent = toBrokerEvent(event);
- Boolean eventPublished = session.publish(topic, getPayload(brokerEvent));
- if (eventPublished) {
- msgLog.log(Direction.PUBLISH, brokerEvent);
- }
- return eventPublished;
- }
-
- private String getPayload(SourceAwareEventWrapper event) {
- return gson.toJson(event);
- }
-
- private SourceAwareEventWrapper toBrokerEvent(Event event) {
- JsonObject body = eventToJson(event);
- return new SourceAwareEventWrapper(
- new SourceAwareEventWrapper.EventHeader(
- UUID.randomUUID(), event.getType(), instanceId, event.eventCreatedOn),
- body);
- }
-
- @VisibleForTesting
- public JsonObject eventToJson(Event event) {
- return gson.toJsonTree(event).getAsJsonObject();
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/KafkaSession.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/KafkaSession.java
deleted file mode 100644
index 6594544..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/KafkaSession.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker.kafka;
-
-import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.multisite.InstanceId;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerSession;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
-import com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration;
-import java.util.UUID;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import org.apache.kafka.clients.producer.KafkaProducer;
-import org.apache.kafka.clients.producer.Producer;
-import org.apache.kafka.clients.producer.ProducerRecord;
-import org.apache.kafka.clients.producer.RecordMetadata;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class KafkaSession implements BrokerSession {
- private static final Logger LOGGER = LoggerFactory.getLogger(KafkaSession.class);
- private KafkaConfiguration properties;
- private final UUID instanceId;
- private volatile Producer<String, String> producer;
-
- @Inject
- public KafkaSession(KafkaConfiguration kafkaConfig, @InstanceId UUID instanceId) {
- this.properties = kafkaConfig;
- this.instanceId = instanceId;
- }
-
- @Override
- public boolean isOpen() {
- if (producer != null) {
- return true;
- }
- return false;
- }
-
- @Override
- public void connect() {
- if (isOpen()) {
- LOGGER.debug("Already connected.");
- return;
- }
-
- LOGGER.info("Connect to {}...", properties.getKafka().getBootstrapServers());
- /* Need to make sure that the thread of the running connection uses
- * the correct class loader otherwize you can endup with hard to debug
- * ClassNotFoundExceptions
- */
- setConnectionClassLoader();
- producer = new KafkaProducer<>(properties.kafkaPublisher());
- LOGGER.info("Connection established.");
- }
-
- private void setConnectionClassLoader() {
- Thread.currentThread().setContextClassLoader(KafkaSession.class.getClassLoader());
- }
-
- @Override
- public void disconnect() {
- LOGGER.info("Disconnecting...");
- if (producer != null) {
- LOGGER.info("Closing Producer {}...", producer);
- producer.close();
- }
- producer = null;
- }
-
- @Override
- public boolean publish(String topic, String payload) {
- return publishToTopic(properties.getKafka().getTopicAlias(EventTopic.of(topic)), payload);
- }
-
- private boolean publishToTopic(String topic, String payload) {
- Future<RecordMetadata> future =
- producer.send(new ProducerRecord<>(topic, instanceId.toString(), payload));
- try {
- RecordMetadata metadata = future.get();
- LOGGER.debug("The offset of the record we just sent is: {}", metadata.offset());
- return true;
- } catch (InterruptedException | ExecutionException e) {
- LOGGER.error("Cannot send the message", e);
- return false;
- }
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/AbstractSubcriber.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/AbstractSubcriber.java
index 2308c0e..ec6072c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/AbstractSubcriber.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/AbstractSubcriber.java
@@ -14,77 +14,73 @@
package com.googlesource.gerrit.plugins.multisite.consumer;
+import com.gerritforge.gerrit.eventbroker.EventMessage;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gson.Gson;
-import com.google.gwtorm.server.OrmException;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.InstanceId;
import com.googlesource.gerrit.plugins.multisite.MessageLogger;
import com.googlesource.gerrit.plugins.multisite.MessageLogger.Direction;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApi;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
import com.googlesource.gerrit.plugins.multisite.forwarder.CacheNotFoundException;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
import com.googlesource.gerrit.plugins.multisite.forwarder.router.ForwardedEventRouter;
import java.io.IOException;
import java.util.UUID;
+import java.util.function.Consumer;
-public abstract class AbstractSubcriber implements Runnable {
+public abstract class AbstractSubcriber {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
- private final BrokerApi brokerApi;
private final ForwardedEventRouter eventRouter;
private final DynamicSet<DroppedEventListener> droppedEventListeners;
- private final Gson gson;
private final UUID instanceId;
private final MessageLogger msgLog;
private SubscriberMetrics subscriberMetrics;
+ private final Configuration cfg;
+ private final String topic;
public AbstractSubcriber(
- BrokerApiWrapper brokerApi,
ForwardedEventRouter eventRouter,
DynamicSet<DroppedEventListener> droppedEventListeners,
- @BrokerGson Gson gson,
@InstanceId UUID instanceId,
MessageLogger msgLog,
- SubscriberMetrics subscriberMetrics) {
+ SubscriberMetrics subscriberMetrics,
+ Configuration cfg) {
this.eventRouter = eventRouter;
this.droppedEventListeners = droppedEventListeners;
- this.gson = gson;
this.instanceId = instanceId;
this.msgLog = msgLog;
this.subscriberMetrics = subscriberMetrics;
- this.brokerApi = brokerApi;
- }
-
- @Override
- public void run() {
- brokerApi.receiveAync(getTopic().topic(), this::processRecord);
+ this.cfg = cfg;
+ this.topic = getTopic().topic(cfg);
}
protected abstract EventTopic getTopic();
- private void processRecord(SourceAwareEventWrapper event) {
+ public Consumer<EventMessage> getConsumer() {
+ return this::processRecord;
+ }
- if (event.getHeader().getSourceInstanceId().equals(instanceId)) {
+ private void processRecord(EventMessage event) {
+
+ if (event.getHeader().sourceInstanceId.equals(instanceId)) {
logger.atFiner().log(
"Dropping event %s produced by our instanceId %s",
event.toString(), instanceId.toString());
droppedEventListeners.forEach(l -> l.onEventDropped(event));
} else {
try {
- msgLog.log(Direction.CONSUME, event);
- eventRouter.route(event.getEventBody(gson));
+ msgLog.log(Direction.CONSUME, topic, event);
+ eventRouter.route(event.getEvent());
subscriberMetrics.incrementSubscriberConsumedMessage();
} catch (IOException e) {
logger.atSevere().withCause(e).log(
- "Malformed event '%s': [Exception: %s]", event.getHeader().getEventType());
+ "Malformed event '%s': [Exception: %s]", event.getHeader());
subscriberMetrics.incrementSubscriberFailedToConsumeMessage();
- } catch (PermissionBackendException | OrmException | CacheNotFoundException e) {
+ } catch (PermissionBackendException | CacheNotFoundException e) {
logger.atSevere().withCause(e).log(
- "Cannot handle message %s: [Exception: %s]", event.getHeader().getEventType());
+ "Cannot handle message %s: [Exception: %s]", event.getHeader());
subscriberMetrics.incrementSubscriberFailedToConsumeMessage();
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/CacheEvictionEventSubscriber.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/CacheEvictionEventSubscriber.java
index 572d1a3..eae66b4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/CacheEvictionEventSubscriber.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/CacheEvictionEventSubscriber.java
@@ -15,13 +15,11 @@
package com.googlesource.gerrit.plugins.multisite.consumer;
import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.InstanceId;
import com.googlesource.gerrit.plugins.multisite.MessageLogger;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
import com.googlesource.gerrit.plugins.multisite.forwarder.router.CacheEvictionEventRouter;
import java.util.UUID;
@@ -30,21 +28,14 @@
public class CacheEvictionEventSubscriber extends AbstractSubcriber {
@Inject
public CacheEvictionEventSubscriber(
- BrokerApiWrapper brokerApi,
CacheEvictionEventRouter eventRouter,
DynamicSet<DroppedEventListener> droppedEventListeners,
- @BrokerGson Gson gsonProvider,
@InstanceId UUID instanceId,
MessageLogger msgLog,
- SubscriberMetrics subscriberMetrics) {
- super(
- brokerApi,
- eventRouter,
- droppedEventListeners,
- gsonProvider,
- instanceId,
- msgLog,
- subscriberMetrics);
+ SubscriberMetrics subscriberMetrics,
+ Configuration cfg) {
+
+ super(eventRouter, droppedEventListeners, instanceId, msgLog, subscriberMetrics, cfg);
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/ConsumerExecutor.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/ConsumerExecutor.java
deleted file mode 100644
index 936d07a..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/ConsumerExecutor.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (C) 2019 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.multisite.consumer;
-
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import com.google.inject.BindingAnnotation;
-import java.lang.annotation.Retention;
-
-@Retention(RUNTIME)
-@BindingAnnotation
-public @interface ConsumerExecutor {}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/DroppedEventListener.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/DroppedEventListener.java
index 680e8ed..6f4680c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/DroppedEventListener.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/DroppedEventListener.java
@@ -14,11 +14,13 @@
package com.googlesource.gerrit.plugins.multisite.consumer;
+import com.gerritforge.gerrit.eventbroker.EventMessage;
+
public interface DroppedEventListener {
/**
* Invoked when any event is dropped.
*
* @param event information about the event.
*/
- void onEventDropped(SourceAwareEventWrapper event);
+ void onEventDropped(EventMessage event);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/IndexEventSubscriber.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/IndexEventSubscriber.java
index df55040..696cf03 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/IndexEventSubscriber.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/IndexEventSubscriber.java
@@ -15,13 +15,11 @@
package com.googlesource.gerrit.plugins.multisite.consumer;
import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.InstanceId;
import com.googlesource.gerrit.plugins.multisite.MessageLogger;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
import com.googlesource.gerrit.plugins.multisite.forwarder.router.IndexEventRouter;
import java.util.UUID;
@@ -30,21 +28,14 @@
public class IndexEventSubscriber extends AbstractSubcriber {
@Inject
public IndexEventSubscriber(
- BrokerApiWrapper brokerApi,
IndexEventRouter eventRouter,
DynamicSet<DroppedEventListener> droppedEventListeners,
- @BrokerGson Gson gsonProvider,
@InstanceId UUID instanceId,
MessageLogger msgLog,
- SubscriberMetrics subscriberMetrics) {
+ SubscriberMetrics subscriberMetrics,
+ Configuration cfg) {
super(
- brokerApi,
- eventRouter,
- droppedEventListeners,
- gsonProvider,
- instanceId,
- msgLog,
- subscriberMetrics);
+ eventRouter, droppedEventListeners, instanceId, msgLog, subscriberMetrics, cfg);
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/MultiSiteConsumerRunner.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/MultiSiteConsumerRunner.java
index 1778961..f14dde5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/MultiSiteConsumerRunner.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/MultiSiteConsumerRunner.java
@@ -14,36 +14,42 @@
package com.googlesource.gerrit.plugins.multisite.consumer;
+import com.gerritforge.gerrit.eventbroker.BrokerApi;
+import com.google.common.collect.Lists;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.events.LifecycleListener;
+import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import java.util.concurrent.ExecutorService;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
@Singleton
public class MultiSiteConsumerRunner implements LifecycleListener {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final DynamicSet<AbstractSubcriber> consumers;
- private final ExecutorService executor;
+ private DynamicItem<BrokerApi> brokerApi;
+ private Configuration cfg;
@Inject
public MultiSiteConsumerRunner(
- @ConsumerExecutor ExecutorService executor, DynamicSet<AbstractSubcriber> consumers) {
+ DynamicItem<BrokerApi> brokerApi,
+ DynamicSet<AbstractSubcriber> consumers,
+ Configuration cfg) {
this.consumers = consumers;
- this.executor = executor;
+ this.brokerApi = brokerApi;
+ this.cfg = cfg;
}
@Override
public void start() {
logger.atInfo().log("starting consumers");
- consumers.forEach(c -> executor.execute(c));
+ consumers.forEach(
+ consumer ->
+ brokerApi.get().receiveAsync(consumer.getTopic().topic(cfg), consumer.getConsumer()));
}
@Override
- public void stop() {
- logger.atInfo().log("shutting down consumers");
- executor.shutdown();
- }
+ public void stop() {}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/ProjectUpdateEventSubscriber.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/ProjectUpdateEventSubscriber.java
index 5c42ea6..bf8b33d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/ProjectUpdateEventSubscriber.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/ProjectUpdateEventSubscriber.java
@@ -15,13 +15,11 @@
package com.googlesource.gerrit.plugins.multisite.consumer;
import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.InstanceId;
import com.googlesource.gerrit.plugins.multisite.MessageLogger;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
import com.googlesource.gerrit.plugins.multisite.forwarder.router.ProjectListUpdateRouter;
import java.util.UUID;
@@ -30,15 +28,14 @@
public class ProjectUpdateEventSubscriber extends AbstractSubcriber {
@Inject
public ProjectUpdateEventSubscriber(
- BrokerApiWrapper brokerApi,
ProjectListUpdateRouter eventRouter,
DynamicSet<DroppedEventListener> droppedEventListeners,
- @BrokerGson Gson gson,
@InstanceId UUID instanceId,
MessageLogger msgLog,
- SubscriberMetrics subscriberMetrics) {
+ SubscriberMetrics subscriberMetrics,
+ Configuration cfg) {
super(
- brokerApi, eventRouter, droppedEventListeners, gson, instanceId, msgLog, subscriberMetrics);
+ eventRouter, droppedEventListeners, instanceId, msgLog, subscriberMetrics, cfg);
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SourceAwareEventWrapper.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SourceAwareEventWrapper.java
deleted file mode 100644
index b8bd0d8..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SourceAwareEventWrapper.java
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright (C) 2019 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.multisite.consumer;
-
-import static java.util.Objects.requireNonNull;
-
-import com.google.gerrit.server.events.Event;
-import com.google.gson.Gson;
-import com.google.gson.JsonObject;
-import java.util.UUID;
-
-public class SourceAwareEventWrapper {
-
- private final EventHeader header;
- private final JsonObject body;
-
- public EventHeader getHeader() {
- return header;
- }
-
- public JsonObject getBody() {
- return body;
- }
-
- public Event getEventBody(Gson gson) {
- return gson.fromJson(this.body, Event.class);
- }
-
- public static class EventHeader {
- private final UUID eventId;
- private final String eventType;
- private final UUID sourceInstanceId;
- private final Long eventCreatedOn;
-
- public EventHeader(UUID eventId, String eventType, UUID sourceInstanceId, Long eventCreatedOn) {
- this.eventId = eventId;
- this.eventType = eventType;
- this.sourceInstanceId = sourceInstanceId;
- this.eventCreatedOn = eventCreatedOn;
- }
-
- public UUID getEventId() {
- return eventId;
- }
-
- public String getEventType() {
- return eventType;
- }
-
- public UUID getSourceInstanceId() {
- return sourceInstanceId;
- }
-
- public Long getEventCreatedOn() {
- return eventCreatedOn;
- }
-
- public void validate() {
- requireNonNull(eventId, "EventId cannot be null");
- requireNonNull(eventType, "EventType cannot be null");
- requireNonNull(sourceInstanceId, "Source Instance ID cannot be null");
- }
-
- @Override
- public String toString() {
- return "{"
- + "eventId="
- + eventId
- + ", eventType='"
- + eventType
- + '\''
- + ", sourceInstanceId="
- + sourceInstanceId
- + ", eventCreatedOn="
- + eventCreatedOn
- + '}';
- }
- }
-
- public SourceAwareEventWrapper(EventHeader header, JsonObject body) {
- this.header = header;
- this.body = body;
- }
-
- public void validate() {
- requireNonNull(header, "Header cannot be null");
- requireNonNull(body, "Body cannot be null");
- header.validate();
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/StreamEventSubscriber.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/StreamEventSubscriber.java
index b48ab31..39ace0e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/StreamEventSubscriber.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/StreamEventSubscriber.java
@@ -15,13 +15,11 @@
package com.googlesource.gerrit.plugins.multisite.consumer;
import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gson.Gson;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.InstanceId;
import com.googlesource.gerrit.plugins.multisite.MessageLogger;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
import com.googlesource.gerrit.plugins.multisite.forwarder.router.StreamEventRouter;
import java.util.UUID;
@@ -30,15 +28,14 @@
public class StreamEventSubscriber extends AbstractSubcriber {
@Inject
public StreamEventSubscriber(
- BrokerApiWrapper brokerApi,
StreamEventRouter eventRouter,
DynamicSet<DroppedEventListener> droppedEventListeners,
- @BrokerGson Gson gson,
@InstanceId UUID instanceId,
MessageLogger msgLog,
- SubscriberMetrics subscriberMetrics) {
+ SubscriberMetrics subscriberMetrics,
+ Configuration cfg) {
super(
- brokerApi, eventRouter, droppedEventListeners, gson, instanceId, msgLog, subscriberMetrics);
+ eventRouter, droppedEventListeners, instanceId, msgLog, subscriberMetrics, cfg);
}
@Override
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SubscriberMetrics.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SubscriberMetrics.java
index 996b581..3a7cce7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SubscriberMetrics.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SubscriberMetrics.java
@@ -26,12 +26,9 @@
private static final String SUBSCRIBER_SUCCESS_COUNTER = "subscriber_msg_consumer_counter";
private static final String SUBSCRIBER_FAILURE_COUNTER =
"subscriber_msg_consumer_failure_counter";
- private static final String SUBSCRIBER_POLL_FAILURE_COUNTER =
- "subscriber_msg_consumer_poll_failure_counter";
private final Counter1<String> subscriberSuccessCounter;
private final Counter1<String> subscriberFailureCounter;
- private final Counter1<String> subscriberPollFailureCounter;
@Inject
public SubscriberMetrics(MetricMaker metricMaker) {
@@ -51,15 +48,6 @@
.setUnit("errors"),
Field.ofString(
SUBSCRIBER_FAILURE_COUNTER, "Subscriber failed to consume messages count"));
-
- this.subscriberPollFailureCounter =
- metricMaker.newCounter(
- "multi_site/subscriber/subscriber_message_consumer_poll_failure_counter",
- new Description("Number of failed attempts to poll messages by the subscriber")
- .setRate()
- .setUnit("errors"),
- Field.ofString(
- SUBSCRIBER_POLL_FAILURE_COUNTER, "Subscriber failed to poll messages count"));
}
public void incrementSubscriberConsumedMessage() {
@@ -69,8 +57,4 @@
public void incrementSubscriberFailedToConsumeMessage() {
subscriberFailureCounter.increment(SUBSCRIBER_FAILURE_COUNTER);
}
-
- public void incrementSubscriberFailedToPollMessages() {
- subscriberPollFailureCounter.increment(SUBSCRIBER_POLL_FAILURE_COUNTER);
- }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SubscriberModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SubscriberModule.java
index 0a0c350..afd4d09 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SubscriberModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/consumer/SubscriberModule.java
@@ -16,22 +16,20 @@
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.lifecycle.LifecycleModule;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.MultiSiteEvent;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
public class SubscriberModule extends LifecycleModule {
@Override
protected void configure() {
MultiSiteEvent.registerEventTypes();
- bind(ExecutorService.class)
- .annotatedWith(ConsumerExecutor.class)
- .toInstance(Executors.newFixedThreadPool(EventTopic.values().length));
- listener().to(MultiSiteConsumerRunner.class);
DynamicSet.setOf(binder(), AbstractSubcriber.class);
DynamicSet.setOf(binder(), DroppedEventListener.class);
+
+ DynamicSet.bind(binder(), AbstractSubcriber.class).to(IndexEventSubscriber.class);
+ DynamicSet.bind(binder(), AbstractSubcriber.class).to(StreamEventSubscriber.class);
+ DynamicSet.bind(binder(), AbstractSubcriber.class).to(CacheEvictionEventSubscriber.class);
+ DynamicSet.bind(binder(), AbstractSubcriber.class).to(ProjectUpdateEventSubscriber.class);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedAwareEventBroker.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedAwareEventBroker.java
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedAwareEventBroker.java
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedEventHandler.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedEventHandler.java
index 85dab30..278ba4e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedEventHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedEventHandler.java
@@ -19,7 +19,6 @@
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.slf4j.Logger;
@@ -47,9 +46,8 @@
* Dispatch an event in the local node, event will not be forwarded to the other node.
*
* @param event The event to dispatch
- * @throws OrmException If an error occur while retrieving the change the event belongs to.
*/
- public void dispatch(Event event) throws OrmException, PermissionBackendException {
+ public void dispatch(Event event) throws PermissionBackendException {
try (ManualRequestContext ctx = oneOffCtx.open()) {
Context.setForwardedEvent(true);
log.debug("dispatching event {}", event.getType());
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexAccountHandler.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexAccountHandler.java
index 29bfa44..31256b7 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexAccountHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexAccountHandler.java
@@ -20,7 +20,6 @@
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.AccountIndexEvent;
-import java.io.IOException;
import java.util.Optional;
/**
@@ -41,7 +40,7 @@
}
@Override
- protected void doIndex(Account.Id id, Optional<AccountIndexEvent> event) throws IOException {
+ protected void doIndex(Account.Id id, Optional<AccountIndexEvent> event) {
indexer.index(id);
log.debug("Account {} successfully indexed", id);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexChangeHandler.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexChangeHandler.java
index 1913b00..8340a5f 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexChangeHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexChangeHandler.java
@@ -18,10 +18,8 @@
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.multisite.Configuration;
@@ -30,7 +28,6 @@
import com.googlesource.gerrit.plugins.multisite.index.ChangeChecker;
import com.googlesource.gerrit.plugins.multisite.index.ChangeCheckerImpl;
import com.googlesource.gerrit.plugins.multisite.index.ForwardedIndexExecutor;
-import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
@@ -71,72 +68,48 @@
}
@Override
- protected void doIndex(String id, Optional<ChangeIndexEvent> indexEvent)
- throws IOException, OrmException {
+ protected void doIndex(String id, Optional<ChangeIndexEvent> indexEvent) {
doIndex(id, indexEvent, 0);
}
- private void doIndex(String id, Optional<ChangeIndexEvent> indexEvent, int retryCount)
- throws IOException, OrmException {
- try {
- ChangeChecker checker = changeCheckerFactory.create(id);
- Optional<ChangeNotes> changeNotes = checker.getChangeNotes();
- if (changeNotes.isPresent()) {
- ChangeNotes notes = changeNotes.get();
- reindex(notes);
+ private void doIndex(String id, Optional<ChangeIndexEvent> indexEvent, int retryCount) {
+ ChangeChecker checker = changeCheckerFactory.create(id);
+ Optional<ChangeNotes> changeNotes = checker.getChangeNotes();
+ if (changeNotes.isPresent()) {
+ ChangeNotes notes = changeNotes.get();
+ reindex(notes);
- if (checker.isChangeUpToDate(indexEvent)) {
- if (retryCount > 0) {
- log.warn("Change {} has been eventually indexed after {} attempt(s)", id, retryCount);
- } else {
- log.debug("Change {} successfully indexed", id);
- }
+ if (checker.isChangeUpToDate(indexEvent)) {
+ if (retryCount > 0) {
+ log.warn("Change {} has been eventually indexed after {} attempt(s)", id, retryCount);
} else {
- log.warn(
- "Change {} seems too old compared to the event timestamp (event={} >> change-Ts={})",
- id,
- indexEvent,
- checker);
- rescheduleIndex(id, indexEvent, retryCount + 1);
+ log.debug("Change {} successfully indexed", id);
}
} else {
log.warn(
- "Change {} not present yet in local Git repository (event={}) after {} attempt(s)",
+ "Change {} seems too old compared to the event timestamp (event={} >> change-Ts={})",
id,
indexEvent,
- retryCount);
- if (!rescheduleIndex(id, indexEvent, retryCount + 1)) {
- log.error(
- "Change {} could not be found in the local Git repository (event={})",
- id,
- indexEvent);
- }
+ checker);
+ rescheduleIndex(id, indexEvent, retryCount + 1);
}
- } catch (Exception e) {
- if (isCausedByNoSuchChangeException(e)) {
- indexer.delete(parseChangeId(id));
- log.warn("Error trying to index Change {}. Deleted from index", id, e);
- return;
+ } else {
+ log.warn(
+ "Change {} not present yet in local Git repository (event={}) after {} attempt(s)",
+ id,
+ indexEvent,
+ retryCount);
+ if (!rescheduleIndex(id, indexEvent, retryCount + 1)) {
+ log.error(
+ "Change {} could not be found in the local Git repository (event={})", id, indexEvent);
}
-
- throw e;
}
}
- private static boolean isCausedByNoSuchChangeException(Throwable throwable) {
- while (throwable != null) {
- if (throwable instanceof NoSuchChangeException) {
- return true;
- }
- throwable = throwable.getCause();
- }
- return false;
- }
-
- private void reindex(ChangeNotes notes) throws IOException, OrmException {
+ private void reindex(ChangeNotes notes) {
try (ManualRequestContext ctx = oneOffCtx.open()) {
notes.reload();
- indexer.index(ctx.getReviewDbProvider().get(), notes.getChange());
+ indexer.index(notes.getChange());
}
}
@@ -172,7 +145,7 @@
}
@Override
- protected void doDelete(String id, Optional<ChangeIndexEvent> indexEvent) throws IOException {
+ protected void doDelete(String id, Optional<ChangeIndexEvent> indexEvent) {
indexer.delete(parseChangeId(id));
log.debug("Change {} successfully deleted from index", id);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexGroupHandler.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexGroupHandler.java
index 76ce260..368dffe 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexGroupHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexGroupHandler.java
@@ -16,12 +16,10 @@
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.index.group.GroupIndexer;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.GroupIndexEvent;
-import java.io.IOException;
import java.util.Optional;
/**
@@ -41,8 +39,7 @@
}
@Override
- protected void doIndex(String uuid, Optional<GroupIndexEvent> event)
- throws IOException, OrmException {
+ protected void doIndex(String uuid, Optional<GroupIndexEvent> event) {
indexer.index(new AccountGroup.UUID(uuid));
log.debug("Group {} successfully indexed", uuid);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandler.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandler.java
index ff2e111..e5f7e10 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexProjectHandler.java
@@ -22,7 +22,6 @@
import com.googlesource.gerrit.plugins.multisite.forwarder.events.ProjectIndexEvent;
import com.googlesource.gerrit.plugins.multisite.index.ForwardedIndexExecutor;
import com.googlesource.gerrit.plugins.multisite.index.ProjectChecker;
-import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -58,15 +57,14 @@
}
@Override
- protected void doIndex(String projectName, Optional<ProjectIndexEvent> event) throws IOException {
+ protected void doIndex(String projectName, Optional<ProjectIndexEvent> event) {
if (!attemptIndex(projectName, event)) {
log.warn("First Attempt failed, scheduling again after {} msecs", retryInterval);
rescheduleIndex(projectName, event, 1);
}
}
- public boolean attemptIndex(String projectName, Optional<ProjectIndexEvent> event)
- throws IOException {
+ public boolean attemptIndex(String projectName, Optional<ProjectIndexEvent> event) {
log.debug("Attempt to index project {}, event: [{}]", projectName, event);
final Project.NameKey projectNameKey = new Project.NameKey(projectName);
if (projectChecker.isProjectUpToDate(projectNameKey)) {
@@ -97,17 +95,13 @@
indexExecutor.schedule(
() -> {
Context.setForwardedEvent(true);
- try {
- if (!attemptIndex(projectName, event)) {
- log.warn(
- "Attempt {} to index project {} failed, scheduling again after {} msecs",
- retryCount,
- projectName,
- retryInterval);
- rescheduleIndex(projectName, event, retryCount + 1);
- }
- } catch (IOException e) {
- log.warn("Project {} could not be indexed", projectName, e);
+ if (!attemptIndex(projectName, event)) {
+ log.warn(
+ "Attempt {} to index project {} failed, scheduling again after {} msecs",
+ retryCount,
+ projectName,
+ retryInterval);
+ rescheduleIndex(projectName, event, retryCount + 1);
}
},
retryInterval,
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexingHandler.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexingHandler.java
index 67662f6..de6b836 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexingHandler.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexingHandler.java
@@ -15,7 +15,6 @@
package com.googlesource.gerrit.plugins.multisite.forwarder;
import com.google.common.util.concurrent.Striped;
-import com.google.gwtorm.server.OrmException;
import java.io.IOException;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
@@ -43,9 +42,9 @@
private final Striped<Lock> idLocks;
- protected abstract void doIndex(T id, Optional<E> indexEvent) throws IOException, OrmException;
+ protected abstract void doIndex(T id, Optional<E> indexEvent);
- protected abstract void doDelete(T id, Optional<E> indexEvent) throws IOException;
+ protected abstract void doDelete(T id, Optional<E> indexEvent);
protected ForwardedIndexingHandler(int lockStripes) {
idLocks = Striped.lock(lockStripes);
@@ -58,9 +57,8 @@
* @param operation The operation to do; index or delete
* @param event The index event details.
* @throws IOException If an error occur while indexing.
- * @throws OrmException If an error occur while retrieving a change related to the item to index
*/
- public void index(T id, Operation operation, Optional<E> event) throws IOException, OrmException {
+ public void index(T id, Operation operation, Optional<E> event) throws IOException {
log.debug("{} {} {}", operation, id, event);
try {
Context.setForwardedEvent(true);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerCacheEvictionForwarder.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerCacheEvictionForwarder.java
index dff21c1..b32e5ae 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerCacheEvictionForwarder.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerCacheEvictionForwarder.java
@@ -16,7 +16,7 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApi;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
import com.googlesource.gerrit.plugins.multisite.forwarder.CacheEvictionForwarder;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.CacheEvictionEvent;
@@ -24,15 +24,17 @@
@Singleton
public class BrokerCacheEvictionForwarder implements CacheEvictionForwarder {
- private final BrokerApi broker;
+ private final BrokerApiWrapper broker;
+ private final Configuration cfg;
@Inject
- BrokerCacheEvictionForwarder(BrokerApiWrapper broker) {
+ BrokerCacheEvictionForwarder(BrokerApiWrapper broker, Configuration cfg) {
this.broker = broker;
+ this.cfg = cfg;
}
@Override
public boolean evict(CacheEvictionEvent event) {
- return broker.send(EventTopic.CACHE_TOPIC.topic(), event);
+ return broker.send(EventTopic.CACHE_TOPIC.topic(cfg), event);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerForwarderModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerForwarderModule.java
new file mode 100644
index 0000000..6bd6437
--- /dev/null
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerForwarderModule.java
@@ -0,0 +1,33 @@
+// Copyright (C) 2019 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.multisite.forwarder.broker;
+
+import com.google.gerrit.extensions.registration.DynamicSet;
+import com.google.gerrit.lifecycle.LifecycleModule;
+import com.googlesource.gerrit.plugins.multisite.forwarder.CacheEvictionForwarder;
+import com.googlesource.gerrit.plugins.multisite.forwarder.IndexEventForwarder;
+import com.googlesource.gerrit.plugins.multisite.forwarder.ProjectListUpdateForwarder;
+import com.googlesource.gerrit.plugins.multisite.forwarder.StreamEventForwarder;
+
+public class BrokerForwarderModule extends LifecycleModule {
+ @Override
+ protected void configure() {
+ DynamicSet.bind(binder(), IndexEventForwarder.class).to(BrokerIndexEventForwarder.class);
+ DynamicSet.bind(binder(), CacheEvictionForwarder.class).to(BrokerCacheEvictionForwarder.class);
+ DynamicSet.bind(binder(), ProjectListUpdateForwarder.class)
+ .to(BrokerProjectListUpdateForwarder.class);
+ DynamicSet.bind(binder(), StreamEventForwarder.class).to(BrokerStreamEventForwarder.class);
+ }
+}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerIndexEventForwarder.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerIndexEventForwarder.java
index c2cc3dc..0b4252d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerIndexEventForwarder.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerIndexEventForwarder.java
@@ -15,22 +15,24 @@
package com.googlesource.gerrit.plugins.multisite.forwarder.broker;
import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApi;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
import com.googlesource.gerrit.plugins.multisite.forwarder.IndexEventForwarder;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.IndexEvent;
public class BrokerIndexEventForwarder implements IndexEventForwarder {
- private final BrokerApi broker;
+ private final BrokerApiWrapper broker;
+ private final Configuration cfg;
@Inject
- BrokerIndexEventForwarder(BrokerApiWrapper broker) {
+ BrokerIndexEventForwarder(BrokerApiWrapper broker, Configuration cfg) {
this.broker = broker;
+ this.cfg = cfg;
}
@Override
public boolean index(IndexEvent event) {
- return broker.send(EventTopic.INDEX_TOPIC.topic(), event);
+ return broker.send(EventTopic.INDEX_TOPIC.topic(cfg), event);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerProjectListUpdateForwarder.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerProjectListUpdateForwarder.java
index 1a8b652..34e0300 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerProjectListUpdateForwarder.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerProjectListUpdateForwarder.java
@@ -18,22 +18,24 @@
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApi;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
import com.googlesource.gerrit.plugins.multisite.forwarder.ProjectListUpdateForwarder;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.ProjectListUpdateEvent;
@Singleton
public class BrokerProjectListUpdateForwarder implements ProjectListUpdateForwarder {
- private final BrokerApi broker;
+ private final BrokerApiWrapper broker;
+ private final Configuration cfg;
@Inject
- BrokerProjectListUpdateForwarder(BrokerApiWrapper broker) {
+ BrokerProjectListUpdateForwarder(BrokerApiWrapper broker, Configuration cfg) {
this.broker = broker;
+ this.cfg = cfg;
}
@Override
public boolean updateProjectList(ProjectListUpdateEvent event) {
- return broker.send(PROJECT_LIST_TOPIC.topic(), event);
+ return broker.send(PROJECT_LIST_TOPIC.topic(cfg), event);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerStreamEventForwarder.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerStreamEventForwarder.java
index ed3a717..9ff4688 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerStreamEventForwarder.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/broker/BrokerStreamEventForwarder.java
@@ -17,22 +17,24 @@
import com.google.gerrit.server.events.Event;
import com.google.inject.Inject;
import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApi;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
import com.googlesource.gerrit.plugins.multisite.forwarder.StreamEventForwarder;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
@Singleton
public class BrokerStreamEventForwarder implements StreamEventForwarder {
- private final BrokerApi broker;
+ private final BrokerApiWrapper broker;
+ private final Configuration cfg;
@Inject
- BrokerStreamEventForwarder(BrokerApiWrapper broker) {
+ BrokerStreamEventForwarder(BrokerApiWrapper broker, Configuration cfg) {
this.broker = broker;
+ this.cfg = cfg;
}
@Override
public boolean send(Event event) {
- return broker.send(EventTopic.STREAM_EVENT_TOPIC.topic(), event);
+ return broker.send(EventTopic.STREAM_EVENT_TOPIC.topic(cfg), event);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/events/EventTopic.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/events/EventTopic.java
index 7d42acc..eaa2df9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/events/EventTopic.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/events/EventTopic.java
@@ -14,6 +14,8 @@
package com.googlesource.gerrit.plugins.multisite.forwarder.events;
+import com.googlesource.gerrit.plugins.multisite.Configuration;
+
public enum EventTopic {
INDEX_TOPIC("GERRIT.EVENT.INDEX", "indexEvent"),
CACHE_TOPIC("GERRIT.EVENT.CACHE", "cacheEvent"),
@@ -28,18 +30,14 @@
this.aliasKey = aliasKey;
}
- public String topic() {
- return topic;
+ public String topic(Configuration config) {
+ return config.broker().getTopic(topicAliasKey(), topic);
}
public String topicAliasKey() {
return aliasKey + "Topic";
}
- public String enabledKey() {
- return aliasKey + "Enabled";
- }
-
public static EventTopic of(String topicString) {
EventTopic[] topics = EventTopic.values();
for (EventTopic topic : topics) {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedEventRouter.java
index 139020b..f9ad0c9 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedEventRouter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/ForwardedEventRouter.java
@@ -15,11 +15,10 @@
package com.googlesource.gerrit.plugins.multisite.forwarder.router;
import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gwtorm.server.OrmException;
import com.googlesource.gerrit.plugins.multisite.forwarder.CacheNotFoundException;
import java.io.IOException;
public interface ForwardedEventRouter<EventType> {
void route(EventType sourceEvent)
- throws IOException, OrmException, PermissionBackendException, CacheNotFoundException;
+ throws IOException, PermissionBackendException, CacheNotFoundException;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/IndexEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/IndexEventRouter.java
index 0103c38..3bd1142 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/IndexEventRouter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/IndexEventRouter.java
@@ -18,7 +18,6 @@
import static com.googlesource.gerrit.plugins.multisite.forwarder.ForwardedIndexingHandler.Operation.INDEX;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.multisite.forwarder.ForwardedIndexAccountHandler;
import com.googlesource.gerrit.plugins.multisite.forwarder.ForwardedIndexChangeHandler;
@@ -52,7 +51,7 @@
}
@Override
- public void route(IndexEvent sourceEvent) throws IOException, OrmException {
+ public void route(IndexEvent sourceEvent) throws IOException {
if (sourceEvent instanceof ChangeIndexEvent) {
ChangeIndexEvent changeIndexEvent = (ChangeIndexEvent) sourceEvent;
ForwardedIndexingHandler.Operation operation = changeIndexEvent.deleted ? DELETE : INDEX;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/StreamEventRouter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/StreamEventRouter.java
index 71edfb0..d911c00 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/StreamEventRouter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/forwarder/router/StreamEventRouter.java
@@ -16,7 +16,6 @@
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.multisite.forwarder.ForwardedEventHandler;
@@ -29,7 +28,7 @@
}
@Override
- public void route(Event sourceEvent) throws OrmException, PermissionBackendException {
+ public void route(Event sourceEvent) throws PermissionBackendException {
streamEventHandler.dispatch(sourceEvent);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeChecker.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeChecker.java
index 1b0fea8..3646b3a 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeChecker.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeChecker.java
@@ -15,7 +15,6 @@
package com.googlesource.gerrit.plugins.multisite.index;
import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gwtorm.server.OrmException;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.ChangeIndexEvent;
import java.io.IOException;
import java.util.Optional;
@@ -27,9 +26,8 @@
* Return the Change nodes read from ReviewDb or NoteDb.
*
* @return notes of the Change
- * @throws OrmException if ReviewDb or NoteDb cannot be opened
*/
- public Optional<ChangeNotes> getChangeNotes() throws OrmException;
+ public Optional<ChangeNotes> getChangeNotes();
/**
* Create a new index event POJO associated with the current Change.
@@ -40,21 +38,17 @@
* index
* @return new IndexEvent
* @throws IOException if the current Change cannot read
- * @throws OrmException if ReviewDb cannot be opened
*/
public Optional<ChangeIndexEvent> newIndexEvent(String projectName, int changeId, boolean deleted)
- throws IOException, OrmException;
+ throws IOException;
/**
* Check if the local Change is aligned with the indexEvent received.
*
* @param indexEvent indexing event
* @return true if the local Change is up-to-date, false otherwise.
- * @throws IOException if an I/O error occurred while reading the local Change
- * @throws OrmException if the local ReviewDb cannot be opened
*/
- public boolean isChangeUpToDate(Optional<ChangeIndexEvent> indexEvent)
- throws IOException, OrmException;
+ public boolean isChangeUpToDate(Optional<ChangeIndexEvent> indexEvent);
/**
* Return the last computed up-to-date Change time-stamp.
@@ -63,7 +57,6 @@
*
* @return the Change timestamp epoch in seconds
* @throws IOException if an I/O error occurred while reading the local Change
- * @throws OrmException if the local ReviewDb cannot be opened
*/
- public Optional<Long> getComputedChangeTs() throws IOException, OrmException;
+ public Optional<Long> getComputedChangeTs() throws IOException;
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeCheckerImpl.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeCheckerImpl.java
index 8cb2fec..f1e80cc 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeCheckerImpl.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/index/ChangeCheckerImpl.java
@@ -14,16 +14,15 @@
package com.googlesource.gerrit.plugins.multisite.index;
+import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.ChangeIndexEvent;
@@ -66,7 +65,7 @@
@Override
public Optional<ChangeIndexEvent> newIndexEvent(String projectName, int changeId, boolean deleted)
- throws IOException, OrmException {
+ throws IOException {
return getComputedChangeTs()
.map(
ts -> {
@@ -78,7 +77,7 @@
}
@Override
- public Optional<ChangeNotes> getChangeNotes() throws OrmException {
+ public Optional<ChangeNotes> getChangeNotes() {
try (ManualRequestContext ctx = oneOffReqCtx.open()) {
this.changeNotes = Optional.ofNullable(changeFinder.findOne(changeId));
return changeNotes;
@@ -86,8 +85,7 @@
}
@Override
- public boolean isChangeUpToDate(Optional<ChangeIndexEvent> indexEvent)
- throws IOException, OrmException {
+ public boolean isChangeUpToDate(Optional<ChangeIndexEvent> indexEvent) {
getComputedChangeTs();
if (!computedChangeTs.isPresent()) {
log.warn("Unable to compute last updated ts for change {}", changeId);
@@ -108,7 +106,7 @@
}
@Override
- public Optional<Long> getComputedChangeTs() throws IOException, OrmException {
+ public Optional<Long> getComputedChangeTs() {
if (!computedChangeTs.isPresent()) {
computedChangeTs = computeLastChangeTs();
}
@@ -117,17 +115,12 @@
@Override
public String toString() {
- try {
- return "change-id="
- + changeId
- + "@"
- + getComputedChangeTs().map(ChangeIndexEvent::format)
- + "/"
- + getBranchTargetSha();
- } catch (IOException | OrmException e) {
- log.error("Unable to render change {}", changeId, e);
- return "change-id=" + changeId;
- }
+ return "change-id="
+ + changeId
+ + "@"
+ + getComputedChangeTs().map(ChangeIndexEvent::format)
+ + "/"
+ + getBranchTargetSha();
}
private String getBranchTargetSha() {
@@ -147,21 +140,19 @@
}
}
- private Optional<Long> computeLastChangeTs() throws OrmException {
- try (ReviewDb db = oneOffReqCtx.open().getReviewDbProvider().get()) {
- return getChangeNotes().map(notes -> getTsFromChangeAndDraftComments(db, notes));
- }
+ private Optional<Long> computeLastChangeTs() {
+ return getChangeNotes().map(notes -> getTsFromChangeAndDraftComments(notes));
}
- private long getTsFromChangeAndDraftComments(ReviewDb db, ChangeNotes notes) {
+ private long getTsFromChangeAndDraftComments(ChangeNotes notes) {
Change change = notes.getChange();
Timestamp changeTs = change.getLastUpdatedOn();
try {
- for (Comment comment : commentsUtil.draftByChange(db, changeNotes.get())) {
+ for (Comment comment : commentsUtil.draftByChange(changeNotes.get())) {
Timestamp commentTs = comment.writtenOn;
changeTs = commentTs.after(changeTs) ? commentTs : changeTs;
}
- } catch (OrmException e) {
+ } catch (StorageException e) {
log.warn("Unable to access draft comments for change {}", change, e);
}
return changeTs.getTime() / 1000;
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaBrokerApi.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaBrokerApi.java
deleted file mode 100644
index ff23b78..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaBrokerApi.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka;
-
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.server.events.Event;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApi;
-import com.googlesource.gerrit.plugins.multisite.broker.kafka.BrokerPublisher;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
-import com.googlesource.gerrit.plugins.multisite.kafka.consumer.KafkaEventSubscriber;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.function.Consumer;
-
-public class KafkaBrokerApi implements BrokerApi, LifecycleListener {
-
- private final BrokerPublisher publisher;
- private final Provider<KafkaEventSubscriber> subscriberProvider;
- private List<KafkaEventSubscriber> subscribers;
-
- @Inject
- public KafkaBrokerApi(
- BrokerPublisher publisher, Provider<KafkaEventSubscriber> subscriberProvider) {
- this.publisher = publisher;
- this.subscriberProvider = subscriberProvider;
- subscribers = new ArrayList<>();
- }
-
- @Override
- public boolean send(String topic, Event event) {
- return publisher.publish(topic, event);
- }
-
- @Override
- public void receiveAync(String topic, Consumer<SourceAwareEventWrapper> eventConsumer) {
- KafkaEventSubscriber subscriber = subscriberProvider.get();
- synchronized (subscribers) {
- subscribers.add(subscriber);
- }
- subscriber.subscribe(EventTopic.of(topic), eventConsumer);
- }
-
- @Override
- public void start() {}
-
- @Override
- public void stop() {
- for (KafkaEventSubscriber subscriber : subscribers) {
- subscriber.shutdown();
- }
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaBrokerModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaBrokerModule.java
deleted file mode 100644
index 5fdb07e..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaBrokerModule.java
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka;
-
-import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.inject.Inject;
-import com.google.inject.TypeLiteral;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerSession;
-import com.googlesource.gerrit.plugins.multisite.broker.kafka.BrokerPublisher;
-import com.googlesource.gerrit.plugins.multisite.broker.kafka.KafkaSession;
-import com.googlesource.gerrit.plugins.multisite.consumer.AbstractSubcriber;
-import com.googlesource.gerrit.plugins.multisite.consumer.CacheEvictionEventSubscriber;
-import com.googlesource.gerrit.plugins.multisite.consumer.IndexEventSubscriber;
-import com.googlesource.gerrit.plugins.multisite.consumer.ProjectUpdateEventSubscriber;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import com.googlesource.gerrit.plugins.multisite.consumer.StreamEventSubscriber;
-import com.googlesource.gerrit.plugins.multisite.forwarder.CacheEvictionForwarder;
-import com.googlesource.gerrit.plugins.multisite.forwarder.IndexEventForwarder;
-import com.googlesource.gerrit.plugins.multisite.forwarder.ProjectListUpdateForwarder;
-import com.googlesource.gerrit.plugins.multisite.forwarder.StreamEventForwarder;
-import com.googlesource.gerrit.plugins.multisite.forwarder.broker.BrokerCacheEvictionForwarder;
-import com.googlesource.gerrit.plugins.multisite.forwarder.broker.BrokerIndexEventForwarder;
-import com.googlesource.gerrit.plugins.multisite.forwarder.broker.BrokerProjectListUpdateForwarder;
-import com.googlesource.gerrit.plugins.multisite.forwarder.broker.BrokerStreamEventForwarder;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
-import com.googlesource.gerrit.plugins.multisite.kafka.consumer.KafkaEventDeserializer;
-import org.apache.kafka.common.serialization.ByteArrayDeserializer;
-import org.apache.kafka.common.serialization.Deserializer;
-
-public class KafkaBrokerModule extends LifecycleModule {
- private KafkaConfiguration config;
-
- @Inject
- public KafkaBrokerModule(KafkaConfiguration config) {
- this.config = config;
- }
-
- @Override
- protected void configure() {
- if (config.kafkaSubscriber().enabled()) {
- bind(new TypeLiteral<Deserializer<byte[]>>() {}).toInstance(new ByteArrayDeserializer());
- bind(new TypeLiteral<Deserializer<SourceAwareEventWrapper>>() {})
- .to(KafkaEventDeserializer.class);
-
- if (config.kafkaSubscriber().enabledEvent(EventTopic.INDEX_TOPIC)) {
- DynamicSet.bind(binder(), AbstractSubcriber.class).to(IndexEventSubscriber.class);
- }
- if (config.kafkaSubscriber().enabledEvent(EventTopic.STREAM_EVENT_TOPIC)) {
- DynamicSet.bind(binder(), AbstractSubcriber.class).to(StreamEventSubscriber.class);
- }
- if (config.kafkaSubscriber().enabledEvent(EventTopic.CACHE_TOPIC)) {
- DynamicSet.bind(binder(), AbstractSubcriber.class).to(CacheEvictionEventSubscriber.class);
- }
- if (config.kafkaSubscriber().enabledEvent(EventTopic.PROJECT_LIST_TOPIC)) {
- DynamicSet.bind(binder(), AbstractSubcriber.class).to(ProjectUpdateEventSubscriber.class);
- }
- }
-
- if (config.kafkaPublisher().enabled()) {
- listener().to(BrokerPublisher.class);
- bind(BrokerSession.class).to(KafkaSession.class);
-
- if (config.kafkaPublisher().enabledEvent(EventTopic.INDEX_TOPIC)) {
- DynamicSet.bind(binder(), IndexEventForwarder.class).to(BrokerIndexEventForwarder.class);
- }
- if (config.kafkaPublisher().enabledEvent(EventTopic.CACHE_TOPIC)) {
- DynamicSet.bind(binder(), CacheEvictionForwarder.class)
- .to(BrokerCacheEvictionForwarder.class);
- }
- if (config.kafkaPublisher().enabledEvent(EventTopic.PROJECT_LIST_TOPIC)) {
- DynamicSet.bind(binder(), ProjectListUpdateForwarder.class)
- .to(BrokerProjectListUpdateForwarder.class);
- }
- if (config.kafkaPublisher().enabledEvent(EventTopic.STREAM_EVENT_TOPIC)) {
- DynamicSet.bind(binder(), StreamEventForwarder.class).to(BrokerStreamEventForwarder.class);
- }
- }
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfiguration.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfiguration.java
deleted file mode 100644
index dee7382..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfiguration.java
+++ /dev/null
@@ -1,283 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka;
-
-import static com.google.common.base.Suppliers.memoize;
-import static com.google.common.base.Suppliers.ofInstance;
-
-import com.google.common.base.CaseFormat;
-import com.google.common.base.Strings;
-import com.google.common.base.Supplier;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.multisite.Configuration;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.UUID;
-import org.apache.kafka.common.serialization.StringSerializer;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Singleton
-public class KafkaConfiguration {
-
- private static final Logger log = LoggerFactory.getLogger(KafkaConfiguration.class);
- static final String KAFKA_PROPERTY_PREFIX = "KafkaProp-";
- static final String KAFKA_SECTION = "kafka";
- static final String ENABLE_KEY = "enabled";
- private static final String DEFAULT_KAFKA_BOOTSTRAP_SERVERS = "localhost:9092";
- private static final boolean DEFAULT_ENABLE_PROCESSING = true;
- private static final int DEFAULT_POLLING_INTERVAL_MS = 1000;
-
- private final Supplier<KafkaSubscriber> subscriber;
- private final Supplier<Kafka> kafka;
- private final Supplier<KafkaPublisher> publisher;
-
- @Inject
- public KafkaConfiguration(Configuration configuration) {
- Supplier<Config> lazyCfg = lazyLoad(configuration.getMultiSiteConfig());
- kafka = memoize(() -> new Kafka(lazyCfg));
- publisher = memoize(() -> new KafkaPublisher(lazyCfg));
- subscriber = memoize(() -> new KafkaSubscriber(lazyCfg));
- }
-
- public Kafka getKafka() {
- return kafka.get();
- }
-
- public KafkaSubscriber kafkaSubscriber() {
- return subscriber.get();
- }
-
- private static void applyKafkaConfig(
- Supplier<Config> configSupplier, String subsectionName, Properties target) {
- Config config = configSupplier.get();
- for (String section : config.getSubsections(KAFKA_SECTION)) {
- if (section.equals(subsectionName)) {
- for (String name : config.getNames(KAFKA_SECTION, section, true)) {
- if (name.startsWith(KAFKA_PROPERTY_PREFIX)) {
- Object value = config.getString(KAFKA_SECTION, subsectionName, name);
- String configProperty = name.replaceFirst(KAFKA_PROPERTY_PREFIX, "");
- String propName =
- CaseFormat.LOWER_CAMEL
- .to(CaseFormat.LOWER_HYPHEN, configProperty)
- .replaceAll("-", ".");
- log.info("[{}] Setting kafka property: {} = {}", subsectionName, propName, value);
- target.put(propName, value);
- }
- }
- }
- }
- target.put(
- "bootstrap.servers",
- getString(
- configSupplier,
- KAFKA_SECTION,
- null,
- "bootstrapServers",
- DEFAULT_KAFKA_BOOTSTRAP_SERVERS));
- }
-
- private static String getString(
- Supplier<Config> cfg, String section, String subsection, String name, String defaultValue) {
- String value = cfg.get().getString(section, subsection, name);
- if (!Strings.isNullOrEmpty(value)) {
- return value;
- }
- return defaultValue;
- }
-
- private static Map<EventTopic, Boolean> eventsEnabled(
- Supplier<Config> config, String subsection) {
- Map<EventTopic, Boolean> eventsEnabled = new HashMap<>();
- for (EventTopic topic : EventTopic.values()) {
- eventsEnabled.put(
- topic,
- config
- .get()
- .getBoolean(
- KAFKA_SECTION, subsection, topic.enabledKey(), DEFAULT_ENABLE_PROCESSING));
- }
- return eventsEnabled;
- }
-
- public KafkaPublisher kafkaPublisher() {
- return publisher.get();
- }
-
- private Supplier<Config> lazyLoad(Config config) {
- if (config instanceof FileBasedConfig) {
- return memoize(
- () -> {
- FileBasedConfig fileConfig = (FileBasedConfig) config;
- String fileConfigFileName = fileConfig.getFile().getPath();
- try {
- log.info("Loading configuration from {}", fileConfigFileName);
- fileConfig.load();
- } catch (IOException | ConfigInvalidException e) {
- log.error("Unable to load configuration from " + fileConfigFileName, e);
- }
- return fileConfig;
- });
- }
- return ofInstance(config);
- }
-
- public static class Kafka {
- private final Map<EventTopic, String> eventTopics;
- private final String bootstrapServers;
-
- Kafka(Supplier<Config> config) {
- this.bootstrapServers =
- getString(
- config, KAFKA_SECTION, null, "bootstrapServers", DEFAULT_KAFKA_BOOTSTRAP_SERVERS);
-
- this.eventTopics = new HashMap<>();
- for (EventTopic eventTopic : EventTopic.values()) {
- eventTopics.put(
- eventTopic,
- getString(config, KAFKA_SECTION, null, eventTopic.topicAliasKey(), eventTopic.topic()));
- }
- }
-
- public String getTopicAlias(EventTopic topic) {
- return eventTopics.get(topic);
- }
-
- public String getBootstrapServers() {
- return bootstrapServers;
- }
-
- private static String getString(
- Supplier<Config> cfg, String section, String subsection, String name, String defaultValue) {
- String value = cfg.get().getString(section, subsection, name);
- if (!Strings.isNullOrEmpty(value)) {
- return value;
- }
- return defaultValue;
- }
- }
-
- public static class KafkaPublisher extends Properties {
- private static final long serialVersionUID = 0L;
-
- public static final String KAFKA_STRING_SERIALIZER = StringSerializer.class.getName();
-
- public static final String KAFKA_PUBLISHER_SUBSECTION = "publisher";
- public static final boolean DEFAULT_BROKER_ENABLED = false;
-
- private final boolean enabled;
- private final Map<EventTopic, Boolean> eventsEnabled;
-
- private KafkaPublisher(Supplier<Config> cfg) {
- enabled =
- cfg.get()
- .getBoolean(
- KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, ENABLE_KEY, DEFAULT_BROKER_ENABLED);
-
- eventsEnabled = eventsEnabled(cfg, KAFKA_PUBLISHER_SUBSECTION);
-
- if (enabled) {
- setDefaults();
- applyKafkaConfig(cfg, KAFKA_PUBLISHER_SUBSECTION, this);
- }
- }
-
- private void setDefaults() {
- put("acks", "all");
- put("retries", 10);
- put("batch.size", 16384);
- put("linger.ms", 1);
- put("buffer.memory", 33554432);
- put("key.serializer", KAFKA_STRING_SERIALIZER);
- put("value.serializer", KAFKA_STRING_SERIALIZER);
- put("reconnect.backoff.ms", 5000L);
- }
-
- public boolean enabled() {
- return enabled;
- }
-
- public boolean enabledEvent(EventTopic eventType) {
- return eventsEnabled.get(eventType);
- }
- }
-
- public static class KafkaSubscriber extends Properties {
- private static final long serialVersionUID = 1L;
-
- static final String KAFKA_SUBSCRIBER_SUBSECTION = "subscriber";
-
- private final boolean enabled;
- private final Integer pollingInterval;
- private Map<EventTopic, Boolean> eventsEnabled;
- private final Config cfg;
-
- public KafkaSubscriber(Supplier<Config> configSupplier) {
- this.cfg = configSupplier.get();
-
- this.pollingInterval =
- cfg.getInt(
- KAFKA_SECTION,
- KAFKA_SUBSCRIBER_SUBSECTION,
- "pollingIntervalMs",
- DEFAULT_POLLING_INTERVAL_MS);
-
- enabled = cfg.getBoolean(KAFKA_SECTION, KAFKA_SUBSCRIBER_SUBSECTION, ENABLE_KEY, false);
-
- eventsEnabled = eventsEnabled(configSupplier, KAFKA_SUBSCRIBER_SUBSECTION);
-
- if (enabled) {
- applyKafkaConfig(configSupplier, KAFKA_SUBSCRIBER_SUBSECTION, this);
- }
- }
-
- public boolean enabled() {
- return enabled;
- }
-
- public boolean enabledEvent(EventTopic topic) {
- return eventsEnabled.get(topic);
- }
-
- public Properties initPropsWith(UUID instanceId) {
- String groupId =
- getString(
- cfg, KAFKA_SECTION, KAFKA_SUBSCRIBER_SUBSECTION, "groupId", instanceId.toString());
- this.put("group.id", groupId);
-
- return this;
- }
-
- public Integer getPollingInterval() {
- return pollingInterval;
- }
-
- private String getString(
- Config cfg, String section, String subsection, String name, String defaultValue) {
- String value = cfg.getString(section, subsection, name);
- if (!Strings.isNullOrEmpty(value)) {
- return value;
- }
- return defaultValue;
- }
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaConsumerFactory.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaConsumerFactory.java
deleted file mode 100644
index 9a5e19f..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaConsumerFactory.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka.consumer;
-
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration;
-import java.util.UUID;
-import org.apache.kafka.clients.consumer.Consumer;
-import org.apache.kafka.clients.consumer.KafkaConsumer;
-import org.apache.kafka.common.serialization.ByteArrayDeserializer;
-import org.apache.kafka.common.serialization.Deserializer;
-
-@Singleton
-public class KafkaConsumerFactory {
- private KafkaConfiguration config;
-
- @Inject
- public KafkaConsumerFactory(KafkaConfiguration configuration) {
- this.config = configuration;
- }
-
- public Consumer<byte[], byte[]> create(Deserializer<byte[]> keyDeserializer, UUID instanceId) {
- return new KafkaConsumer<>(
- config.kafkaSubscriber().initPropsWith(instanceId),
- keyDeserializer,
- new ByteArrayDeserializer());
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventDeserializer.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventDeserializer.java
deleted file mode 100644
index 38b8d61..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventDeserializer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka.consumer;
-
-import com.google.gson.Gson;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import java.util.Map;
-import org.apache.kafka.common.serialization.Deserializer;
-import org.apache.kafka.common.serialization.StringDeserializer;
-
-@Singleton
-public class KafkaEventDeserializer implements Deserializer<SourceAwareEventWrapper> {
-
- private final StringDeserializer stringDeserializer = new StringDeserializer();
- private Gson gson;
-
- // To be used when providing this deserializer with class name (then need to add a configuration
- // entry to set the gson.provider
- public KafkaEventDeserializer() {}
-
- @Inject
- public KafkaEventDeserializer(@BrokerGson Gson gson) {
- this.gson = gson;
- }
-
- @Override
- public void configure(Map<String, ?> configs, boolean isKey) {}
-
- @Override
- public SourceAwareEventWrapper deserialize(String topic, byte[] data) {
- final SourceAwareEventWrapper result =
- gson.fromJson(stringDeserializer.deserialize(topic, data), SourceAwareEventWrapper.class);
-
- result.validate();
-
- return result;
- }
-
- @Override
- public void close() {}
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventSubscriber.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventSubscriber.java
deleted file mode 100644
index c72fa0d..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventSubscriber.java
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka.consumer;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.server.util.ManualRequestContext;
-import com.google.gerrit.server.util.OneOffRequestContext;
-import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.multisite.InstanceId;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import com.googlesource.gerrit.plugins.multisite.consumer.SubscriberMetrics;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
-import com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration;
-import java.time.Duration;
-import java.util.Collections;
-import java.util.UUID;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.apache.kafka.clients.consumer.Consumer;
-import org.apache.kafka.clients.consumer.ConsumerRecords;
-import org.apache.kafka.common.errors.WakeupException;
-import org.apache.kafka.common.serialization.Deserializer;
-
-public class KafkaEventSubscriber {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final Consumer<byte[], byte[]> consumer;
- private final OneOffRequestContext oneOffCtx;
- private final AtomicBoolean closed = new AtomicBoolean(false);
-
- private final Deserializer<SourceAwareEventWrapper> valueDeserializer;
- private final KafkaConfiguration configuration;
- private final SubscriberMetrics subscriberMetrics;
-
- @Inject
- public KafkaEventSubscriber(
- KafkaConfiguration configuration,
- KafkaConsumerFactory consumerFactory,
- Deserializer<byte[]> keyDeserializer,
- Deserializer<SourceAwareEventWrapper> valueDeserializer,
- @InstanceId UUID instanceId,
- OneOffRequestContext oneOffCtx,
- SubscriberMetrics subscriberMetrics) {
-
- this.configuration = configuration;
- this.oneOffCtx = oneOffCtx;
- this.subscriberMetrics = subscriberMetrics;
-
- final ClassLoader previousClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(KafkaEventSubscriber.class.getClassLoader());
- this.consumer = consumerFactory.create(keyDeserializer, instanceId);
- } finally {
- Thread.currentThread().setContextClassLoader(previousClassLoader);
- }
- this.valueDeserializer = valueDeserializer;
- }
-
- public void subscribe(
- EventTopic evenTopic, java.util.function.Consumer<SourceAwareEventWrapper> messageProcessor) {
- try {
- final String topic = configuration.getKafka().getTopicAlias(evenTopic);
- logger.atInfo().log(
- "Kafka consumer subscribing to topic alias [%s] for event topic [%s]", topic, evenTopic);
- consumer.subscribe(Collections.singleton(topic));
- while (!closed.get()) {
- ConsumerRecords<byte[], byte[]> consumerRecords =
- consumer.poll(Duration.ofMillis(configuration.kafkaSubscriber().getPollingInterval()));
- consumerRecords.forEach(
- consumerRecord -> {
- try (ManualRequestContext ctx = oneOffCtx.open()) {
- SourceAwareEventWrapper event =
- valueDeserializer.deserialize(consumerRecord.topic(), consumerRecord.value());
- messageProcessor.accept(event);
- } catch (Exception e) {
- logger.atSevere().withCause(e).log(
- "Malformed event '%s': [Exception: %s]",
- new String(consumerRecord.value(), UTF_8));
- subscriberMetrics.incrementSubscriberFailedToConsumeMessage();
- }
- });
- }
- } catch (WakeupException e) {
- // Ignore exception if closing
- if (!closed.get()) throw e;
- } catch (Exception e) {
- subscriberMetrics.incrementSubscriberFailedToPollMessages();
- throw e;
- } finally {
- consumer.close();
- }
- }
-
- public void shutdown() {
- closed.set(true);
- consumer.wakeup();
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
index 4e6bef5..cfe585d 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidator.java
@@ -19,7 +19,7 @@
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.multisite.LockWrapper;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.OutOfSyncException;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement.EnforcePolicy;
import java.io.IOException;
@@ -29,6 +29,8 @@
import java.util.stream.Stream;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdRef;
+import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.transport.ReceiveCommand;
@@ -99,6 +101,13 @@
refsToUpdate = compareAndGetLatestLocalRefs(refsToUpdate, locks);
delegateUpdate.invoke();
updateSharedRefDb(batchRefUpdate.getCommands().stream(), refsToUpdate);
+ } catch (OutOfSyncException e) {
+ List<ReceiveCommand> receiveCommands = batchRefUpdate.getCommands();
+ logger.atWarning().withCause(e).log(
+ String.format(
+ "Batch ref-update failing because node is out of sync with the shared ref-db. Set all commands Result to LOCK_FAILURE [%d]",
+ receiveCommands.size()));
+ receiveCommands.forEach((command) -> command.setResult(ReceiveCommand.Result.LOCK_FAILURE));
}
}
@@ -124,7 +133,7 @@
try {
switch (command.getType()) {
case CREATE:
- return new RefPair(SharedRefDatabase.nullRef(command.getRefName()), getNewRef(command));
+ return new RefPair(nullRef(command.getRefName()), getNewRef(command));
case UPDATE:
case UPDATE_NONFASTFORWARD:
@@ -155,4 +164,8 @@
}
return latestRefsToUpdate;
}
+
+ private static final Ref nullRef(String refName) {
+ return new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, refName, ObjectId.zeroId());
+ }
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefDatabase.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefDatabase.java
index 630b091..e1d1c65 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefDatabase.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefDatabase.java
@@ -99,11 +99,6 @@
}
@Override
- public Ref getRef(String name) throws IOException {
- return refDatabase.getRef(name);
- }
-
- @Override
public String toString() {
return refDatabase.toString();
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilter.java
index 5f25607..42f7194 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilter.java
@@ -14,16 +14,18 @@
package com.googlesource.gerrit.plugins.multisite.validation;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedLockException;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
import com.googlesource.gerrit.plugins.replication.ReplicationPushFilter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
+import org.eclipse.jgit.lib.ObjectIdRef;
+import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -52,13 +54,15 @@
String ref = refUpdate.getSrcRef();
try {
if (sharedRefDb.isUpToDate(
- projectName, SharedRefDatabase.newRef(ref, refUpdate.getNewObjectId()))) {
+ new Project.NameKey(projectName),
+ new ObjectIdRef.Unpeeled(
+ Ref.Storage.NETWORK, ref, refUpdate.getNewObjectId()))) {
return true;
}
repLog.warn(
"{} is not up-to-date with the shared-refdb and thus will NOT BE replicated",
refUpdate);
- } catch (SharedLockException e) {
+ } catch (GlobalRefDbLockException e) {
repLog.warn(
"{} is locked on shared-refdb and thus will NOT BE replicated", refUpdate);
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectDeletedSharedDbCleanup.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectDeletedSharedDbCleanup.java
index 78e1cea..9c93793 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectDeletedSharedDbCleanup.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectDeletedSharedDbCleanup.java
@@ -14,11 +14,12 @@
package com.googlesource.gerrit.plugins.multisite.validation;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.events.ProjectDeletedListener;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
-import java.io.IOException;
public class ProjectDeletedSharedDbCleanup implements ProjectDeletedListener {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -41,8 +42,8 @@
"Deleting project '%s'. Will perform a cleanup in Shared-Ref database.", projectName);
try {
- sharedDb.removeProject(projectName);
- } catch (IOException e) {
+ sharedDb.remove(new Project.NameKey(projectName));
+ } catch (GlobalRefDbSystemError e) {
validationMetrics.incrementSplitBrain();
logger.atSevere().withCause(e).log(
"Project '%s' deleted from GIT but it was not able to cleanup"
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
index 82d4ff0..1f87b77 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidator.java
@@ -14,10 +14,10 @@
package com.googlesource.gerrit.plugins.multisite.validation;
-import static com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase.nullRef;
-
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
import com.google.common.base.MoreObjects;
import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.reviewdb.client.Project;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.googlesource.gerrit.plugins.multisite.LockWrapper;
@@ -25,12 +25,12 @@
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.OutOfSyncException;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedDbSplitBrainException;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedLockException;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement.EnforcePolicy;
import java.io.IOException;
import java.util.HashMap;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
@@ -127,6 +127,11 @@
updateSharedDbOrThrowExceptionFor(refPairForUpdate);
}
return result;
+ } catch (OutOfSyncException e) {
+ logger.atWarning().withCause(e).log(
+ String.format("Local node is out of sync with ref-db: %s", e.getMessage()));
+
+ return RefUpdate.Result.LOCK_FAILURE;
}
}
@@ -144,8 +149,10 @@
projectName, refPair.getName(), refPair.putValue);
boolean succeeded;
try {
- succeeded = sharedRefDb.compareAndPut(projectName, refPair.compareRef, refPair.putValue);
- } catch (IOException e) {
+ succeeded =
+ sharedRefDb.compareAndPut(
+ new Project.NameKey(projectName), refPair.compareRef, refPair.putValue);
+ } catch (GlobalRefDbSystemError e) {
throw new SharedDbSplitBrainException(errorMessage, e);
}
@@ -166,14 +173,17 @@
String.format("%s-%s", projectName, refName),
() ->
lockWrapperFactory.create(
- projectName, refName, sharedRefDb.lockRef(projectName, refName)));
+ projectName,
+ refName,
+ sharedRefDb.lockRef(new Project.NameKey(projectName), refName)));
RefPair latestRefPair = getLatestLocalRef(refPair);
- if (sharedRefDb.isUpToDate(projectName, latestRefPair.compareRef)) {
+ if (sharedRefDb.isUpToDate(new Project.NameKey(projectName), latestRefPair.compareRef)) {
return latestRefPair;
}
- if (isNullRef(latestRefPair.compareRef) || sharedRefDb.exists(projectName, refName)) {
+ if (isNullRef(latestRefPair.compareRef)
+ || sharedRefDb.exists(new Project.NameKey(projectName), refName)) {
validationMetrics.incrementSplitBrainPrevention();
softFailBasedOnEnforcement(
@@ -193,6 +203,10 @@
latestRef == null ? nullRef(refPair.getName()) : latestRef, refPair.putValue);
}
+ private Ref nullRef(String name) {
+ return new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, name, ObjectId.zeroId());
+ }
+
protected boolean isSuccessful(RefUpdate.Result result) {
switch (result) {
case NEW:
@@ -219,7 +233,7 @@
}
protected Ref getCurrentRef(String refName) throws IOException {
- return MoreObjects.firstNonNull(refDb.getRef(refName), SharedRefDatabase.nullRef(refName));
+ return MoreObjects.firstNonNull(refDb.getRef(refName), nullRef(refName));
}
public static class CloseableSet<T extends AutoCloseable> implements AutoCloseable {
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
index e331819..1719f38 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ValidationModule.java
@@ -16,19 +16,16 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.extensions.events.ProjectDeletedListener;
import com.google.gerrit.extensions.registration.DynamicItem;
-import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Scopes;
import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.LockWrapper;
import com.googlesource.gerrit.plugins.multisite.Log4jSharedRefLogger;
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.SharedRefLogger;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.CustomSharedRefEnforcementByProject;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.NoopSharedRefDatabase;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
import com.googlesource.gerrit.plugins.replication.ReplicationExtensionPointModule;
import com.googlesource.gerrit.plugins.replication.ReplicationPushFilter;
@@ -37,23 +34,16 @@
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final Configuration cfg;
- private final boolean disableGitRepositoryValidation;
- public ValidationModule(Configuration cfg, boolean disableGitRepositoryValidation) {
+ public ValidationModule(Configuration cfg) {
this.cfg = cfg;
- this.disableGitRepositoryValidation = disableGitRepositoryValidation;
}
@Override
protected void configure() {
install(new ReplicationExtensionPointModule());
- DynamicItem.itemOf(binder(), SharedRefDatabase.class);
- DynamicItem.bind(binder(), SharedRefDatabase.class)
- .to(NoopSharedRefDatabase.class)
- .in(Scopes.SINGLETON);
- logger.atInfo().log("Shared ref-db engine: none");
-
+ bind(SharedRefDatabaseWrapper.class).in(Scopes.SINGLETON);
bind(SharedRefLogger.class).to(Log4jSharedRefLogger.class);
factory(LockWrapper.Factory.class);
@@ -64,12 +54,10 @@
factory(RefUpdateValidator.Factory.class);
factory(BatchRefUpdateValidator.Factory.class);
+ bind(GitRepositoryManager.class).to(MultiSiteGitRepositoryManager.class);
DynamicItem.bind(binder(), ReplicationPushFilter.class)
.to(MultisiteReplicationPushFilter.class);
- if (!disableGitRepositoryValidation) {
- bind(GitRepositoryManager.class).to(MultiSiteGitRepositoryManager.class);
- }
if (cfg.getSharedRefDb().getEnforcementRules().isEmpty()) {
bind(SharedRefEnforcement.class).to(DefaultSharedRefEnforcement.class).in(Scopes.SINGLETON);
} else {
@@ -77,6 +65,5 @@
.to(CustomSharedRefEnforcementByProject.class)
.in(Scopes.SINGLETON);
}
- DynamicSet.bind(binder(), ProjectDeletedListener.class).to(ProjectDeletedSharedDbCleanup.class);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ZkConnectionConfig.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ZkConnectionConfig.java
deleted file mode 100644
index 0339f01..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/ZkConnectionConfig.java
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (C) 2019 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.multisite.validation;
-
-import org.apache.curator.RetryPolicy;
-
-public class ZkConnectionConfig {
-
- public final RetryPolicy curatorRetryPolicy;
- public final Long transactionLockTimeout;
-
- public ZkConnectionConfig(RetryPolicy curatorRetryPolicy, Long transactionLockTimeout) {
- this.curatorRetryPolicy = curatorRetryPolicy;
- this.transactionLockTimeout = transactionLockTimeout;
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/NoopSharedRefDatabase.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/NoopSharedRefDatabase.java
index e40688f..aa15108 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/NoopSharedRefDatabase.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/NoopSharedRefDatabase.java
@@ -14,30 +14,37 @@
package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDatabase;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
+import com.google.gerrit.reviewdb.client.Project;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
-public class NoopSharedRefDatabase implements SharedRefDatabase {
+public class NoopSharedRefDatabase implements GlobalRefDatabase {
+
@Override
- public boolean isUpToDate(String project, Ref ref) {
+ public boolean isUpToDate(Project.NameKey project, Ref ref) throws GlobalRefDbLockException {
return true;
}
@Override
- public boolean compareAndPut(String project, Ref currRef, ObjectId newRefValue) {
+ public boolean compareAndPut(Project.NameKey project, Ref currRef, ObjectId newRefValue)
+ throws GlobalRefDbSystemError {
return true;
}
@Override
- public AutoCloseable lockRef(String project, String refName) {
+ public AutoCloseable lockRef(Project.NameKey project, String refName)
+ throws GlobalRefDbLockException {
return () -> {};
}
@Override
- public boolean exists(String project, String refName) {
+ public boolean exists(Project.NameKey project, String refName) {
return false;
}
@Override
- public void removeProject(String project) {}
+ public void remove(Project.NameKey project) throws GlobalRefDbSystemError {}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/SharedRefDatabase.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/SharedRefDatabase.java
deleted file mode 100644
index a93efcf..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/SharedRefDatabase.java
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (C) 2019 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.multisite.validation.dfsrefdb;
-
-import java.io.IOException;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectIdRef;
-import org.eclipse.jgit.lib.Ref;
-
-public interface SharedRefDatabase {
-
- /** A null ref that isn't associated to any name. */
- Ref NULL_REF = nullRef(null);
-
- /**
- * Create a new in-memory ref name associated with an NULL object id.
- *
- * @param refName ref name
- * @return the new NULL ref object
- */
- static Ref nullRef(String refName) {
- return new Ref() {
-
- @Override
- public String getName() {
- return refName;
- }
-
- @Override
- public boolean isSymbolic() {
- return false;
- }
-
- @Override
- public Ref getLeaf() {
- return null;
- }
-
- @Override
- public Ref getTarget() {
- return null;
- }
-
- @Override
- public ObjectId getObjectId() {
- return ObjectId.zeroId();
- }
-
- @Override
- public ObjectId getPeeledObjectId() {
- return ObjectId.zeroId();
- }
-
- @Override
- public boolean isPeeled() {
- return false;
- }
-
- @Override
- public Storage getStorage() {
- return Storage.NEW;
- }
- };
- }
-
- /**
- * Create a new in-memory Ref name associated with an objectId.
- *
- * @param refName ref name
- * @param objectId object id
- */
- static Ref newRef(String refName, ObjectId objectId) {
- return new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, refName, objectId);
- }
-
- /**
- * Verify in shared db if Ref is the most recent
- *
- * @param project project name of the ref
- * @param ref to be checked against shared-ref db
- * @return true if it is; false otherwise
- * @throws SharedLockException if there was a problem locking the resource
- */
- boolean isUpToDate(String project, Ref ref) throws SharedLockException;
-
- /**
- * Compare a reference, and put if it matches.
- *
- * <p>Two reference match if and only if they satisfy the following:
- *
- * <ul>
- * <li>If one reference is a symbolic ref, the other one should be a symbolic ref.
- * <li>If both are symbolic refs, the target names should be same.
- * <li>If both are object ID refs, the object IDs should be same.
- * </ul>
- *
- * @param project project name of the ref
- * @param currRef old value to compare to. If the reference is expected to not exist the old value
- * has a storage of {@link org.eclipse.jgit.lib.Ref.Storage#NEW} and an ObjectId value of
- * {@code null}.
- * @param newRefValue new reference to store.
- * @return true if the put was successful; false otherwise.
- * @throws java.io.IOException the reference cannot be put due to a system error.
- */
- boolean compareAndPut(String project, Ref currRef, ObjectId newRefValue) throws IOException;
-
- /**
- * Lock a reference for writing.
- *
- * @param project project name
- * @param refName ref to lock
- * @return lock object
- * @throws SharedLockException if the lock cannot be obtained
- */
- AutoCloseable lockRef(String project, String refName) throws SharedLockException;
-
- /**
- * Verify if the DB contains a value for the specific project and ref name
- *
- * @param project
- * @param refName
- * @return true if the ref exists on the project
- */
- boolean exists(String project, String refName);
-
- /**
- * Clean project path from SharedRefDatabase
- *
- * @param project project name
- * @throws IOException
- */
- void removeProject(String project) throws IOException;
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabase.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabase.java
deleted file mode 100644
index 1179045..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabase.java
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (C) 2012 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.multisite.validation.dfsrefdb.zookeeper;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-
-import com.google.common.flogger.FluentLogger;
-import com.google.inject.Inject;
-import com.googlesource.gerrit.plugins.multisite.validation.ZkConnectionConfig;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedLockException;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import org.apache.curator.RetryPolicy;
-import org.apache.curator.framework.CuratorFramework;
-import org.apache.curator.framework.recipes.atomic.AtomicValue;
-import org.apache.curator.framework.recipes.atomic.DistributedAtomicValue;
-import org.apache.curator.framework.recipes.locks.InterProcessMutex;
-import org.apache.curator.framework.recipes.locks.Locker;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-
-public class ZkSharedRefDatabase implements SharedRefDatabase {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final CuratorFramework client;
- private final RetryPolicy retryPolicy;
-
- private final Long transactionLockTimeOut;
-
- @Inject
- public ZkSharedRefDatabase(CuratorFramework client, ZkConnectionConfig connConfig) {
- this.client = client;
- this.retryPolicy = connConfig.curatorRetryPolicy;
- this.transactionLockTimeOut = connConfig.transactionLockTimeout;
- }
-
- @Override
- public boolean isUpToDate(String project, Ref ref) throws SharedLockException {
- if (!exists(project, ref.getName())) {
- return true;
- }
-
- try {
- final byte[] valueInZk = client.getData().forPath(pathFor(project, ref.getName()));
-
- // Assuming this is a delete node NULL_REF
- if (valueInZk == null) {
- logger.atInfo().log(
- "%s:%s not found in Zookeeper, assumed as delete node NULL_REF",
- project, ref.getName());
- return false;
- }
-
- ObjectId objectIdInSharedRefDb = readObjectId(valueInZk);
- Boolean isUpToDate = objectIdInSharedRefDb.equals(ref.getObjectId());
-
- if (!isUpToDate) {
- logger.atWarning().log(
- "%s:%s is out of sync: local=%s zk=%s",
- project, ref.getName(), ref.getObjectId(), objectIdInSharedRefDb);
- }
-
- return isUpToDate;
- } catch (Exception e) {
- throw new SharedLockException(project, ref.getName(), e);
- }
- }
-
- @Override
- public void removeProject(String project) throws IOException {
- try {
- client.delete().deletingChildrenIfNeeded().forPath("/" + project);
- } catch (Exception e) {
- throw new IOException(String.format("Not able to delete project '%s'", project), e);
- }
- }
-
- @Override
- public boolean exists(String project, String refName) throws ZookeeperRuntimeException {
- try {
- return client.checkExists().forPath(pathFor(project, refName)) != null;
- } catch (Exception e) {
- throw new ZookeeperRuntimeException("Failed to check if path exists in Zookeeper", e);
- }
- }
-
- @Override
- public Locker lockRef(String project, String refName) throws SharedLockException {
- InterProcessMutex refPathMutex =
- new InterProcessMutex(client, "/locks" + pathFor(project, refName));
- try {
- return new Locker(refPathMutex, transactionLockTimeOut, MILLISECONDS);
- } catch (Exception e) {
- throw new SharedLockException(project, refName, e);
- }
- }
-
- @Override
- public boolean compareAndPut(String projectName, Ref oldRef, ObjectId newRefValue)
- throws IOException {
-
- final DistributedAtomicValue distributedRefValue =
- new DistributedAtomicValue(client, pathFor(projectName, oldRef), retryPolicy);
-
- try {
- if (oldRef == NULL_REF) {
- return distributedRefValue.initialize(writeObjectId(newRefValue));
- }
- final ObjectId newValue = newRefValue == null ? ObjectId.zeroId() : newRefValue;
- final AtomicValue<byte[]> newDistributedValue =
- distributedRefValue.compareAndSet(
- writeObjectId(oldRef.getObjectId()), writeObjectId(newValue));
-
- if (!newDistributedValue.succeeded() && refNotInZk(projectName, oldRef)) {
- return distributedRefValue.initialize(writeObjectId(newRefValue));
- }
-
- return newDistributedValue.succeeded();
- } catch (Exception e) {
- logger.atWarning().withCause(e).log(
- "Error trying to perform CAS at path %s", pathFor(projectName, oldRef));
- throw new IOException(
- String.format("Error trying to perform CAS at path %s", pathFor(projectName, oldRef)), e);
- }
- }
-
- private boolean refNotInZk(String projectName, Ref oldRef) throws Exception {
- return client.checkExists().forPath(pathFor(projectName, oldRef)) == null;
- }
-
- static String pathFor(String projectName, Ref oldRef) {
- return pathFor(projectName, oldRef.getName());
- }
-
- static String pathFor(String projectName, String refName) {
- return "/" + projectName + "/" + refName;
- }
-
- static ObjectId readObjectId(byte[] value) {
- return ObjectId.fromString(value, 0);
- }
-
- static byte[] writeObjectId(ObjectId value) {
- return ObjectId.toString(value).getBytes(StandardCharsets.US_ASCII);
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkValidationModule.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkValidationModule.java
deleted file mode 100644
index f83b4d9..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkValidationModule.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2019 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.multisite.validation.dfsrefdb.zookeeper;
-
-import com.google.gerrit.extensions.registration.DynamicItem;
-import com.google.inject.AbstractModule;
-import com.google.inject.Inject;
-import com.google.inject.Scopes;
-import com.googlesource.gerrit.plugins.multisite.Configuration;
-import com.googlesource.gerrit.plugins.multisite.ZookeeperConfig;
-import com.googlesource.gerrit.plugins.multisite.validation.ZkConnectionConfig;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
-import org.apache.curator.framework.CuratorFramework;
-
-public class ZkValidationModule extends AbstractModule {
-
- private ZookeeperConfig cfg;
-
- @Inject
- public ZkValidationModule(Configuration cfg) {
- this.cfg = new ZookeeperConfig(cfg.getMultiSiteConfig());
- }
-
- @Override
- protected void configure() {
- DynamicItem.bind(binder(), SharedRefDatabase.class)
- .to(ZkSharedRefDatabase.class)
- .in(Scopes.SINGLETON);
- bind(CuratorFramework.class).toInstance(cfg.buildCurator());
-
- bind(ZkConnectionConfig.class)
- .toInstance(
- new ZkConnectionConfig(cfg.buildCasRetryPolicy(), cfg.getZkInterProcessLockTimeOut()));
- }
-}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZookeeperRuntimeException.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZookeeperRuntimeException.java
deleted file mode 100644
index 9f2951b..0000000
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZookeeperRuntimeException.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (C) 2019 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.multisite.validation.dfsrefdb.zookeeper;
-
-/** Unable to communicate with Zookeeper */
-public class ZookeeperRuntimeException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- public ZookeeperRuntimeException(String description, Throwable t) {
- super(description, t);
- }
-}
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index 264c8e9..42249b1 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -3,12 +3,13 @@
the masters happens using the replication plugin and an external message
broker.
-This plugin allows Gerrit to publish and to consume events over a Kafka
+This plugin allows Gerrit to publish and to consume events over a
message broker for aligning with the other masters over different sites.
The masters must be:
-* migrated to NoteDb
+* events-broker library must be installed as a library module in the
+ `$GERRIT_SITE/lib` directory of all the masters
* connected to the same message broker
* behind a load balancer (e.g., HAProxy)
@@ -57,34 +58,12 @@
Prerequisites:
-* Kafka message broker deployed in a multi-master setup across all the sites
+* Message broker deployed in a multi-master setup across all the sites
For the masters:
* Install and configure @PLUGIN@ plugin
-Here is an example of minimal @PLUGIN@.config:
-
-For all the masters on all the sites:
-
-```
-[kafka]
- bootstrapServers = kafka-1:9092,kafka-2:9092,kafka-3:9092
- eventTopic = gerrit_index
-
-[kafka "publisher"]
- enable = true
- indexEventTopic = gerrit_index
- streamEventTopic = gerrit_stream
- cacheEvictionEventTopic = gerrit_cache_eviction
-
-[kafka "subscriber"]
- enable = true
- pollingIntervalMs = 1000
- autoCommitIntervalMs = 1000
-```
-
-
For further information and supported options, refer to [config](config.md)
documentation.
@@ -95,21 +74,29 @@
### Broker message publisher
* Broker message published count
-`metric=multi_site/broker/broker_message_publisher_counter/broker_msg_publisher_counter, type=com.codahale.metrics.Meter`
+`metric=plugins/multi-site/multi_site/broker/broker_message_publisher_counter/broker_msg_publisher_counter, type=com.codahale.metrics.Meter`
* Broker failed to publish message count
-`metric=multi_site/broker/broker_message_publisher_failure_counter/broker_msg_publisher_failure_counter, type=com.codahale.metrics.Meter`
+`metric=plugins/multi-site/multi_site/broker/broker_message_publisher_failure_counter/broker_msg_publisher_failure_counter, type=com.codahale.metrics.Meter`
### Message subscriber
* Subscriber message consumed count
-`multi_site/subscriber/subscriber_message_consumer_counter/subscriber_msg_consumer_counter, type=com.codahale.metrics.Meter`
+`metric=plugins/multi-site/multi_site/subscriber/subscriber_message_consumer_counter/subscriber_msg_consumer_counter, type=com.codahale.metrics.Meter`
* Subscriber failed to consume message count
-`multi_site/subscriber/subscriber_message_consumer_failure_counter/subscriber_msg_consumer_failure_counter, type=com.codahale.metrics.Meter`
+`metric=plugins/multi-site/multi_site/subscriber/subscriber_message_consumer_failure_counter/subscriber_msg_consumer_failure_counter, type=com.codahale.metrics.Meter`
* Subscriber failed to poll messages count
-`multi_site/subscriber/subscriber_message_consumer_poll_failure_counter/subscriber_msg_consumer_poll_failure_counter, type=com.codahale.metrics.Meter`
+`metric=plugins/multi-site/multi_site/subscriber/subscriber_message_consumer_failure_counter/subscriber_msg_consumer_poll_failure_counter, type=com.codahale.metrics.Meter`
+
+* Subscriber replication status (latest replication Epoch time in seconds) per instance
+
+`metric=plugins/multi-site/multi_site/subscriber/subscriber_replication_status/instance_latest_replication_epochtime_secs, type=com.google.gerrit.metrics.dropwizard.CallbackMetricImpl`
+
+* Subscriber replication status (latest replication Epoch time in seconds) per project
+
+`metric=plugins/multi-site/multi_site/subscriber/subscriber_replication_status/latest_replication_epochtime_secs_<projectName>, type=com.google.gerrit.metrics.dropwizard.CallbackMetricImpl`
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 227d0e8..662f46e 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -3,60 +3,8 @@
=========================
The @PLUGIN@ plugin must be installed as a library module in the
-`$GERRIT_SITE/lib` folder of all the instances and the following fields should
-be specified in the `$site_path/etc/@PLUGIN@.config` file:
-
-File '@PLUGIN@.config'
---------------------
-
-## Sample configuration.
-
-```
-[kafka]
- bootstrapServers = kafka-1:9092,kafka-2:9092,kafka-3:9092
-
- indexEventTopic = gerrit_index
- streamEventTopic = gerrit_stream
- cacheEventTopic = gerrit_cache_eviction
- projectListEventTopic = gerrit_project_list
-
-[kafka "publisher"]
- enabled = true
-
- indexEventEnabled = true
- cacheEventEnabled = true
- projectListEventEnabled = true
- streamEventEnabled = true
-
- KafkaProp-compressionType = none
- KafkaProp-deliveryTimeoutMs = 60000
-
-[kafka "subscriber"]
- enabled = true
- pollingIntervalMs = 1000
-
- KafkaProp-enableAutoCommit = true
- KafkaProp-autoCommitIntervalMs = 1000
- KafkaProp-autoCommitIntervalMs = 5000
-
- indexEventEnabled = true
- cacheEventEnabled = true
- projectListEventEnabled = true
- streamEventEnabled = true
-
-[ref-database "zookeeper"]
- connectString = "localhost:2181"
- rootNode = "/gerrit/multi-site"
- sessionTimeoutMs = 1000
- connectionTimeoutMs = 1000
- retryPolicyBaseSleepTimeMs = 1000
- retryPolicyMaxSleepTimeMs = 3000
- retryPolicyMaxRetries = 3
- casRetryPolicyBaseSleepTimeMs = 100
- casRetryPolicyMaxSleepTimeMs = 100
- casRetryPolicyMaxRetries = 3
- transactionLockTimeoutMs = 1000
-```
+`$GERRIT_SITE/lib` folder of all the instances. Configuration should
+be specified in the `$site_path/etc/@PLUGIN@.config` file.
## Configuration parameters
@@ -106,83 +54,22 @@
: The time interval in milliseconds between subsequent auto-retries.
Defaults to 30000 (30 seconds).
-```kafka.bootstrapServers```
-: List of Kafka broker hosts (host:port) to use for publishing events to the message
- broker
-
-```kafka.indexEventTopic```
-: Name of the Kafka topic to use for publishing indexing events
+```broker.indexEventTopic```
+: Name of the topic to use for publishing indexing events
Defaults to GERRIT.EVENT.INDEX
-```kafka.streamEventTopic```
-: Name of the Kafka topic to use for publishing stream events
+```broker.streamEventTopic```
+: Name of the topic to use for publishing stream events
Defaults to GERRIT.EVENT.STREAM
-```kafka.cacheEventTopic```
-: Name of the Kafka topic to use for publishing cache eviction events
+```broker.cacheEventTopic```
+: Name of the topic to use for publishing cache eviction events
Defaults to GERRIT.EVENT.CACHE
-```kafka.projectListEventTopic```
-: Name of the Kafka topic to use for publishing cache eviction events
+```broker.projectListEventTopic```
+: Name of the topic to use for publishing cache eviction events
Defaults to GERRIT.EVENT.PROJECT.LIST
-```kafka.publisher.indexEventEnabled```
-: Enable publication of index events, ignored when `kafka.publisher.enabled`
- is false
-
- Defaults: true
-
-```kafka.publisher.cacheEventEnabled```
-: Enable publication of cache events, ignored when `kafka.publisher.enabled`
- is false
-
- Defaults: true
-
-```kafka.publisher.projectListEventEnabled```
-: Enable publication of project list events, ignored when `kafka.publisher.enabled`
- is false
-
- Defaults: true
-
-```kafka.publisher.streamEventEnabled```
-: Enable publication of stream events, ignored when `kafka.publisher.enabled`
- is false
-
- Defaults: true
-
-```kafka.subscriber.enabled```
-: Enable consuming of events from Kafka
- Defaults: false
-
-```kafka.subscriber.indexEventEnabled```
-: Enable consumption of index events, ignored when `kafka.subscriber.enabled`
- is false
-
- Defaults: true
-
-```kafka.subscriber.cacheEventEnabled```
-: Enable consumption of cache events, ignored when `kafka.subscriber.enabled`
- is false
-
- Defaults: true
-
-```kafka.subscriber.projectListEventEnabled```
-: Enable consumption of project list events, ignored when `kafka.subscriber.enabled`
- is false
-
- Defaults: true
-
-```kafka.subscriber.streamEventEnabled```
-: Enable consumption of stream events, ignored when `kafka.subscriber.enabled`
- is false
-
- Defaults: true
-
-```kafka.subscriber.pollingIntervalMs```
-: Polling interval in milliseconds for checking incoming events
-
- Defaults: 1000
-
```ref-database.enabled```
: Enable the use of a shared ref-database
Defaults: true
@@ -213,88 +100,4 @@
Relax the alignment with the shared ref-database for AProject on refs/heads/feature.
- Defaults: No rules = All projects are REQUIRED to be consistent on all refs.
-
-```ref-database.zookeeper.connectString```
-: Connection string to Zookeeper
-
-```ref-database.zookeeper.rootNode```
-: Root node to use in Zookeeper to store/retrieve information
-
- Defaults: "/gerrit/multi-site"
-
-
-```ref-database.zookeeper.sessionTimeoutMs```
-: Zookeeper session timeout in milliseconds
-
- Defaults: 1000
-
-```ref-database.zookeeper.connectionTimeoutMs```
-: Zookeeper connection timeout in milliseconds
-
- Defaults: 1000
-
-```ref-database.zookeeper.retryPolicyBaseSleepTimeMs```
-: Configuration for the base sleep timeout in milliseconds of the
- BoundedExponentialBackoffRetry policy used for the Zookeeper connection
-
- Defaults: 1000
-
-```ref-database.zookeeper.retryPolicyMaxSleepTimeMs```
-: Configuration for the maximum sleep timeout in milliseconds of the
- BoundedExponentialBackoffRetry policy used for the Zookeeper connection
-
- Defaults: 3000
-
-```ref-database.zookeeper.retryPolicyMaxRetries```
-: Configuration for the maximum number of retries of the
- BoundedExponentialBackoffRetry policy used for the Zookeeper connection
-
- Defaults: 3
-
-```ref-database.zookeeper.casRetryPolicyBaseSleepTimeMs```
-: Configuration for the base sleep timeout in milliseconds of the
- BoundedExponentialBackoffRetry policy used for the Compare and Swap
- operations on Zookeeper
-
- Defaults: 1000
-
-```ref-database.zookeeper.casRetryPolicyMaxSleepTimeMs```
-: Configuration for the maximum sleep timeout in milliseconds of the
- BoundedExponentialBackoffRetry policy used for the Compare and Swap
- operations on Zookeeper
-
- Defaults: 3000
-
-```ref-database.zookeeper.casRetryPolicyMaxRetries```
-: Configuration for the maximum number of retries of the
- BoundedExponentialBackoffRetry policy used for the Compare and Swap
- operations on Zookeeper
-
- Defaults: 3
-
-```ref-database.zookeeper.transactionLockTimeoutMs```
-: Configuration for the Zookeeper Lock timeout (in milliseconds) used when reading data
- from Zookeeper, applying the git local changes and writing the new objectId
- into Zookeeper
-
- Defaults: 1000
-
-#### Custom kafka properties:
-
-In addition to the above settings, custom Kafka properties can be explicitly set
-for `publisher` and `subscriber`.
-In order to be acknowledged, these properties need to be prefixed with the
-`KafkaProp-` prefix and be formatted using camel case, as follows: `KafkaProp-yourPropertyValue`
-
-For example, if you want to set the `auto.commit.interval.ms` property for
-consumers, you need to configure this property as `KafkaProp-autoCommitIntervalMs`.
-
-**NOTE**: custom Kafka properties will be ignored when the relevant subsection is
-disabled (i.e. `kafka.subscriber.enabled` and/or `kafka.publisher.enabled` are
-set to `false`).
-
-The complete list of available settings can be found directly in the kafka website:
-
-* **Publisher**: https://kafka.apache.org/documentation/#producerconfigs
-* **Subscriber**: https://kafka.apache.org/documentation/#consumerconfigs
+ Defaults: No rules = All projects are REQUIRED to be consistent on all refs.
\ No newline at end of file
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/ModuleTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/ModuleTest.java
index 8b7a17b..2df60dd 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/ModuleTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/ModuleTest.java
@@ -17,7 +17,6 @@
import static com.google.common.truth.Truth.assertThat;
import com.google.gerrit.server.config.SitePaths;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerModule;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -37,16 +36,13 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Configuration configMock;
- @Mock private NoteDbStatus noteDb;
- @Mock private BrokerModule brokerModule;
-
@Rule public TemporaryFolder tempFolder = new TemporaryFolder();
private Module module;
@Before
public void setup() {
- module = new Module(configMock, noteDb, brokerModule);
+ module = new Module(configMock);
}
@Test
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiWrapperTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiWrapperTest.java
index 2abc7b0..92fa101 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiWrapperTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/broker/BrokerApiWrapperTest.java
@@ -5,9 +5,11 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import com.gerritforge.gerrit.eventbroker.BrokerApi;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.server.events.Event;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
+import com.googlesource.gerrit.plugins.multisite.MessageLogger;
+import java.util.UUID;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -19,26 +21,30 @@
@Mock private BrokerMetrics brokerMetrics;
@Mock private BrokerApi brokerApi;
@Mock Event event;
+ @Mock MessageLogger msgLog;
+ private UUID instanceId = UUID.randomUUID();
+ private String topic = "index";
private BrokerApiWrapper objectUnderTest;
@Before
public void setUp() {
objectUnderTest =
- new BrokerApiWrapper(DynamicItem.itemOf(BrokerApi.class, brokerApi), brokerMetrics);
+ new BrokerApiWrapper(
+ DynamicItem.itemOf(BrokerApi.class, brokerApi), brokerMetrics, msgLog, instanceId);
}
@Test
public void shouldIncrementBrokerMetricCounterWhenMessagePublished() {
when(brokerApi.send(any(), any())).thenReturn(true);
- objectUnderTest.send(EventTopic.INDEX_TOPIC.topic(), event);
+ objectUnderTest.send(topic, event);
verify(brokerMetrics, only()).incrementBrokerPublishedMessage();
}
@Test
public void shouldIncrementBrokerFailedMetricCounterWhenMessagePublishingFailed() {
when(brokerApi.send(any(), any())).thenReturn(false);
- objectUnderTest.send(EventTopic.INDEX_TOPIC.topic(), event);
+ objectUnderTest.send(topic, event);
verify(brokerMetrics, only()).incrementBrokerFailedToPublishMessage();
}
@@ -47,7 +53,7 @@
when(brokerApi.send(any(), any()))
.thenThrow(new RuntimeException("Unexpected runtime exception"));
try {
- objectUnderTest.send(EventTopic.INDEX_TOPIC.topic(), event);
+ objectUnderTest.send(topic, event);
} catch (RuntimeException e) {
// expected
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/BrokerPublisherTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/BrokerPublisherTest.java
deleted file mode 100644
index c751a84..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/broker/kafka/BrokerPublisherTest.java
+++ /dev/null
@@ -1,178 +0,0 @@
-// Copyright (C) 2019 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.multisite.broker.kafka;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.only;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import com.google.gerrit.extensions.client.ChangeKind;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Branch;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.server.data.AccountAttribute;
-import com.google.gerrit.server.data.ApprovalAttribute;
-import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gerrit.server.events.Event;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.googlesource.gerrit.plugins.multisite.MessageLogger;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerMetrics;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerSession;
-import com.googlesource.gerrit.plugins.multisite.broker.GsonProvider;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
-import java.util.UUID;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
-
-@RunWith(MockitoJUnitRunner.class)
-public class BrokerPublisherTest {
-
- @Mock private BrokerMetrics brokerMetrics;
- @Mock private BrokerSession session;
- @Mock private MessageLogger msgLog;
- private BrokerPublisher publisher;
-
- private Gson gson = new GsonProvider().get();
-
- private String accountName = "Foo Bar";
- private String accountEmail = "foo@bar.com";
- private String accountUsername = "foobar";
- private String approvalType = ChangeKind.REWORK.toString();
-
- private String approvalDescription = "ApprovalDescription";
- private String approvalValue = "+2";
- private String oldApprovalValue = "+1";
- private Long approvalGrantedOn = 123L;
- private String commentDescription = "Patch Set 1: Code-Review+2";
- private String projectName = "project";
- private String refName = "refs/heads/master";
- private String changeId = "Iabcd1234abcd1234abcd1234abcd1234abcd1234";
- private Long eventCreatedOn = 123L;
-
- @Before
- public void setUp() {
- publisher = new BrokerPublisher(session, gson, UUID.randomUUID(), msgLog);
- }
-
- @Test
- public void shouldSerializeCommentAddedEvent() {
-
- Event event = createSampleEvent();
-
- String expectedSerializedCommentEvent =
- "{\"author\": {\"name\": \""
- + accountName
- + "\",\"email\": \""
- + accountEmail
- + "\",\"username\": \""
- + accountUsername
- + "\"},\"approvals\": [{\"type\": \""
- + approvalType
- + "\",\"description\": \""
- + approvalDescription
- + "\",\"value\": \""
- + approvalValue
- + "\",\"oldValue\": \""
- + oldApprovalValue
- + "\",\"grantedOn\": "
- + approvalGrantedOn
- + ",\"by\": {\"name\": \""
- + accountName
- + "\",\"email\": \""
- + accountEmail
- + "\",\"username\": \""
- + accountUsername
- + "\"}}],\"comment\": \""
- + commentDescription
- + "\",\""
- + projectName
- + "\": {\"name\": \""
- + projectName
- + "\"},\"refName\": \""
- + refName
- + "\",\"changeKey\": {\"id\": \""
- + changeId
- + "\""
- + " },\"type\": \"comment-added\",\"eventCreatedOn\": "
- + eventCreatedOn
- + "}";
-
- JsonObject expectedCommentEventJsonObject =
- gson.fromJson(expectedSerializedCommentEvent, JsonElement.class).getAsJsonObject();
-
- assertThat(publisher.eventToJson(event).equals(expectedCommentEventJsonObject)).isTrue();
- }
-
- @Test
- public void shouldLogEventPublishedMessageWhenPublishingSucceed() {
- Event event = createSampleEvent();
- when(session.publish(any(), any())).thenReturn(true);
- publisher.publish(EventTopic.INDEX_TOPIC.topic(), event);
- verify(msgLog, only()).log(any(), any());
- }
-
- @Test
- public void shouldSkipEventPublishedLoggingWhenMessagePublishigFailed() {
- Event event = createSampleEvent();
- when(session.publish(any(), any())).thenReturn(false);
-
- publisher.publish(EventTopic.INDEX_TOPIC.topic(), event);
- verify(msgLog, never()).log(any(), any());
- }
-
- private Event createSampleEvent() {
- final Change change =
- new Change(
- new Change.Key(changeId),
- new Change.Id(1),
- new Account.Id(1),
- new Branch.NameKey(projectName, refName),
- TimeUtil.nowTs());
-
- CommentAddedEvent event = new CommentAddedEvent(change);
- AccountAttribute accountAttribute = new AccountAttribute();
- accountAttribute.email = accountEmail;
- accountAttribute.name = accountName;
- accountAttribute.username = accountUsername;
-
- event.eventCreatedOn = eventCreatedOn;
- event.approvals =
- () -> {
- ApprovalAttribute approvalAttribute = new ApprovalAttribute();
- approvalAttribute.value = approvalValue;
- approvalAttribute.oldValue = oldApprovalValue;
- approvalAttribute.description = approvalDescription;
- approvalAttribute.by = accountAttribute;
- approvalAttribute.type = ChangeKind.REWORK.toString();
- approvalAttribute.grantedOn = approvalGrantedOn;
-
- return new ApprovalAttribute[] {approvalAttribute};
- };
-
- event.author = () -> accountAttribute;
- event.comment = commentDescription;
-
- return event;
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/CacheEvictionEventRouterTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/event/CacheEvictionEventRouterTest.java
similarity index 96%
rename from src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/CacheEvictionEventRouterTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/multisite/event/CacheEvictionEventRouterTest.java
index ec03a40..8c094cd 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/CacheEvictionEventRouterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/event/CacheEvictionEventRouterTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.googlesource.gerrit.plugins.multisite.kafka.consumer;
+package com.googlesource.gerrit.plugins.multisite.event;
import static org.mockito.Mockito.verify;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/IndexEventRouterTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/event/IndexEventRouterTest.java
similarity index 98%
rename from src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/IndexEventRouterTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/multisite/event/IndexEventRouterTest.java
index df7c2fc..f30a45a 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/IndexEventRouterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/event/IndexEventRouterTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.googlesource.gerrit.plugins.multisite.kafka.consumer;
+package com.googlesource.gerrit.plugins.multisite.event;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/ProjectListUpdateRouterTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/event/ProjectListUpdateRouterTest.java
similarity index 95%
rename from src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/ProjectListUpdateRouterTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/multisite/event/ProjectListUpdateRouterTest.java
index 00a239b..93daf92 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/ProjectListUpdateRouterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/event/ProjectListUpdateRouterTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.googlesource.gerrit.plugins.multisite.kafka.consumer;
+package com.googlesource.gerrit.plugins.multisite.event;
import static org.mockito.Mockito.verify;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/StreamEventRouterTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/event/StreamEventRouterTest.java
similarity index 96%
rename from src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/StreamEventRouterTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/multisite/event/StreamEventRouterTest.java
index 147f275..45696e1 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/StreamEventRouterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/event/StreamEventRouterTest.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.googlesource.gerrit.plugins.multisite.kafka.consumer;
+package com.googlesource.gerrit.plugins.multisite.event;
import static org.mockito.Mockito.verify;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedEventHandlerTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedEventHandlerTest.java
index 3b01c61..5c36ada 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedEventHandlerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedEventHandlerTest.java
@@ -19,11 +19,11 @@
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
+import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.EventDispatcher;
import com.google.gerrit.server.events.ProjectCreatedEvent;
import com.google.gerrit.server.util.OneOffRequestContext;
-import com.google.gwtorm.server.OrmException;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -81,7 +81,7 @@
(Answer<Void>)
invocation -> {
assertThat(Context.isForwardedEvent()).isTrue();
- throw new OrmException("someMessage");
+ throw new StorageException("someMessage");
})
.when(dispatcherMock)
.postEvent(event);
@@ -89,8 +89,8 @@
assertThat(Context.isForwardedEvent()).isFalse();
try {
handler.dispatch(event);
- fail("should have throw an OrmException");
- } catch (OrmException e) {
+ fail("should have throw an StorageException");
+ } catch (StorageException e) {
assertThat(e.getMessage()).isEqualTo("someMessage");
}
assertThat(Context.isForwardedEvent()).isFalse();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexChangeHandlerTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexChangeHandlerTest.java
index 2793253..0a910c5 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexChangeHandlerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/forwarder/ForwardedIndexChangeHandlerTest.java
@@ -24,17 +24,15 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.change.ChangeIndexer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.util.Providers;
import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.forwarder.ForwardedIndexingHandler.Operation;
import com.googlesource.gerrit.plugins.multisite.forwarder.events.ChangeIndexEvent;
@@ -60,10 +58,8 @@
private static String TEST_CHANGE_ID = TEST_PROJECT + "~" + TEST_CHANGE_NUMBER;
private static final boolean CHANGE_EXISTS = true;
private static final boolean CHANGE_DOES_NOT_EXIST = false;
- private static final boolean DO_NOT_THROW_IO_EXCEPTION = false;
- private static final boolean DO_NOT_THROW_ORM_EXCEPTION = false;
- private static final boolean THROW_IO_EXCEPTION = true;
- private static final boolean THROW_ORM_EXCEPTION = true;
+ private static final boolean DO_NOT_THROW_STORAGE_EXCEPTION = false;
+ private static final boolean THROW_STORAGE_EXCEPTION = true;
private static final boolean CHANGE_UP_TO_DATE = true;
private static final boolean CHANGE_OUTDATED = false;
@@ -71,7 +67,6 @@
@Mock private ChangeIndexer indexerMock;
@Mock private OneOffRequestContext ctxMock;
@Mock private ManualRequestContext manualRequestContextMock;
- @Mock private ReviewDb dbMock;
@Mock private ChangeNotes changeNotes;
@Mock private Configuration configurationMock;
@Mock private Configuration.Index index;
@@ -87,7 +82,6 @@
@Before
public void setUp() throws Exception {
when(ctxMock.open()).thenReturn(manualRequestContextMock);
- when(manualRequestContextMock.getReviewDbProvider()).thenReturn(Providers.of(dbMock));
id = new Change.Id(TEST_CHANGE_NUMBER);
change = new Change(null, id, null, null, TimeUtil.nowTs());
when(changeNotes.getChange()).thenReturn(change);
@@ -103,7 +97,7 @@
public void changeIsIndexedWhenUpToDate() throws Exception {
setupChangeAccessRelatedMocks(CHANGE_EXISTS, CHANGE_UP_TO_DATE);
handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
- verify(indexerMock, times(1)).index(any(ReviewDb.class), any(Change.class));
+ verify(indexerMock, times(1)).index(any(Change.class));
}
@Test
@@ -111,7 +105,7 @@
setupChangeAccessRelatedMocks(CHANGE_EXISTS, CHANGE_OUTDATED);
handler.index(
TEST_CHANGE_ID, Operation.INDEX, Optional.of(new ChangeIndexEvent("foo", 1, false)));
- verify(indexerMock, times(1)).index(any(ReviewDb.class), any(Change.class));
+ verify(indexerMock, times(1)).index(any(Change.class));
}
@Test
@@ -125,22 +119,13 @@
setupChangeAccessRelatedMocks(CHANGE_DOES_NOT_EXIST, CHANGE_OUTDATED);
handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
verify(indexerMock, never()).delete(id);
- verify(indexerMock, never())
- .index(any(ReviewDb.class), any(Project.NameKey.class), any(Change.Id.class));
+ verify(indexerMock, never()).index(any(Project.NameKey.class), any(Change.Id.class));
}
@Test
- public void schemaThrowsExceptionWhenLookingUpForChange() throws Exception {
- setupChangeAccessRelatedMocks(CHANGE_EXISTS, THROW_ORM_EXCEPTION, CHANGE_UP_TO_DATE);
- exception.expect(OrmException.class);
- handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
- }
-
- @Test
- public void indexerThrowsIOExceptionTryingToIndexChange() throws Exception {
- setupChangeAccessRelatedMocks(
- CHANGE_EXISTS, DO_NOT_THROW_ORM_EXCEPTION, THROW_IO_EXCEPTION, CHANGE_UP_TO_DATE);
- exception.expect(IOException.class);
+ public void indexerThrowsStorageExceptionTryingToIndexChange() throws Exception {
+ setupChangeAccessRelatedMocks(CHANGE_EXISTS, THROW_STORAGE_EXCEPTION, CHANGE_UP_TO_DATE);
+ exception.expect(StorageException.class);
handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
}
@@ -156,13 +141,13 @@
return null;
})
.when(indexerMock)
- .index(any(ReviewDb.class), any(Change.class));
+ .index(any(Change.class));
assertThat(Context.isForwardedEvent()).isFalse();
handler.index(TEST_CHANGE_ID, Operation.INDEX, Optional.empty());
assertThat(Context.isForwardedEvent()).isFalse();
- verify(indexerMock, times(1)).index(any(ReviewDb.class), any(Change.class));
+ verify(indexerMock, times(1)).index(any(Change.class));
}
@Test
@@ -175,7 +160,7 @@
throw new IOException("someMessage");
})
.when(indexerMock)
- .index(any(ReviewDb.class), any(Change.class));
+ .index(any(Change.class));
assertThat(Context.isForwardedEvent()).isFalse();
try {
@@ -186,36 +171,22 @@
}
assertThat(Context.isForwardedEvent()).isFalse();
- verify(indexerMock, times(1)).index(any(ReviewDb.class), any(Change.class));
+ verify(indexerMock, times(1)).index(any(Change.class));
}
private void setupChangeAccessRelatedMocks(boolean changeExist, boolean changeUpToDate)
throws Exception {
- setupChangeAccessRelatedMocks(
- changeExist, DO_NOT_THROW_ORM_EXCEPTION, DO_NOT_THROW_IO_EXCEPTION, changeUpToDate);
+ setupChangeAccessRelatedMocks(changeExist, DO_NOT_THROW_STORAGE_EXCEPTION, changeUpToDate);
}
private void setupChangeAccessRelatedMocks(
- boolean changeExist, boolean ormException, boolean changeUpToDate)
- throws OrmException, IOException {
- setupChangeAccessRelatedMocks(
- changeExist, ormException, DO_NOT_THROW_IO_EXCEPTION, changeUpToDate);
- }
-
- private void setupChangeAccessRelatedMocks(
- boolean changeExists, boolean ormException, boolean ioException, boolean changeIsUpToDate)
- throws OrmException, IOException {
- if (ormException) {
- doThrow(new OrmException("")).when(ctxMock).open();
- }
-
+ boolean changeExists, boolean storageException, boolean changeIsUpToDate)
+ throws StorageException {
if (changeExists) {
when(changeCheckerFactoryMock.create(TEST_CHANGE_ID)).thenReturn(changeCheckerPresentMock);
when(changeCheckerPresentMock.getChangeNotes()).thenReturn(Optional.of(changeNotes));
- if (ioException) {
- doThrow(new IOException("io-error"))
- .when(indexerMock)
- .index(any(ReviewDb.class), any(Change.class));
+ if (storageException) {
+ doThrow(new StorageException("io-error")).when(indexerMock).index(any(Change.class));
}
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfigurationTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfigurationTest.java
deleted file mode 100644
index 84e1dd8..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/KafkaConfigurationTest.java
+++ /dev/null
@@ -1,200 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration.ENABLE_KEY;
-import static com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration.KAFKA_PROPERTY_PREFIX;
-import static com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration.KAFKA_SECTION;
-import static com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration.KafkaPublisher.KAFKA_PUBLISHER_SUBSECTION;
-import static com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration.KafkaSubscriber.KAFKA_SUBSCRIBER_SUBSECTION;
-
-import com.googlesource.gerrit.plugins.multisite.Configuration;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.EventTopic;
-import org.eclipse.jgit.lib.Config;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnitRunner;
-
-@RunWith(MockitoJUnitRunner.class)
-public class KafkaConfigurationTest {
-
- private Config globalPluginConfig;
- private Configuration multiSiteConfig;
-
- @Before
- public void setup() {
- globalPluginConfig = new Config();
- multiSiteConfig = new Configuration(globalPluginConfig, new Config());
- }
-
- private KafkaConfiguration getConfiguration() {
- return new KafkaConfiguration(multiSiteConfig);
- }
-
- @Test
- public void kafkaSubscriberPropertiesAreSetWhenSectionIsEnabled() {
- final String kafkaPropertyName = KAFKA_PROPERTY_PREFIX + "fooBarBaz";
- final String kafkaPropertyValue = "aValue";
- globalPluginConfig.setBoolean(KAFKA_SECTION, KAFKA_SUBSCRIBER_SUBSECTION, ENABLE_KEY, true);
- globalPluginConfig.setString(
- KAFKA_SECTION, KAFKA_SUBSCRIBER_SUBSECTION, kafkaPropertyName, kafkaPropertyValue);
-
- final String property = getConfiguration().kafkaSubscriber().getProperty("foo.bar.baz");
-
- assertThat(property.equals(kafkaPropertyValue)).isTrue();
- }
-
- @Test
- public void kafkaSubscriberPropertiesAreNotSetWhenSectionIsDisabled() {
- final String kafkaPropertyName = KAFKA_PROPERTY_PREFIX + "fooBarBaz";
- final String kafkaPropertyValue = "aValue";
- globalPluginConfig.setBoolean(KAFKA_SECTION, KAFKA_SUBSCRIBER_SUBSECTION, ENABLE_KEY, false);
- globalPluginConfig.setString(
- KAFKA_SECTION, KAFKA_SUBSCRIBER_SUBSECTION, kafkaPropertyName, kafkaPropertyValue);
-
- final String property = getConfiguration().kafkaSubscriber().getProperty("foo.bar.baz");
-
- assertThat(property).isNull();
- }
-
- @Test
- public void kafkaSubscriberPropertiesAreIgnoredWhenPrefixIsNotSet() {
- final String kafkaPropertyName = "fooBarBaz";
- final String kafkaPropertyValue = "aValue";
- globalPluginConfig.setBoolean(KAFKA_SECTION, KAFKA_SUBSCRIBER_SUBSECTION, ENABLE_KEY, true);
- globalPluginConfig.setString(
- KAFKA_SECTION, KAFKA_SUBSCRIBER_SUBSECTION, kafkaPropertyName, kafkaPropertyValue);
-
- final String property = getConfiguration().kafkaSubscriber().getProperty("foo.bar.baz");
-
- assertThat(property).isNull();
- }
-
- @Test
- public void kafkaPublisherPropertiesAreSetWhenSectionIsEnabled() {
- final String kafkaPropertyName = KAFKA_PROPERTY_PREFIX + "fooBarBaz";
- final String kafkaPropertyValue = "aValue";
- globalPluginConfig.setBoolean(KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, ENABLE_KEY, true);
- globalPluginConfig.setString(
- KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, kafkaPropertyName, kafkaPropertyValue);
-
- final String property = getConfiguration().kafkaPublisher().getProperty("foo.bar.baz");
-
- assertThat(property.equals(kafkaPropertyValue)).isTrue();
- }
-
- @Test
- public void kafkaPublisherPropertiesAreIgnoredWhenPrefixIsNotSet() {
- final String kafkaPropertyName = "fooBarBaz";
- final String kafkaPropertyValue = "aValue";
- globalPluginConfig.setBoolean(KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, ENABLE_KEY, true);
- globalPluginConfig.setString(
- KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, kafkaPropertyName, kafkaPropertyValue);
-
- final String property = getConfiguration().kafkaPublisher().getProperty("foo.bar.baz");
-
- assertThat(property).isNull();
- }
-
- @Test
- public void kafkaPublisherPropertiesAreNotSetWhenSectionIsDisabled() {
- final String kafkaPropertyName = KAFKA_PROPERTY_PREFIX + "fooBarBaz";
- final String kafkaPropertyValue = "aValue";
- globalPluginConfig.setBoolean(KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, ENABLE_KEY, false);
- globalPluginConfig.setString(
- KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, kafkaPropertyName, kafkaPropertyValue);
-
- final String property = getConfiguration().kafkaPublisher().getProperty("foo.bar.baz");
-
- assertThat(property).isNull();
- }
-
- @Test
- public void shouldReturnKafkaTopicAliasForIndexTopic() {
- setKafkaTopicAlias("indexEventTopic", "gerrit_index");
- final String property = getConfiguration().getKafka().getTopicAlias(EventTopic.INDEX_TOPIC);
-
- assertThat(property).isEqualTo("gerrit_index");
- }
-
- @Test
- public void shouldReturnKafkaTopicAliasForStreamEventTopic() {
- setKafkaTopicAlias("streamEventTopic", "gerrit_stream_events");
- final String property =
- getConfiguration().getKafka().getTopicAlias(EventTopic.STREAM_EVENT_TOPIC);
-
- assertThat(property).isEqualTo("gerrit_stream_events");
- }
-
- @Test
- public void shouldReturnKafkaTopicAliasForProjectListEventTopic() {
- setKafkaTopicAlias("projectListEventTopic", "gerrit_project_list");
- final String property =
- getConfiguration().getKafka().getTopicAlias(EventTopic.PROJECT_LIST_TOPIC);
-
- assertThat(property).isEqualTo("gerrit_project_list");
- }
-
- @Test
- public void shouldReturnKafkaTopicAliasForCacheEventTopic() {
- setKafkaTopicAlias("cacheEventTopic", "gerrit_cache");
- final String property = getConfiguration().getKafka().getTopicAlias(EventTopic.CACHE_TOPIC);
-
- assertThat(property).isEqualTo("gerrit_cache");
- }
-
- @Test
- public void shouldReturnKafkaTopicEnabledForCacheEventTopic() {
- setKafkaTopicEnabled("cacheEventEnabled", false);
- final Boolean property =
- getConfiguration().kafkaPublisher().enabledEvent(EventTopic.CACHE_TOPIC);
- assertThat(property).isFalse();
- }
-
- @Test
- public void shouldReturnKafkaTopicEnabledForIndexTopic() {
- setKafkaTopicEnabled("indexEventEnabled", false);
- final Boolean property =
- getConfiguration().kafkaPublisher().enabledEvent(EventTopic.INDEX_TOPIC);
- assertThat(property).isFalse();
- }
-
- @Test
- public void shouldReturnKafkaTopicEnabledForStreamEventTopic() {
- setKafkaTopicEnabled("streamEventEnabled", false);
- final Boolean property =
- getConfiguration().kafkaPublisher().enabledEvent(EventTopic.STREAM_EVENT_TOPIC);
- assertThat(property).isFalse();
- }
-
- @Test
- public void shouldReturnKafkaTopicEnabledForProjectListEventTopic() {
- setKafkaTopicEnabled("projectListEventEnabled", false);
- final Boolean property =
- getConfiguration().kafkaPublisher().enabledEvent(EventTopic.PROJECT_LIST_TOPIC);
- assertThat(property).isFalse();
- }
-
- private void setKafkaTopicAlias(String topicKey, String topic) {
- globalPluginConfig.setString(KAFKA_SECTION, null, topicKey, topic);
- }
-
- private void setKafkaTopicEnabled(String topicEnabledKey, Boolean isEnabled) {
- globalPluginConfig.setBoolean(
- KAFKA_SECTION, KAFKA_PUBLISHER_SUBSECTION, topicEnabledKey, isEnabled);
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/EventConsumerIT.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/EventConsumerIT.java
deleted file mode 100644
index cbd192d..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/EventConsumerIT.java
+++ /dev/null
@@ -1,295 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka.consumer;
-
-import static com.google.common.truth.Truth.assertThat;
-import static java.util.stream.Collectors.toSet;
-
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
-import com.google.gerrit.acceptance.LogThreshold;
-import com.google.gerrit.acceptance.NoHttpd;
-import com.google.gerrit.acceptance.UseLocalDisk;
-import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.extensions.registration.DynamicItem;
-import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.data.PatchSetAttribute;
-import com.google.gerrit.server.events.CommentAddedEvent;
-import com.google.gerrit.server.events.Event;
-import com.google.gerrit.server.events.PatchSetCreatedEvent;
-import com.google.gerrit.server.events.RefUpdatedEvent;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gson.Gson;
-import com.google.inject.Inject;
-import com.google.inject.Key;
-import com.google.inject.Scopes;
-import com.google.inject.TypeLiteral;
-import com.googlesource.gerrit.plugins.multisite.Configuration;
-import com.googlesource.gerrit.plugins.multisite.Module;
-import com.googlesource.gerrit.plugins.multisite.NoteDbStatus;
-import com.googlesource.gerrit.plugins.multisite.PluginModule;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApi;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerApiWrapper;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerGson;
-import com.googlesource.gerrit.plugins.multisite.broker.BrokerModule;
-import com.googlesource.gerrit.plugins.multisite.consumer.DroppedEventListener;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import com.googlesource.gerrit.plugins.multisite.consumer.SubscriberModule;
-import com.googlesource.gerrit.plugins.multisite.forwarder.events.ChangeIndexEvent;
-import com.googlesource.gerrit.plugins.multisite.kafka.KafkaBrokerModule;
-import com.googlesource.gerrit.plugins.multisite.kafka.KafkaConfiguration;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.ZkValidationModule;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Collectors;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-import org.junit.Test;
-import org.testcontainers.containers.KafkaContainer;
-
-@NoHttpd
-@LogThreshold(level = "INFO")
-@UseLocalDisk
-public class EventConsumerIT extends AbstractDaemonTest {
- public static final String GERRIT_CONFIG_KEY = "gerrit.installModule";
- public static final String GERRIT_CONFIG_VALUE =
- "com.googlesource.gerrit.plugins.multisite.kafka.consumer.EventConsumerIT$KafkaTestContainerModule";
- private static final int QUEUE_POLL_TIMEOUT_MSECS = 10000;
-
- static {
- System.setProperty("gerrit.notedb", "ON");
- }
-
- public static class KafkaTestContainerModule extends LifecycleModule {
-
- public static class KafkaStopAtShutdown implements LifecycleListener {
- private final KafkaContainer kafka;
-
- public KafkaStopAtShutdown(KafkaContainer kafka) {
- this.kafka = kafka;
- }
-
- @Override
- public void stop() {
- kafka.stop();
- }
-
- @Override
- public void start() {
- // Do nothing
- }
- }
-
- public static class TestBrokerModule extends BrokerModule {
- @Override
- protected void configure() {
- DynamicItem.itemOf(binder(), BrokerApi.class);
- bind(BrokerApiWrapper.class).in(Scopes.SINGLETON);
-
- install(new SubscriberModule());
- }
- }
-
- private final FileBasedConfig config;
- private final Module multiSiteModule;
- private final PluginModule pluginModule;
-
- @Inject
- public KafkaTestContainerModule(SitePaths sitePaths, NoteDbStatus noteDb) throws IOException {
- this.config =
- new FileBasedConfig(
- sitePaths.etc_dir.resolve(Configuration.MULTI_SITE_CONFIG).toFile(), FS.DETECTED);
- config.setBoolean("kafka", "publisher", "enabled", true);
- config.setBoolean("kafka", "subscriber", "enabled", true);
- config.setBoolean("ref-database", null, "enabled", false);
- config.save();
-
- Configuration multiSiteConfig = new Configuration(config, new Config());
- this.multiSiteModule = new Module(multiSiteConfig, noteDb, new TestBrokerModule(), true);
- this.pluginModule =
- new PluginModule(
- multiSiteConfig,
- new ZkValidationModule(multiSiteConfig),
- new KafkaBrokerModule(new KafkaConfiguration(multiSiteConfig)));
- }
-
- @Override
- protected void configure() {
- try {
- final KafkaContainer kafka = startAndConfigureKafkaConnection();
-
- listener().toInstance(new KafkaStopAtShutdown(kafka));
-
- install(multiSiteModule);
- install(pluginModule);
-
- } catch (IOException e) {
- throw new IllegalStateException(e);
- }
- }
-
- private KafkaContainer startAndConfigureKafkaConnection() throws IOException {
- KafkaContainer kafkaContainer = new KafkaContainer();
- kafkaContainer.start();
-
- config.setString("kafka", null, "bootstrapServers", kafkaContainer.getBootstrapServers());
- config.save();
-
- return kafkaContainer;
- }
- }
-
- @Test
- @GerritConfig(name = GERRIT_CONFIG_KEY, value = GERRIT_CONFIG_VALUE)
- public void createChangeShouldPropagateChangeIndexAndRefUpdateStreamEvent() throws Exception {
- LinkedBlockingQueue<SourceAwareEventWrapper> droppedEventsQueue = captureDroppedEvents();
- drainQueue(droppedEventsQueue);
-
- ChangeData change = createChange().getChange();
- String project = change.project().get();
- int changeNum = change.getId().get();
- String changeNotesRef = change.notes().getRefName();
- int patchsetNum = change.currentPatchSet().getPatchSetId();
- String patchsetRevision = change.currentPatchSet().getRevision().get();
- String patchsetRef = change.currentPatchSet().getRefName();
-
- Map<String, List<Event>> eventsByType = receiveEventsByType(droppedEventsQueue);
- assertThat(eventsByType).isNotEmpty();
-
- assertThat(eventsByType.get("change-index"))
- .containsExactly(createChangeIndexEvent(project, changeNum, getParentCommit(change)));
-
- assertThat(
- eventsByType.get("ref-updated").stream()
- .map(e -> ((RefUpdatedEvent) e).getRefName())
- .collect(toSet()))
- .containsAllOf(changeNotesRef, patchsetRef); // 'refs/sequences/changes'
- // not always updated thus
- // not checked
-
- List<Event> patchSetCreatedEvents = eventsByType.get("patchset-created");
- assertThat(patchSetCreatedEvents).hasSize(1);
- assertPatchSetAttributes(
- (PatchSetCreatedEvent) patchSetCreatedEvents.get(0),
- patchsetNum,
- patchsetRevision,
- patchsetRef);
- }
-
- private void assertPatchSetAttributes(
- PatchSetCreatedEvent patchSetCreated,
- int patchsetNum,
- String patchsetRevision,
- String patchsetRef) {
- PatchSetAttribute patchSetAttribute = patchSetCreated.patchSet.get();
- assertThat(patchSetAttribute.number).isEqualTo(patchsetNum);
- assertThat(patchSetAttribute.revision).isEqualTo(patchsetRevision);
- assertThat(patchSetAttribute.ref).isEqualTo(patchsetRef);
- }
-
- @Test
- @GerritConfig(name = GERRIT_CONFIG_KEY, value = GERRIT_CONFIG_VALUE)
- public void reviewChangeShouldPropagateChangeIndexAndCommentAdded() throws Exception {
- LinkedBlockingQueue<SourceAwareEventWrapper> droppedEventsQueue = captureDroppedEvents();
- ChangeData change = createChange().getChange();
- String project = change.project().get();
- int changeNum = change.getId().get();
- drainQueue(droppedEventsQueue);
-
- ReviewInput in = ReviewInput.recommend();
- in.message = "LGTM";
- gApi.changes().id(changeNum).revision("current").review(in);
-
- Map<String, List<Event>> eventsByType = receiveEventsByType(droppedEventsQueue);
-
- assertThat(eventsByType).isNotEmpty();
-
- assertThat(eventsByType.get("change-index"))
- .containsExactly(createChangeIndexEvent(project, changeNum, getParentCommit(change)));
-
- List<Event> commentAddedEvents = eventsByType.get("comment-added");
- assertThat(commentAddedEvents).hasSize(1);
- assertThat(((CommentAddedEvent) commentAddedEvents.get(0)).comment)
- .isEqualTo("Patch Set 1: Code-Review+1\n\n" + in.message);
- }
-
- private String getParentCommit(ChangeData change) throws Exception {
- RevCommit parent;
- try (Repository repo = repoManager.openRepository(change.project());
- RevWalk walk = new RevWalk(repo)) {
- RevCommit commit =
- walk.parseCommit(ObjectId.fromString(change.currentPatchSet().getRevision().get()));
- parent = commit.getParent(0);
- }
- return parent.getId().name();
- }
-
- private ChangeIndexEvent createChangeIndexEvent(
- String projectName, int changeId, String targetSha1) {
- ChangeIndexEvent event = new ChangeIndexEvent(projectName, changeId, false);
- event.targetSha = targetSha1;
- return event;
- }
-
- private LinkedBlockingQueue<SourceAwareEventWrapper> captureDroppedEvents() throws Exception {
- LinkedBlockingQueue<SourceAwareEventWrapper> droppedEvents = new LinkedBlockingQueue<>();
-
- TypeLiteral<DynamicSet<DroppedEventListener>> type =
- new TypeLiteral<DynamicSet<DroppedEventListener>>() {};
- server
- .getTestInjector()
- .getInstance(Key.get(type))
- .add(
- "multi-site",
- new DroppedEventListener() {
- @Override
- public void onEventDropped(SourceAwareEventWrapper event) {
- droppedEvents.offer(event);
- }
- });
- return droppedEvents;
- }
-
- private Map<String, List<Event>> receiveEventsByType(
- LinkedBlockingQueue<SourceAwareEventWrapper> queue) throws InterruptedException {
- return drainQueue(queue).stream()
- .sorted(Comparator.comparing(e -> e.type))
- .collect(Collectors.groupingBy(e -> e.type));
- }
-
- private List<Event> drainQueue(LinkedBlockingQueue<SourceAwareEventWrapper> queue)
- throws InterruptedException {
- Gson gson = server.getTestInjector().getInstance(Key.get(Gson.class, BrokerGson.class));
- SourceAwareEventWrapper event;
- List<Event> eventsList = new ArrayList<>();
- while ((event = queue.poll(QUEUE_POLL_TIMEOUT_MSECS, TimeUnit.MILLISECONDS)) != null) {
- eventsList.add(event.getEventBody(gson));
- }
- return eventsList;
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventDeserializerTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventDeserializerTest.java
deleted file mode 100644
index 239b586..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/kafka/consumer/KafkaEventDeserializerTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright (C) 2019 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.multisite.kafka.consumer;
-
-import static com.google.common.truth.Truth.assertThat;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.gson.Gson;
-import com.googlesource.gerrit.plugins.multisite.broker.GsonProvider;
-import com.googlesource.gerrit.plugins.multisite.consumer.SourceAwareEventWrapper;
-import java.util.UUID;
-import org.junit.Before;
-import org.junit.Test;
-
-public class KafkaEventDeserializerTest {
- private KafkaEventDeserializer deserializer;
-
- @Before
- public void setUp() {
- final Gson gson = new GsonProvider().get();
- deserializer = new KafkaEventDeserializer(gson);
- }
-
- @Test
- public void kafkaEventDeserializerShouldParseAKafkaEvent() {
- final UUID eventId = UUID.randomUUID();
- final String eventType = "event-type";
- final UUID sourceInstanceId = UUID.randomUUID();
- final long eventCreatedOn = 10L;
- final String eventJson =
- String.format(
- "{ "
- + "\"header\": { \"eventId\": \"%s\", \"eventType\": \"%s\", \"sourceInstanceId\": \"%s\", \"eventCreatedOn\": %d },"
- + "\"body\": {}"
- + "}",
- eventId, eventType, sourceInstanceId, eventCreatedOn);
- final SourceAwareEventWrapper event =
- deserializer.deserialize("ignored", eventJson.getBytes(UTF_8));
-
- assertThat(event.getBody().entrySet()).isEmpty();
- assertThat(event.getHeader().getEventId()).isEqualTo(eventId);
- assertThat(event.getHeader().getEventType()).isEqualTo(eventType);
- assertThat(event.getHeader().getSourceInstanceId()).isEqualTo(sourceInstanceId);
- assertThat(event.getHeader().getEventCreatedOn()).isEqualTo(eventCreatedOn);
- }
-
- @Test(expected = RuntimeException.class)
- public void kafkaEventDeserializerShouldFailForInvalidJson() {
- deserializer.deserialize("ignored", "this is not a JSON string".getBytes(UTF_8));
- }
-
- @Test(expected = RuntimeException.class)
- public void kafkaEventDeserializerShouldFailForInvalidObjectButValidJSON() {
- deserializer.deserialize("ignored", "{}".getBytes(UTF_8));
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
index 5a68d2f..0960cf1 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/BatchRefUpdateValidatorTest.java
@@ -14,27 +14,31 @@
package com.googlesource.gerrit.plugins.multisite.validation;
-import static junit.framework.TestCase.assertFalse;
+import static com.google.common.truth.Truth.assertThat;
import static org.eclipse.jgit.transport.ReceiveCommand.Type.UPDATE;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.lenient;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
-import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.metrics.DisabledMetricMaker;
+import com.google.gerrit.reviewdb.client.Project;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.ZkSharedRefDatabase;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.ZookeeperTestContainerSupport;
import java.io.IOException;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
-import org.apache.curator.retry.RetryNTimes;
import org.eclipse.jgit.internal.storage.file.RefDirectory;
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -43,7 +47,11 @@
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+@RunWith(MockitoJUnitRunner.class)
public class BatchRefUpdateValidatorTest extends LocalDiskRepositoryTestCase implements RefFixture {
@Rule public TestName nameRule = new TestName();
@@ -53,15 +61,15 @@
private RevCommit A;
private RevCommit B;
- ZookeeperTestContainerSupport zookeeperContainer;
- SharedRefDatabaseWrapper zkSharedRefDatabase;
+ @Mock SharedRefDatabaseWrapper sharedRefDatabase;
+
+ @Mock SharedRefEnforcement tmpRefEnforcement;
@Before
public void setup() throws Exception {
super.setUp();
gitRepoSetup();
- zookeeperAndPolicyEnforcementSetup();
}
private void gitRepoSetup() throws Exception {
@@ -72,24 +80,6 @@
B = repo.commit(repo.getRevWalk().parseCommit(A));
}
- private void zookeeperAndPolicyEnforcementSetup() {
- zookeeperContainer = new ZookeeperTestContainerSupport(false);
- int SLEEP_BETWEEN_RETRIES_MS = 30;
- long TRANSACTION_LOCK_TIMEOUT = 1000l;
- int NUMBER_OF_RETRIES = 5;
-
- zkSharedRefDatabase =
- new SharedRefDatabaseWrapper(
- DynamicItem.itemOf(
- SharedRefDatabase.class,
- new ZkSharedRefDatabase(
- zookeeperContainer.getCurator(),
- new ZkConnectionConfig(
- new RetryNTimes(NUMBER_OF_RETRIES, SLEEP_BETWEEN_RETRIES_MS),
- TRANSACTION_LOCK_TIMEOUT))),
- new DisabledSharedRefLogger());
- }
-
@Test
public void immutableChangeShouldNotBeWrittenIntoZk() throws Exception {
String AN_IMMUTABLE_REF = "refs/changes/01/1/1";
@@ -102,7 +92,8 @@
BatchRefUpdateValidator.executeBatchUpdateWithValidation(
batchRefUpdate, () -> execute(batchRefUpdate));
- assertFalse(zkSharedRefDatabase.exists(A_TEST_PROJECT_NAME, AN_IMMUTABLE_REF));
+ verify(sharedRefDatabase, never())
+ .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));
}
@Test
@@ -116,7 +107,34 @@
BatchRefUpdateValidator.executeBatchUpdateWithValidation(
batchRefUpdate, () -> execute(batchRefUpdate));
- assertFalse(zkSharedRefDatabase.exists(A_TEST_PROJECT_NAME, DRAFT_COMMENT));
+ verify(sharedRefDatabase, never())
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, newRef(DRAFT_COMMENT, A.getId()), B.getId());
+ }
+
+ @Test
+ public void validationShouldFailWhenLocalRefDbIsOutOfSync() throws Exception {
+ String AN_OUT_OF_SYNC_REF = "refs/changes/01/1/1";
+ BatchRefUpdate batchRefUpdate =
+ newBatchUpdate(
+ Collections.singletonList(new ReceiveCommand(A, B, AN_OUT_OF_SYNC_REF, UPDATE)));
+ BatchRefUpdateValidator batchRefUpdateValidator =
+ getRefValidatorForEnforcement(A_TEST_PROJECT_NAME, tmpRefEnforcement);
+
+ doReturn(SharedRefEnforcement.EnforcePolicy.REQUIRED)
+ .when(batchRefUpdateValidator.refEnforcement)
+ .getPolicy(A_TEST_PROJECT_NAME, AN_OUT_OF_SYNC_REF);
+ lenient()
+ .doReturn(false)
+ .when(sharedRefDatabase)
+ .isUpToDate(A_TEST_PROJECT_NAME_KEY, newRef(AN_OUT_OF_SYNC_REF, AN_OBJECT_ID_1));
+
+ batchRefUpdateValidator.executeBatchUpdateWithValidation(
+ batchRefUpdate, () -> execute(batchRefUpdate));
+
+ final List<ReceiveCommand> commands = batchRefUpdate.getCommands();
+ assertThat(commands.size()).isEqualTo(1);
+ commands.forEach(
+ (command) -> assertThat(command.getResult()).isEqualTo(ReceiveCommand.Result.LOCK_FAILURE));
}
private BatchRefUpdateValidator newDefaultValidator(String projectName) {
@@ -126,7 +144,7 @@
private BatchRefUpdateValidator getRefValidatorForEnforcement(
String projectName, SharedRefEnforcement sharedRefEnforcement) {
return new BatchRefUpdateValidator(
- zkSharedRefDatabase,
+ sharedRefDatabase,
new ValidationMetrics(new DisabledMetricMaker()),
sharedRefEnforcement,
new DummyLockWrapper(),
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/Log4jSharedRefLoggerTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/Log4jSharedRefLoggerTest.java
index f368d41..c6f0fc1 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/Log4jSharedRefLoggerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/Log4jSharedRefLoggerTest.java
@@ -18,10 +18,10 @@
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.json.OutputFormat;
import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.OutputFormat;
-import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.config.SitePaths;
+import com.google.gerrit.server.notedb.Sequences;
import com.google.gerrit.server.util.SystemLog;
import com.google.gson.Gson;
import com.googlesource.gerrit.plugins.multisite.Log4jSharedRefLogger;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
index 730e558..187f686 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteBatchRefUpdateTest.java
@@ -15,17 +15,18 @@
package com.googlesource.gerrit.plugins.multisite.validation;
import static java.util.Arrays.asList;
-import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
import java.io.IOException;
import java.util.Collections;
import org.eclipse.jgit.lib.BatchRefUpdate;
@@ -50,6 +51,7 @@
@Mock SharedRefDatabaseWrapper sharedRefDb;
@Mock BatchRefUpdate batchRefUpdate;
+ @Mock BatchRefUpdateValidator batchRefUpdateValidator;
@Mock RefDatabase refDatabase;
@Mock RevWalk revWalk;
@Mock ProgressMonitor progressMonitor;
@@ -110,30 +112,38 @@
setMockRequiredReturnValues();
// When compareAndPut against sharedDb succeeds
- doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
+ doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
doReturn(true)
.when(sharedRefDb)
- .compareAndPut(eq(A_TEST_PROJECT_NAME), refEquals(oldRef), eq(newRef.getObjectId()));
+ .compareAndPut(eq(A_TEST_PROJECT_NAME_KEY), refEquals(oldRef), eq(newRef.getObjectId()));
multiSiteRefUpdate.execute(revWalk, progressMonitor, Collections.emptyList());
verify(sharedRefDb)
- .compareAndPut(eq(A_TEST_PROJECT_NAME), refEquals(oldRef), eq(newRef.getObjectId()));
+ .compareAndPut(eq(A_TEST_PROJECT_NAME_KEY), refEquals(oldRef), eq(newRef.getObjectId()));
}
private Ref refEquals(Ref oldRef) {
return argThat(new RefMatcher(oldRef));
}
- @Test
+ @Test(expected = IOException.class)
public void executeAndFailsWithExceptions() throws IOException {
+ multiSiteRefUpdate = getMultiSiteBatchRefUpdateWithMockedValidator();
+ doThrow(new IOException("IO Test Exception"))
+ .when(batchRefUpdateValidator)
+ .executeBatchUpdateWithValidation(any(), any());
+
+ multiSiteRefUpdate.execute(revWalk, progressMonitor, Collections.emptyList());
+ }
+
+ @Test
+ public void executeSuccessfullyWithNoExceptionsWhenOutOfSync() throws IOException {
setMockRequiredReturnValues();
- doReturn(true).when(sharedRefDb).exists(A_TEST_PROJECT_NAME, A_TEST_REF_NAME);
- doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
- try {
- multiSiteRefUpdate.execute(revWalk, progressMonitor, Collections.emptyList());
- fail("Expecting an IOException to be thrown");
- } catch (IOException e) {
- verify(validationMetrics).incrementSplitBrainPrevention();
- }
+ doReturn(true).when(sharedRefDb).exists(A_TEST_PROJECT_NAME_KEY, A_TEST_REF_NAME);
+ doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
+
+ multiSiteRefUpdate.execute(revWalk, progressMonitor, Collections.emptyList());
+
+ verify(validationMetrics).incrementSplitBrainPrevention();
}
@Test
@@ -163,6 +173,17 @@
return new MultiSiteBatchRefUpdate(batchRefValidatorFactory, A_TEST_PROJECT_NAME, refDatabase);
}
+ private MultiSiteBatchRefUpdate getMultiSiteBatchRefUpdateWithMockedValidator() {
+ BatchRefUpdateValidator.Factory batchRefValidatorFactory =
+ new BatchRefUpdateValidator.Factory() {
+ @Override
+ public BatchRefUpdateValidator create(String projectName, RefDatabase refDb) {
+ return batchRefUpdateValidator;
+ }
+ };
+ return new MultiSiteBatchRefUpdate(batchRefValidatorFactory, A_TEST_PROJECT_NAME, refDatabase);
+ }
+
protected static class RefMatcher implements ArgumentMatcher<Ref> {
private Ref left;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteGitRepositoryManagerTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteGitRepositoryManagerTest.java
index 82476a1..491ced4 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteGitRepositoryManagerTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteGitRepositoryManagerTest.java
@@ -18,7 +18,7 @@
import static org.mockito.Mockito.verify;
import com.google.gerrit.server.git.LocalDiskRepositoryManager;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
import org.eclipse.jgit.lib.Repository;
import org.junit.Before;
import org.junit.Test;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefDatabaseTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefDatabaseTest.java
index b41378b..41b83e5 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefDatabaseTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefDatabaseTest.java
@@ -17,7 +17,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
import org.junit.Rule;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
index a9d8e76..16cda4e 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRefUpdateTest.java
@@ -24,8 +24,8 @@
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.RefUpdateValidator.Factory;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefUpdateStub;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefUpdateStub;
import java.io.IOException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
@@ -65,10 +65,10 @@
@Test
public void newUpdateShouldValidateAndSucceed() throws Exception {
- doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
+ doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
doReturn(true)
.when(sharedRefDb)
- .compareAndPut(A_TEST_PROJECT_NAME, oldRef, newRef.getObjectId());
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, oldRef, newRef.getObjectId());
RefUpdate refUpdate = RefUpdateStub.forSuccessfulUpdate(oldRef, newRef.getObjectId());
@@ -82,7 +82,7 @@
@Test(expected = Exception.class)
public void newUpdateShouldValidateAndFailWithIOException() throws Exception {
- doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
+ doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
RefUpdate refUpdate = RefUpdateStub.forSuccessfulUpdate(oldRef, newRef.getObjectId());
@@ -94,7 +94,7 @@
@Test
public void newUpdateShouldIncreaseRefUpdateFailureCountWhenFailing() throws IOException {
- doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
+ doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
RefUpdate refUpdate = RefUpdateStub.forSuccessfulUpdate(oldRef, newRef.getObjectId());
@@ -113,10 +113,10 @@
public void newUpdateShouldNotIncreaseSplitBrainPreventedCounterIfFailingSharedDbPostUpdate()
throws IOException {
- doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
+ doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
doReturn(false)
.when(sharedRefDb)
- .compareAndPut(A_TEST_PROJECT_NAME, oldRef, newRef.getObjectId());
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, oldRef, newRef.getObjectId());
RefUpdate refUpdate = RefUpdateStub.forSuccessfulUpdate(oldRef, newRef.getObjectId());
@@ -135,10 +135,10 @@
public void newUpdateShouldtIncreaseSplitBrainCounterIfFailingSharedDbPostUpdate()
throws IOException {
- doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
+ doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
doReturn(false)
.when(sharedRefDb)
- .compareAndPut(A_TEST_PROJECT_NAME, oldRef, newRef.getObjectId());
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, oldRef, newRef.getObjectId());
RefUpdate refUpdate = RefUpdateStub.forSuccessfulUpdate(oldRef, newRef.getObjectId());
@@ -155,9 +155,11 @@
@Test
public void deleteShouldValidateAndSucceed() throws IOException {
- doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
+ doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
- doReturn(true).when(sharedRefDb).compareAndPut(A_TEST_PROJECT_NAME, oldRef, ObjectId.zeroId());
+ doReturn(true)
+ .when(sharedRefDb)
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, oldRef, ObjectId.zeroId());
RefUpdate refUpdate = RefUpdateStub.forSuccessfulDelete(oldRef);
@@ -171,7 +173,7 @@
@Test
public void deleteShouldIncreaseRefUpdateFailureCountWhenFailing() throws IOException {
- doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, oldRef);
+ doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, oldRef);
RefUpdate refUpdate = RefUpdateStub.forSuccessfulDelete(oldRef);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRepositoryTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRepositoryTest.java
index eb05b30..15c596f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRepositoryTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultiSiteRepositoryTest.java
@@ -18,7 +18,7 @@
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
import java.io.IOException;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate.Result;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectDeletedSharedDbCleanupTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectDeletedSharedDbCleanupTest.java
new file mode 100644
index 0000000..ba381a4
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/ProjectDeletedSharedDbCleanupTest.java
@@ -0,0 +1,45 @@
+package com.googlesource.gerrit.plugins.multisite.validation;
+
+import com.google.gerrit.extensions.api.changes.NotifyHandling;
+import com.google.gerrit.extensions.events.ProjectDeletedListener;
+import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ProjectDeletedSharedDbCleanupTest implements RefFixture {
+ @Rule public TestName nameRule = new TestName();
+
+ @Mock ValidationMetrics mockValidationMetrics;
+ @Mock SharedRefDatabaseWrapper sharedRefDatabase;
+
+ @Test
+ public void aDeleteProjectEventShouldCleanupProjectFromZk() throws Exception {
+ String projectName = A_TEST_PROJECT_NAME;
+ ProjectDeletedSharedDbCleanup projectDeletedSharedDbCleanup =
+ new ProjectDeletedSharedDbCleanup(sharedRefDatabase, mockValidationMetrics);
+
+ ProjectDeletedListener.Event event =
+ new ProjectDeletedListener.Event() {
+ @Override
+ public String getProjectName() {
+ return projectName;
+ }
+
+ @Override
+ public NotifyHandling getNotify() {
+ return NotifyHandling.NONE;
+ }
+ };
+
+ projectDeletedSharedDbCleanup.onProjectDeleted(event);
+
+ Mockito.verify(sharedRefDatabase, Mockito.times(1)).remove(A_TEST_PROJECT_NAME_KEY);
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
index f0677b8..a9968c4 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/RefUpdateValidatorTest.java
@@ -16,20 +16,17 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
+import com.google.gerrit.reviewdb.client.Project;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.OutOfSyncException;
+import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedDbSplitBrainException;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate;
@@ -86,15 +83,18 @@
@Test
public void validationShouldSucceedWhenLocalRefDbIsUpToDate() throws Exception {
- lenient().doReturn(false).when(sharedRefDb).isUpToDate(anyString(), any(Ref.class));
- doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, localRef);
lenient()
.doReturn(false)
.when(sharedRefDb)
- .compareAndPut(anyString(), any(Ref.class), any(ObjectId.class));
+ .isUpToDate(any(Project.NameKey.class), any(Ref.class));
+ doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, localRef);
+ lenient()
+ .doReturn(false)
+ .when(sharedRefDb)
+ .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));
doReturn(true)
.when(sharedRefDb)
- .compareAndPut(A_TEST_PROJECT_NAME, localRef, newUpdateRef.getObjectId());
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, localRef, newUpdateRef.getObjectId());
Result result = refUpdateValidator.executeRefUpdate(refUpdate, () -> RefUpdate.Result.NEW);
@@ -104,14 +104,14 @@
@Test
public void sharedRefDbShouldBeUpdatedWithRefDeleted() throws Exception {
doReturn(ObjectId.zeroId()).when(refUpdate).getNewObjectId();
- doReturn(true).when(sharedRefDb).isUpToDate(anyString(), any(Ref.class));
+ doReturn(true).when(sharedRefDb).isUpToDate(any(Project.NameKey.class), any(Ref.class));
lenient()
.doReturn(false)
.when(sharedRefDb)
- .compareAndPut(anyString(), any(Ref.class), any(ObjectId.class));
+ .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));
doReturn(true)
.when(sharedRefDb)
- .compareAndPut(A_TEST_PROJECT_NAME, localRef, ObjectId.zeroId());
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, localRef, ObjectId.zeroId());
doReturn(localRef).doReturn(null).when(localRefDb).getRef(refName);
Result result = refUpdateValidator.executeRefUpdate(refUpdate, () -> RefUpdate.Result.FORCED);
@@ -121,16 +121,16 @@
@Test
public void sharedRefDbShouldBeUpdatedWithNewRefCreated() throws Exception {
- Ref localNullRef = SharedRefDatabase.nullRef(refName);
+ Ref localNullRef = nullRef(refName);
- doReturn(true).when(sharedRefDb).isUpToDate(anyString(), any(Ref.class));
+ doReturn(true).when(sharedRefDb).isUpToDate(any(Project.NameKey.class), any(Ref.class));
lenient()
.doReturn(false)
.when(sharedRefDb)
- .compareAndPut(anyString(), any(Ref.class), any(ObjectId.class));
+ .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));
doReturn(true)
.when(sharedRefDb)
- .compareAndPut(A_TEST_PROJECT_NAME, localNullRef, newUpdateRef.getObjectId());
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, localNullRef, newUpdateRef.getObjectId());
doReturn(localNullRef).doReturn(newUpdateRef).when(localRefDb).getRef(refName);
Result result = refUpdateValidator.executeRefUpdate(refUpdate, () -> RefUpdate.Result.NEW);
@@ -138,44 +138,52 @@
assertThat(result).isEqualTo(RefUpdate.Result.NEW);
}
- @Test(expected = OutOfSyncException.class)
- public void validationShouldFailWhenLocalRefDbIsNotUpToDate() throws Exception {
- lenient().doReturn(true).when(sharedRefDb).isUpToDate(anyString(), any(Ref.class));
- doReturn(true).when(sharedRefDb).exists(A_TEST_PROJECT_NAME, refName);
- doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, localRef);
+ @Test
+ public void validationShouldFailWhenLocalRefDbIsOutOfSync() throws Exception {
+ lenient()
+ .doReturn(true)
+ .when(sharedRefDb)
+ .isUpToDate(any(Project.NameKey.class), any(Ref.class));
+ doReturn(true).when(sharedRefDb).exists(A_TEST_PROJECT_NAME_KEY, refName);
+ doReturn(false).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, localRef);
- refUpdateValidator.executeRefUpdate(refUpdate, () -> RefUpdate.Result.NEW);
+ Result result = refUpdateValidator.executeRefUpdate(refUpdate, () -> RefUpdate.Result.NEW);
+
+ assertThat(result).isEqualTo(Result.LOCK_FAILURE);
}
@Test(expected = SharedDbSplitBrainException.class)
public void shouldTrowSplitBrainWhenLocalRefDbIsUpToDateButFinalCompareAndPutIsFailing()
throws Exception {
- lenient().doReturn(false).when(sharedRefDb).isUpToDate(anyString(), any(Ref.class));
- doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, localRef);
+ lenient()
+ .doReturn(false)
+ .when(sharedRefDb)
+ .isUpToDate(any(Project.NameKey.class), any(Ref.class));
+ doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, localRef);
lenient()
.doReturn(true)
.when(sharedRefDb)
- .compareAndPut(anyString(), any(Ref.class), any(ObjectId.class));
+ .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));
doReturn(false)
.when(sharedRefDb)
- .compareAndPut(A_TEST_PROJECT_NAME, localRef, newUpdateRef.getObjectId());
+ .compareAndPut(A_TEST_PROJECT_NAME_KEY, localRef, newUpdateRef.getObjectId());
refUpdateValidator.executeRefUpdate(refUpdate, () -> RefUpdate.Result.NEW);
}
@Test
public void shouldNotUpdateSharedRefDbWhenFinalCompareAndPutIsFailing() throws Exception {
- lenient().doReturn(false).when(sharedRefDb).isUpToDate(anyString(), any(Ref.class));
- doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME, localRef);
+ lenient()
+ .doReturn(false)
+ .when(sharedRefDb)
+ .isUpToDate(any(Project.NameKey.class), any(Ref.class));
+ doReturn(true).when(sharedRefDb).isUpToDate(A_TEST_PROJECT_NAME_KEY, localRef);
Result result =
refUpdateValidator.executeRefUpdate(refUpdate, () -> RefUpdate.Result.LOCK_FAILURE);
- verify(sharedRefDb, never()).compareAndPut(anyString(), any(Ref.class), any(ObjectId.class));
+ verify(sharedRefDb, never())
+ .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));
assertThat(result).isEqualTo(RefUpdate.Result.LOCK_FAILURE);
}
-
- private Ref newRef(String refName, ObjectId objectId) {
- return new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, refName, objectId);
- }
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/CustomSharedRefEnforcementByProjectTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/CustomSharedRefEnforcementByProjectTest.java
similarity index 94%
rename from src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/CustomSharedRefEnforcementByProjectTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/CustomSharedRefEnforcementByProjectTest.java
index d63436c..4ee3c85 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/CustomSharedRefEnforcementByProjectTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/CustomSharedRefEnforcementByProjectTest.java
@@ -12,15 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper;
+package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb;
import static com.google.common.truth.Truth.assertThat;
-import static com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase.newRef;
import com.googlesource.gerrit.plugins.multisite.Configuration;
import com.googlesource.gerrit.plugins.multisite.Configuration.SharedRefDatabase;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.CustomSharedRefEnforcementByProject;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement.EnforcePolicy;
import java.util.Arrays;
import org.eclipse.jgit.lib.Config;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/DefaultSharedRefEnforcementTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/DefaultSharedRefEnforcementTest.java
similarity index 89%
rename from src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/DefaultSharedRefEnforcementTest.java
rename to src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/DefaultSharedRefEnforcementTest.java
index 83fcf52..b462408 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/DefaultSharedRefEnforcementTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/DefaultSharedRefEnforcementTest.java
@@ -12,13 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper;
+package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb;
import static com.google.common.truth.Truth.assertThat;
-import static com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase.newRef;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement.EnforcePolicy;
import org.eclipse.jgit.lib.Ref;
import org.junit.Test;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/MultisiteReplicationPushFilterTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/MultisiteReplicationPushFilterTest.java
index caf0d69..087259a 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/MultisiteReplicationPushFilterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/MultisiteReplicationPushFilterTest.java
@@ -19,7 +19,11 @@
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDatabase;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException;
+import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
import com.google.gerrit.extensions.registration.DynamicItem;
+import com.google.gerrit.reviewdb.client.Project;
import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
import com.googlesource.gerrit.plugins.multisite.validation.DisabledSharedRefLogger;
import com.googlesource.gerrit.plugins.multisite.validation.MultisiteReplicationPushFilter;
@@ -43,12 +47,13 @@
@Mock SharedRefDatabaseWrapper sharedRefDatabaseMock;
String project = "fooProject";
+ Project.NameKey projectName = new Project.NameKey(project);
@Test
public void shouldReturnAllRefUpdatesWhenAllUpToDate() throws Exception {
List<RemoteRefUpdate> refUpdates =
Arrays.asList(refUpdate("refs/heads/foo"), refUpdate("refs/heads/bar"));
- doReturn(true).when(sharedRefDatabaseMock).isUpToDate(eq(project), any());
+ doReturn(true).when(sharedRefDatabaseMock).isUpToDate(eq(projectName), any());
MultisiteReplicationPushFilter pushFilter =
new MultisiteReplicationPushFilter(sharedRefDatabaseMock);
@@ -92,35 +97,37 @@
Set<String> rejectedSet = new HashSet<>();
rejectedSet.addAll(Arrays.asList(rejectedRefs));
- SharedRefDatabase sharedRefDatabase =
- new SharedRefDatabase() {
+ GlobalRefDatabase sharedRefDatabase =
+ new GlobalRefDatabase() {
@Override
- public void removeProject(String project) throws IOException {}
-
- @Override
- public AutoCloseable lockRef(String project, String refName) throws SharedLockException {
- return null;
- }
-
- @Override
- public boolean isUpToDate(String project, Ref ref) throws SharedLockException {
+ public boolean isUpToDate(Project.NameKey project, Ref ref)
+ throws GlobalRefDbLockException {
return !rejectedSet.contains(ref.getName());
}
@Override
- public boolean exists(String project, String refName) {
+ public boolean exists(Project.NameKey project, String refName) {
return true;
}
@Override
- public boolean compareAndPut(String project, Ref currRef, ObjectId newRefValue)
- throws IOException {
+ public boolean compareAndPut(Project.NameKey project, Ref currRef, ObjectId newRefValue)
+ throws GlobalRefDbSystemError {
return false;
}
+
+ @Override
+ public AutoCloseable lockRef(Project.NameKey project, String refName)
+ throws GlobalRefDbLockException {
+ return null;
+ }
+
+ @Override
+ public void remove(Project.NameKey project) throws GlobalRefDbSystemError {}
};
return new SharedRefDatabaseWrapper(
- DynamicItem.itemOf(SharedRefDatabase.class, sharedRefDatabase),
+ DynamicItem.itemOf(GlobalRefDatabase.class, sharedRefDatabase),
new DisabledSharedRefLogger());
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/NoopSharedRefDatabaseTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/NoopSharedRefDatabaseTest.java
new file mode 100644
index 0000000..c63530a
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/NoopSharedRefDatabaseTest.java
@@ -0,0 +1,28 @@
+package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import org.eclipse.jgit.lib.Ref;
+import org.junit.Test;
+
+public class NoopSharedRefDatabaseTest implements RefFixture {
+
+ private Ref sampleRef = newRef(A_TEST_REF_NAME, AN_OBJECT_ID_1);
+ private NoopSharedRefDatabase objectUnderTest = new NoopSharedRefDatabase();
+
+ @Test
+ public void isUpToDateShouldAlwaysReturnTrue() {
+ assertThat(objectUnderTest.isUpToDate(A_TEST_PROJECT_NAME_KEY, sampleRef)).isTrue();
+ }
+
+ @Test
+ public void compareAndPutShouldAlwaysReturnTrue() {
+ assertThat(objectUnderTest.compareAndPut(A_TEST_PROJECT_NAME_KEY, sampleRef, AN_OBJECT_ID_2))
+ .isTrue();
+ }
+
+ @Test
+ public void existsShouldAlwaysReturnFalse() {
+ assertThat(objectUnderTest.exists(A_TEST_PROJECT_NAME_KEY, A_TEST_REF_NAME)).isFalse();
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/RefFixture.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefFixture.java
similarity index 84%
rename from src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/RefFixture.java
rename to src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefFixture.java
index 72ea236..8ddbf5c 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/RefFixture.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefFixture.java
@@ -12,11 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper;
+package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdRef;
+import org.eclipse.jgit.lib.Ref;
import org.junit.Ignore;
@Ignore
@@ -41,4 +43,12 @@
default String testBranch() {
return "aTestBranch";
}
+
+ default Ref newRef(String refName, ObjectId objectId) {
+ return new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, refName, objectId);
+ }
+
+ default Ref nullRef(String refName) {
+ return newRef(refName, ObjectId.zeroId());
+ }
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefSharedDatabaseTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefSharedDatabaseTest.java
index 57ab5e0..c9eeaa8 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefSharedDatabaseTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefSharedDatabaseTest.java
@@ -16,8 +16,8 @@
import static com.google.common.truth.Truth.assertThat;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.RefFixture;
import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Ref.Storage;
import org.junit.Rule;
@@ -38,7 +38,7 @@
ObjectId objectId = AN_OBJECT_ID_1;
String refName = aBranchRef();
- Ref aNewRef = SharedRefDatabase.newRef(refName, objectId);
+ Ref aNewRef = new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, refName, objectId);
assertThat(aNewRef.getName()).isEqualTo(refName);
assertThat(aNewRef.getObjectId()).isEqualTo(objectId);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/RefUpdateStub.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefUpdateStub.java
similarity index 99%
rename from src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/RefUpdateStub.java
rename to src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefUpdateStub.java
index cec476e..7c1d7b4 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/RefUpdateStub.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/RefUpdateStub.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper;
+package com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb;
import java.io.IOException;
import org.apache.commons.lang.NotImplementedException;
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java
deleted file mode 100644
index e2bdfbc..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseIT.java
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (C) 2019 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.multisite.validation.dfsrefdb.zookeeper;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.extensions.registration.DynamicItem;
-import com.google.gerrit.metrics.DisabledMetricMaker;
-import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
-import com.googlesource.gerrit.plugins.multisite.validation.BatchRefUpdateValidator;
-import com.googlesource.gerrit.plugins.multisite.validation.DisabledSharedRefLogger;
-import com.googlesource.gerrit.plugins.multisite.validation.DummyLockWrapper;
-import com.googlesource.gerrit.plugins.multisite.validation.MultiSiteBatchRefUpdate;
-import com.googlesource.gerrit.plugins.multisite.validation.ValidationMetrics;
-import com.googlesource.gerrit.plugins.multisite.validation.ZkConnectionConfig;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
-import org.apache.curator.retry.RetryNTimes;
-import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
-import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.RefDatabase;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
-import org.eclipse.jgit.transport.ReceiveCommand.Result;
-import org.eclipse.jgit.transport.ReceiveCommand.Type;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-
-public class ZkSharedRefDatabaseIT extends AbstractDaemonTest implements RefFixture {
- @Rule public TestName nameRule = new TestName();
-
- ZookeeperTestContainerSupport zookeeperContainer;
- SharedRefDatabaseWrapper zkSharedRefDatabase;
- SharedRefEnforcement refEnforcement;
-
- int SLEEP_BETWEEN_RETRIES_MS = 30;
- long TRANSACTION_LOCK_TIMEOUT = 1000l;
- int NUMBER_OF_RETRIES = 5;
-
- @Before
- public void setup() {
- refEnforcement = new DefaultSharedRefEnforcement();
- zookeeperContainer = new ZookeeperTestContainerSupport(false);
- zkSharedRefDatabase =
- new SharedRefDatabaseWrapper(
- DynamicItem.itemOf(
- SharedRefDatabase.class,
- new ZkSharedRefDatabase(
- zookeeperContainer.getCurator(),
- new ZkConnectionConfig(
- new RetryNTimes(NUMBER_OF_RETRIES, SLEEP_BETWEEN_RETRIES_MS),
- TRANSACTION_LOCK_TIMEOUT))),
- new DisabledSharedRefLogger());
- }
-
- @After
- public void cleanup() {
- zookeeperContainer.cleanup();
- }
-
- @Test
- public void sequenceOfGitUpdatesWithARejectionCausesZKCheckToFail() throws Exception {
- ObjectId commitObjectIdOne = commitBuilder().add("test_file.txt", "A").create().getId();
- ObjectId commitObjectIdTwo = commitBuilder().add("test_file.txt", "B").create().getId();
- ObjectId commitObjectIdThree = commitBuilder().add("test_file.txt", "A2").create().getId();
-
- ReceiveCommand aRefCreation =
- new ReceiveCommand(ObjectId.zeroId(), commitObjectIdOne, A_TEST_REF_NAME);
-
- ReceiveCommand aCommandThatWillBeRejectedByJGit =
- new ReceiveCommand(
- commitObjectIdOne, commitObjectIdTwo, A_TEST_REF_NAME, Type.UPDATE_NONFASTFORWARD);
-
- ReceiveCommand aCommandThatShouldSucceed =
- new ReceiveCommand(commitObjectIdOne, commitObjectIdThree, A_TEST_REF_NAME, Type.UPDATE);
-
- InMemoryRepository repository = testRepo.getRepository();
- try (RevWalk rw = new RevWalk(repository)) {
- newBatchRefUpdate(repository, aRefCreation).execute(rw, NullProgressMonitor.INSTANCE);
-
- // The rejection of this command should not leave the shared DB into an inconsistent state
- newBatchRefUpdate(repository, aCommandThatWillBeRejectedByJGit)
- .execute(rw, NullProgressMonitor.INSTANCE);
-
- // This command will succeed only if the previous one is not leaving any traces in the
- // shared ref DB
- newBatchRefUpdate(repository, aCommandThatShouldSucceed)
- .execute(rw, NullProgressMonitor.INSTANCE);
-
- assertThat(aRefCreation.getResult()).isEqualTo(Result.OK);
- assertThat(aCommandThatWillBeRejectedByJGit.getResult())
- .isEqualTo(Result.REJECTED_NONFASTFORWARD);
- assertThat(aCommandThatShouldSucceed.getResult()).isEqualTo(Result.OK);
- }
- }
-
- @Test
- public void aBatchWithOneFailedCommandShouldFailAllOtherCommands() throws Exception {
- ObjectId commitObjectIdOne = commitBuilder().add("test_file1.txt", "A").create().getId();
- ObjectId commitObjectIdTwo = commitBuilder().add("test_file1.txt", "B").create().getId();
- ObjectId commitObjectIdThree = commitBuilder().add("test_file2.txt", "C").create().getId();
-
- ReceiveCommand firstCommand =
- new ReceiveCommand(ObjectId.zeroId(), commitObjectIdOne, A_TEST_REF_NAME);
-
- ReceiveCommand aNonFastForwardUpdate =
- new ReceiveCommand(
- commitObjectIdOne, commitObjectIdTwo, A_TEST_REF_NAME, Type.UPDATE_NONFASTFORWARD);
-
- ReceiveCommand aNewCreate =
- new ReceiveCommand(ObjectId.zeroId(), commitObjectIdThree, "refs/for/master2");
-
- InMemoryRepository repository = testRepo.getRepository();
- try (RevWalk rw = new RevWalk(repository)) {
- newBatchRefUpdate(repository, firstCommand, aNonFastForwardUpdate, aNewCreate)
- .execute(rw, NullProgressMonitor.INSTANCE);
- }
-
- // All commands in batch failed because of the second one
- assertThat(firstCommand.getResult()).isEqualTo(Result.REJECTED_OTHER_REASON);
- assertThat(aNonFastForwardUpdate.getResult()).isEqualTo(Result.REJECTED_NONFASTFORWARD);
- assertThat(aNewCreate.getResult()).isEqualTo(Result.REJECTED_OTHER_REASON);
-
- // Zookeeper has been left untouched
- assertFalse(existsDataInZkForCommand(firstCommand));
- assertFalse(existsDataInZkForCommand(aNonFastForwardUpdate));
- assertFalse(existsDataInZkForCommand(aNewCreate));
- }
-
- @Test
- public void shouldBeSuccessfulWhenRefIsRecreated() throws Exception {
- ObjectId commitObjectIdOne = commitBuilder().add("test_file1.txt", "A").create().getId();
- ObjectId commitObjectIdTwo = commitBuilder().add("test_file1.txt", "B").create().getId();
-
- ReceiveCommand firstCommand =
- new ReceiveCommand(ObjectId.zeroId(), commitObjectIdOne, A_TEST_REF_NAME);
-
- ReceiveCommand deleteCommand =
- new ReceiveCommand(commitObjectIdOne, ObjectId.zeroId(), A_TEST_REF_NAME, Type.DELETE);
-
- ReceiveCommand secondCommand =
- new ReceiveCommand(ObjectId.zeroId(), commitObjectIdTwo, A_TEST_REF_NAME);
-
- InMemoryRepository repository = testRepo.getRepository();
- try (RevWalk rw = new RevWalk(repository)) {
-
- newBatchRefUpdate(repository, firstCommand).execute(rw, NullProgressMonitor.INSTANCE);
- newBatchRefUpdate(repository, deleteCommand).execute(rw, NullProgressMonitor.INSTANCE);
- newBatchRefUpdate(repository, secondCommand).execute(rw, NullProgressMonitor.INSTANCE);
- }
-
- assertTrue(existsDataInZkForCommand(secondCommand));
- }
-
- private boolean existsDataInZkForCommand(ReceiveCommand firstCommand) throws Exception {
- return zkSharedRefDatabase.exists(A_TEST_PROJECT_NAME, firstCommand.getRefName());
- }
-
- private MultiSiteBatchRefUpdate newBatchRefUpdate(
- Repository localGitRepo, ReceiveCommand... commands) {
-
- BatchRefUpdateValidator.Factory batchRefValidatorFactory =
- new BatchRefUpdateValidator.Factory() {
- @Override
- public BatchRefUpdateValidator create(String projectName, RefDatabase refDb) {
- return new BatchRefUpdateValidator(
- zkSharedRefDatabase,
- new ValidationMetrics(new DisabledMetricMaker()),
- new DefaultSharedRefEnforcement(),
- new DummyLockWrapper(),
- projectName,
- refDb);
- }
- };
-
- MultiSiteBatchRefUpdate result =
- new MultiSiteBatchRefUpdate(
- batchRefValidatorFactory, A_TEST_PROJECT_NAME, localGitRepo.getRefDatabase());
-
- result.setAllowNonFastForwards(false);
- for (ReceiveCommand command : commands) {
- result.addCommand(command);
- }
- return result;
- }
-
- @Override
- public String testBranch() {
- return "branch_" + nameRule.getMethodName();
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseTest.java
deleted file mode 100644
index bff41f1..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZkSharedRefDatabaseTest.java
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (C) 2019 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.multisite.validation.dfsrefdb.zookeeper;
-
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.mock;
-
-import com.google.gerrit.extensions.api.changes.NotifyHandling;
-import com.google.gerrit.extensions.events.ProjectDeletedListener;
-import com.google.gerrit.extensions.registration.DynamicItem;
-import com.googlesource.gerrit.plugins.multisite.SharedRefDatabaseWrapper;
-import com.googlesource.gerrit.plugins.multisite.validation.DisabledSharedRefLogger;
-import com.googlesource.gerrit.plugins.multisite.validation.ProjectDeletedSharedDbCleanup;
-import com.googlesource.gerrit.plugins.multisite.validation.ValidationMetrics;
-import com.googlesource.gerrit.plugins.multisite.validation.ZkConnectionConfig;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.DefaultSharedRefEnforcement;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefDatabase;
-import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.SharedRefEnforcement;
-import org.apache.curator.retry.RetryNTimes;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestName;
-
-public class ZkSharedRefDatabaseTest implements RefFixture {
- @Rule public TestName nameRule = new TestName();
-
- ZookeeperTestContainerSupport zookeeperContainer;
- SharedRefDatabaseWrapper zkSharedRefDatabase;
- SharedRefEnforcement refEnforcement;
-
- ValidationMetrics mockValidationMetrics;
-
- @Before
- public void setup() {
- refEnforcement = new DefaultSharedRefEnforcement();
- zookeeperContainer = new ZookeeperTestContainerSupport(false);
- int SLEEP_BETWEEN_RETRIES_MS = 30;
- long TRANSACTION_LOCK_TIMEOUT = 1000l;
- int NUMBER_OF_RETRIES = 5;
-
- zkSharedRefDatabase =
- new SharedRefDatabaseWrapper(
- DynamicItem.itemOf(
- SharedRefDatabase.class,
- new ZkSharedRefDatabase(
- zookeeperContainer.getCurator(),
- new ZkConnectionConfig(
- new RetryNTimes(NUMBER_OF_RETRIES, SLEEP_BETWEEN_RETRIES_MS),
- TRANSACTION_LOCK_TIMEOUT))),
- new DisabledSharedRefLogger());
-
- mockValidationMetrics = mock(ValidationMetrics.class);
- }
-
- @After
- public void cleanup() {
- zookeeperContainer.cleanup();
- }
-
- @Test
- public void shouldCompareAndPutSuccessfully() throws Exception {
- Ref oldRef = refOf(AN_OBJECT_ID_1);
- Ref newRef = refOf(AN_OBJECT_ID_2);
- String projectName = A_TEST_PROJECT_NAME;
-
- zookeeperContainer.createRefInZk(projectName, oldRef);
-
- assertThat(zkSharedRefDatabase.compareAndPut(projectName, oldRef, newRef.getObjectId()))
- .isTrue();
- }
-
- @Test
- public void shouldFetchLatestObjectIdInZk() throws Exception {
- Ref oldRef = refOf(AN_OBJECT_ID_1);
- Ref newRef = refOf(AN_OBJECT_ID_2);
- String projectName = A_TEST_PROJECT_NAME;
-
- zookeeperContainer.createRefInZk(projectName, oldRef);
-
- assertThat(zkSharedRefDatabase.compareAndPut(projectName, oldRef, newRef.getObjectId()))
- .isTrue();
-
- assertThat(zkSharedRefDatabase.isUpToDate(projectName, newRef)).isTrue();
- assertThat(zkSharedRefDatabase.isUpToDate(projectName, oldRef)).isFalse();
- }
-
- @Test
- public void shouldCompareAndPutWithNullOldRefSuccessfully() throws Exception {
- Ref oldRef = refOf(null);
- Ref newRef = refOf(AN_OBJECT_ID_2);
- String projectName = A_TEST_PROJECT_NAME;
-
- zookeeperContainer.createRefInZk(projectName, oldRef);
-
- assertThat(zkSharedRefDatabase.compareAndPut(projectName, oldRef, newRef.getObjectId()))
- .isTrue();
- }
-
- @Test
- public void compareAndPutShouldFailIfTheObjectionHasNotTheExpectedValue() throws Exception {
- String projectName = A_TEST_PROJECT_NAME;
-
- Ref oldRef = refOf(AN_OBJECT_ID_1);
- Ref expectedRef = refOf(AN_OBJECT_ID_2);
-
- zookeeperContainer.createRefInZk(projectName, oldRef);
-
- assertThat(zkSharedRefDatabase.compareAndPut(projectName, expectedRef, AN_OBJECT_ID_3))
- .isFalse();
- }
-
- private Ref refOf(ObjectId objectId) {
- return SharedRefDatabase.newRef(aBranchRef(), objectId);
- }
-
- @Test
- public void removeProjectShouldRemoveTheWholePathInZk() throws Exception {
- String projectName = A_TEST_PROJECT_NAME;
- Ref someRef = refOf(AN_OBJECT_ID_1);
-
- zookeeperContainer.createRefInZk(projectName, someRef);
-
- assertThat(zookeeperContainer.readRefValueFromZk(projectName, someRef))
- .isEqualTo(AN_OBJECT_ID_1);
-
- assertThat(getNumChildrenForPath("/")).isEqualTo(1);
-
- zkSharedRefDatabase.removeProject(projectName);
-
- assertThat(getNumChildrenForPath("/")).isEqualTo(0);
- }
-
- @Test
- public void aDeleteProjectEventShouldCleanupProjectFromZk() throws Exception {
- String projectName = A_TEST_PROJECT_NAME;
- Ref someRef = refOf(AN_OBJECT_ID_1);
- ProjectDeletedSharedDbCleanup projectDeletedSharedDbCleanup =
- new ProjectDeletedSharedDbCleanup(zkSharedRefDatabase, mockValidationMetrics);
-
- ProjectDeletedListener.Event event =
- new ProjectDeletedListener.Event() {
- @Override
- public String getProjectName() {
- return projectName;
- }
-
- @Override
- public NotifyHandling getNotify() {
- return NotifyHandling.NONE;
- }
- };
-
- zookeeperContainer.createRefInZk(projectName, someRef);
-
- assertThat(getNumChildrenForPath("/")).isEqualTo(1);
-
- projectDeletedSharedDbCleanup.onProjectDeleted(event);
-
- assertThat(getNumChildrenForPath("/")).isEqualTo(0);
- }
-
- @Override
- public String testBranch() {
- return "branch_" + nameRule.getMethodName();
- }
-
- private int getNumChildrenForPath(String path) throws Exception {
- return zookeeperContainer
- .getCurator()
- .checkExists()
- .forPath(String.format(path))
- .getNumChildren();
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZookeeperTestContainerSupport.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZookeeperTestContainerSupport.java
deleted file mode 100644
index 3237e3a..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/dfsrefdb/zookeeper/ZookeeperTestContainerSupport.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (C) 2019 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.multisite.validation.dfsrefdb.zookeeper;
-
-import static com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.ZkSharedRefDatabase.pathFor;
-import static com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.zookeeper.ZkSharedRefDatabase.writeObjectId;
-
-import com.googlesource.gerrit.plugins.multisite.ZookeeperConfig;
-import org.apache.curator.framework.CuratorFramework;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.junit.Ignore;
-import org.testcontainers.containers.GenericContainer;
-import org.testcontainers.containers.wait.strategy.Wait;
-
-@Ignore
-public class ZookeeperTestContainerSupport {
-
- static class ZookeeperContainer extends GenericContainer<ZookeeperContainer> {
- public static String ZOOKEEPER_VERSION = "3.4.13";
-
- public ZookeeperContainer() {
- super("zookeeper:" + ZOOKEEPER_VERSION);
- }
- }
-
- private ZookeeperContainer container;
- private ZookeeperConfig configuration;
- private CuratorFramework curator;
-
- public CuratorFramework getCurator() {
- return curator;
- }
-
- public ZookeeperContainer getContainer() {
- return container;
- }
-
- @SuppressWarnings("resource")
- public ZookeeperTestContainerSupport(boolean migrationMode) {
- container = new ZookeeperContainer().withExposedPorts(2181).waitingFor(Wait.forListeningPort());
- container.start();
- Integer zkHostPort = container.getMappedPort(2181);
- Config sharedRefDbConfig = new Config();
- String connectString = container.getContainerIpAddress() + ":" + zkHostPort;
- sharedRefDbConfig.setBoolean("ref-database", null, "enabled", true);
- sharedRefDbConfig.setString("ref-database", "zookeeper", "connectString", connectString);
- sharedRefDbConfig.setString(
- "ref-database",
- ZookeeperConfig.SUBSECTION,
- ZookeeperConfig.KEY_CONNECT_STRING,
- connectString);
-
- configuration = new ZookeeperConfig(sharedRefDbConfig);
- this.curator = configuration.buildCurator();
- }
-
- public void cleanup() {
- this.curator.delete();
- this.container.stop();
- }
-
- public ObjectId readRefValueFromZk(String projectName, Ref ref) throws Exception {
- final byte[] bytes = curator.getData().forPath(pathFor(projectName, ref));
- return ZkSharedRefDatabase.readObjectId(bytes);
- }
-
- public void createRefInZk(String projectName, Ref ref) throws Exception {
- curator
- .create()
- .creatingParentContainersIfNeeded()
- .forPath(pathFor(projectName, ref), writeObjectId(ref.getObjectId()));
- }
-}