blob: d4cb48ce5a0e2c8e4d2d5d1adb876b83f25fdd77 [file]
// Copyright (C) 2026 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.gerritforge.gerrit.eventbroker;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.lib.Config;
@Singleton
public class EventsBrokerConfiguration {
static final String EVENTS_BROKER_FILE_NAME = "events-broker";
static final String PARTITION_EVENT_PROPERTY_FIELD = "partitionEventProperty";
static final String PARTITION_VALUE_FIELD = "partitionValue";
static final String TOPIC_SECTION = "topic";
static final String DEFAULT_PARTITION_EVENT_PROPERTY = "type";
private final ImmutableMap<String, ImmutableList<String>> topicToPartitions;
private final ImmutableMap<String, String> topicToEventProperty;
@Inject
public EventsBrokerConfiguration(PluginConfigFactory configFactory) {
// This class is reused by broker implementations, so @PluginName would resolve to the
// implementation plugin name (for example events-kafka) instead of the shared broker config.
Config config = configFactory.getGlobalPluginConfig(EVENTS_BROKER_FILE_NAME);
ImmutableMap.Builder<String, ImmutableList<String>> partitionsByTopic = ImmutableMap.builder();
ImmutableMap.Builder<String, String> eventPropertyByTopic = ImmutableMap.builder();
for (String subsection : config.getSubsections(TOPIC_SECTION)) {
ImmutableList<String> partitionValue =
ImmutableList.copyOf(
config.getStringList(TOPIC_SECTION, subsection, PARTITION_VALUE_FIELD));
if (partitionValue.size() != ImmutableSet.copyOf(partitionValue).size()) {
throw new IllegalArgumentException(
String.format("Duplicate partitionValue entries configured for topic %s", subsection));
}
partitionsByTopic.put(subsection, partitionValue);
eventPropertyByTopic.put(
subsection,
Optional.ofNullable(
config.getString(TOPIC_SECTION, subsection, PARTITION_EVENT_PROPERTY_FIELD))
.orElse(DEFAULT_PARTITION_EVENT_PROPERTY));
}
topicToPartitions = partitionsByTopic.build();
topicToEventProperty = eventPropertyByTopic.build();
}
/**
* Returns the configured logical partition values for the topic.
*
* <p>Returns an empty list when the topic has no configured partition values.
*/
public List<String> getPartitionsForTopic(String topic) {
return topicToPartitions.getOrDefault(topic, ImmutableList.of());
}
/**
* Returns the event property used to pick a logical partition for the topic.
*
* <p>Returns {@link Optional#empty()} when the topic has no partition metadata.
*/
public Optional<String> getEventPropertyForTopic(String topic) {
return Optional.ofNullable(topicToEventProperty.get(topic));
}
}