mirror of https://github.com/apache/druid.git
Add API to return automatic compaction config history (#13699)
Add a new API to return the history of changes to automatic compaction config history to make it easy for users to see what changes have been made to their auto-compaction config. The API is scoped per dataSource to allow users to triage issues with an individual dataSource. The API responds with a list of configs when there is a change to either the settings that impact all auto-compaction configs on a cluster or the dataSource in question.
This commit is contained in:
parent
90d445536d
commit
016c881795
|
@ -470,6 +470,18 @@ Returns all automatic compaction configs.
|
||||||
|
|
||||||
Returns an automatic compaction config of a dataSource.
|
Returns an automatic compaction config of a dataSource.
|
||||||
|
|
||||||
|
`GET /druid/coordinator/v1/config/compaction/{dataSource}/history?interval={interval}&count={count}`
|
||||||
|
|
||||||
|
Returns the history of the automatic compaction config for a dataSource. Optionally accepts `interval` and `count`
|
||||||
|
query string parameters to filter by interval and limit the number of results respectively. If the dataSource does not
|
||||||
|
exist or there is no compaction history for the dataSource, a 404 response is returned.
|
||||||
|
|
||||||
|
The response contains a list of objects with the following keys:
|
||||||
|
* `globalConfig`: A json object containing automatic compaction config that applies to the entire cluster.
|
||||||
|
* `compactionConfig`: A json object containing the automatic compaction config for the datasource.
|
||||||
|
* `auditInfo`: A json object that contains information about the change made - like `author`, `comment` and `ip`.
|
||||||
|
* `auditTime`: The date and time when the change was made.
|
||||||
|
|
||||||
`POST /druid/coordinator/v1/config/compaction/taskslots?ratio={someRatio}&max={someMaxSlots}`
|
`POST /druid/coordinator/v1/config/compaction/taskslots?ratio={someRatio}&max={someMaxSlots}`
|
||||||
|
|
||||||
Update the capacity for compaction tasks. `ratio` and `max` are used to limit the max number of compaction tasks.
|
Update the capacity for compaction tasks. `ratio` and `max` are used to limit the max number of compaction tasks.
|
||||||
|
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.druid.server.coordinator;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.apache.druid.audit.AuditInfo;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DTO containing audit information for compaction config for a datasource.
|
||||||
|
*/
|
||||||
|
public class DataSourceCompactionConfigAuditEntry
|
||||||
|
{
|
||||||
|
private final GlobalCompactionConfig globalConfig;
|
||||||
|
private final DataSourceCompactionConfig compactionConfig;
|
||||||
|
private final AuditInfo auditInfo;
|
||||||
|
private final DateTime auditTime;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public DataSourceCompactionConfigAuditEntry(
|
||||||
|
@JsonProperty("globalConfig") GlobalCompactionConfig globalConfig,
|
||||||
|
@JsonProperty("compactionConfig") DataSourceCompactionConfig compactionConfig,
|
||||||
|
@JsonProperty("auditInfo") AuditInfo auditInfo,
|
||||||
|
@JsonProperty("auditTime") DateTime auditTime
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.globalConfig = globalConfig;
|
||||||
|
this.compactionConfig = compactionConfig;
|
||||||
|
this.auditInfo = auditInfo;
|
||||||
|
this.auditTime = auditTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
public GlobalCompactionConfig getGlobalConfig()
|
||||||
|
{
|
||||||
|
return globalConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
public DataSourceCompactionConfig getCompactionConfig()
|
||||||
|
{
|
||||||
|
return compactionConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
public AuditInfo getAuditInfo()
|
||||||
|
{
|
||||||
|
return auditInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
public DateTime getAuditTime()
|
||||||
|
{
|
||||||
|
return auditTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A DTO containing compaction config for that affects the entire cluster.
|
||||||
|
*/
|
||||||
|
public static class GlobalCompactionConfig
|
||||||
|
{
|
||||||
|
private final double compactionTaskSlotRatio;
|
||||||
|
private final int maxCompactionTaskSlots;
|
||||||
|
private final boolean useAutoScaleSlots;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public GlobalCompactionConfig(
|
||||||
|
@JsonProperty("compactionTaskSlotRatio")
|
||||||
|
double compactionTaskSlotRatio,
|
||||||
|
@JsonProperty("maxCompactionTaskSlots") int maxCompactionTaskSlots,
|
||||||
|
@JsonProperty("useAutoScaleSlots") boolean useAutoScaleSlots
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.compactionTaskSlotRatio = compactionTaskSlotRatio;
|
||||||
|
this.maxCompactionTaskSlots = maxCompactionTaskSlots;
|
||||||
|
this.useAutoScaleSlots = useAutoScaleSlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
public double getCompactionTaskSlotRatio()
|
||||||
|
{
|
||||||
|
return compactionTaskSlotRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
public int getMaxCompactionTaskSlots()
|
||||||
|
{
|
||||||
|
return maxCompactionTaskSlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonProperty
|
||||||
|
public boolean isUseAutoScaleSlots()
|
||||||
|
{
|
||||||
|
return useAutoScaleSlots;
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
public boolean hasSameConfig(CoordinatorCompactionConfig coordinatorCompactionConfig)
|
||||||
|
{
|
||||||
|
return useAutoScaleSlots == coordinatorCompactionConfig.isUseAutoScaleSlots() &&
|
||||||
|
compactionTaskSlotRatio == coordinatorCompactionConfig.getCompactionTaskSlotRatio() &&
|
||||||
|
coordinatorCompactionConfig.getMaxCompactionTaskSlots() == maxCompactionTaskSlots;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.druid.server.coordinator;
|
||||||
|
|
||||||
|
import org.apache.druid.audit.AuditInfo;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class to build the config history for a datasource from audit entries for
|
||||||
|
* {@link CoordinatorCompactionConfig}. The {@link CoordinatorCompactionConfig} contains the entire config for the
|
||||||
|
* cluster, so this class creates adds audit entires to the history only when a setting for this datasource or a global
|
||||||
|
* setting has changed.
|
||||||
|
*/
|
||||||
|
public class DataSourceCompactionConfigHistory
|
||||||
|
{
|
||||||
|
private final Stack<DataSourceCompactionConfigAuditEntry> auditEntries = new Stack<>();
|
||||||
|
private final String dataSource;
|
||||||
|
|
||||||
|
public DataSourceCompactionConfigHistory(String dataSource)
|
||||||
|
{
|
||||||
|
this.dataSource = dataSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(CoordinatorCompactionConfig coordinatorCompactionConfig, AuditInfo auditInfo, DateTime auditTime)
|
||||||
|
{
|
||||||
|
DataSourceCompactionConfigAuditEntry current = auditEntries.isEmpty() ? null : auditEntries.peek();
|
||||||
|
DataSourceCompactionConfigAuditEntry newEntry = null;
|
||||||
|
boolean hasDataSourceCompactionConfig = false;
|
||||||
|
for (DataSourceCompactionConfig dataSourceCompactionConfig : coordinatorCompactionConfig.getCompactionConfigs()) {
|
||||||
|
if (dataSource.equals(dataSourceCompactionConfig.getDataSource())) {
|
||||||
|
hasDataSourceCompactionConfig = true;
|
||||||
|
if (
|
||||||
|
current == null ||
|
||||||
|
(
|
||||||
|
!dataSourceCompactionConfig.equals(current.getCompactionConfig()) ||
|
||||||
|
!current.getGlobalConfig().hasSameConfig(coordinatorCompactionConfig)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
current = new DataSourceCompactionConfigAuditEntry(
|
||||||
|
new DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig(
|
||||||
|
coordinatorCompactionConfig.getCompactionTaskSlotRatio(),
|
||||||
|
coordinatorCompactionConfig.getMaxCompactionTaskSlots(),
|
||||||
|
coordinatorCompactionConfig.isUseAutoScaleSlots()
|
||||||
|
),
|
||||||
|
dataSourceCompactionConfig,
|
||||||
|
auditInfo,
|
||||||
|
auditTime
|
||||||
|
);
|
||||||
|
newEntry = current;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newEntry != null) {
|
||||||
|
auditEntries.push(newEntry);
|
||||||
|
} else if (current != null && !hasDataSourceCompactionConfig) {
|
||||||
|
newEntry = new DataSourceCompactionConfigAuditEntry(
|
||||||
|
new DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig(
|
||||||
|
coordinatorCompactionConfig.getCompactionTaskSlotRatio(),
|
||||||
|
coordinatorCompactionConfig.getMaxCompactionTaskSlots(),
|
||||||
|
coordinatorCompactionConfig.isUseAutoScaleSlots()
|
||||||
|
),
|
||||||
|
null,
|
||||||
|
auditInfo,
|
||||||
|
auditTime
|
||||||
|
);
|
||||||
|
auditEntries.push(newEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DataSourceCompactionConfigAuditEntry> getHistory()
|
||||||
|
{
|
||||||
|
return auditEntries;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,21 +19,28 @@
|
||||||
|
|
||||||
package org.apache.druid.server.http;
|
package org.apache.druid.server.http;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.sun.jersey.spi.container.ResourceFilters;
|
import com.sun.jersey.spi.container.ResourceFilters;
|
||||||
|
import org.apache.druid.audit.AuditEntry;
|
||||||
import org.apache.druid.audit.AuditInfo;
|
import org.apache.druid.audit.AuditInfo;
|
||||||
import org.apache.druid.audit.AuditManager;
|
import org.apache.druid.audit.AuditManager;
|
||||||
import org.apache.druid.common.config.ConfigManager.SetResult;
|
import org.apache.druid.common.config.ConfigManager.SetResult;
|
||||||
import org.apache.druid.common.config.JacksonConfigManager;
|
import org.apache.druid.common.config.JacksonConfigManager;
|
||||||
|
import org.apache.druid.common.utils.ServletResourceUtils;
|
||||||
|
import org.apache.druid.guice.annotations.JsonNonNull;
|
||||||
|
import org.apache.druid.java.util.common.Intervals;
|
||||||
import org.apache.druid.java.util.common.logger.Logger;
|
import org.apache.druid.java.util.common.logger.Logger;
|
||||||
import org.apache.druid.metadata.MetadataStorageConnector;
|
import org.apache.druid.metadata.MetadataStorageConnector;
|
||||||
import org.apache.druid.metadata.MetadataStorageTablesConfig;
|
import org.apache.druid.metadata.MetadataStorageTablesConfig;
|
||||||
import org.apache.druid.server.coordinator.CoordinatorCompactionConfig;
|
import org.apache.druid.server.coordinator.CoordinatorCompactionConfig;
|
||||||
import org.apache.druid.server.coordinator.DataSourceCompactionConfig;
|
import org.apache.druid.server.coordinator.DataSourceCompactionConfig;
|
||||||
|
import org.apache.druid.server.coordinator.DataSourceCompactionConfigHistory;
|
||||||
import org.apache.druid.server.http.security.ConfigResourceFilter;
|
import org.apache.druid.server.http.security.ConfigResourceFilter;
|
||||||
|
import org.joda.time.Interval;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
@ -49,6 +56,9 @@ import javax.ws.rs.QueryParam;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
@ -67,17 +77,23 @@ public class CoordinatorCompactionConfigsResource
|
||||||
private final JacksonConfigManager manager;
|
private final JacksonConfigManager manager;
|
||||||
private final MetadataStorageConnector connector;
|
private final MetadataStorageConnector connector;
|
||||||
private final MetadataStorageTablesConfig connectorConfig;
|
private final MetadataStorageTablesConfig connectorConfig;
|
||||||
|
private final AuditManager auditManager;
|
||||||
|
private final ObjectMapper jsonMapperOnlyNonNullValue;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CoordinatorCompactionConfigsResource(
|
public CoordinatorCompactionConfigsResource(
|
||||||
JacksonConfigManager manager,
|
JacksonConfigManager manager,
|
||||||
MetadataStorageConnector connector,
|
MetadataStorageConnector connector,
|
||||||
MetadataStorageTablesConfig connectorConfig
|
MetadataStorageTablesConfig connectorConfig,
|
||||||
|
AuditManager auditManager,
|
||||||
|
@JsonNonNull ObjectMapper jsonMapperOnlyNonNullValue
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.connector = connector;
|
this.connector = connector;
|
||||||
this.connectorConfig = connectorConfig;
|
this.connectorConfig = connectorConfig;
|
||||||
|
this.auditManager = auditManager;
|
||||||
|
this.jsonMapperOnlyNonNullValue = jsonMapperOnlyNonNullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -101,7 +117,10 @@ public class CoordinatorCompactionConfigsResource
|
||||||
{
|
{
|
||||||
Callable<SetResult> callable = () -> {
|
Callable<SetResult> callable = () -> {
|
||||||
final byte[] currentBytes = getCurrentConfigInByteFromDb();
|
final byte[] currentBytes = getCurrentConfigInByteFromDb();
|
||||||
final CoordinatorCompactionConfig current = CoordinatorCompactionConfig.convertByteToConfig(manager, currentBytes);
|
final CoordinatorCompactionConfig current = CoordinatorCompactionConfig.convertByteToConfig(
|
||||||
|
manager,
|
||||||
|
currentBytes
|
||||||
|
);
|
||||||
final CoordinatorCompactionConfig newCompactionConfig = CoordinatorCompactionConfig.from(
|
final CoordinatorCompactionConfig newCompactionConfig = CoordinatorCompactionConfig.from(
|
||||||
current,
|
current,
|
||||||
compactionTaskSlotRatio,
|
compactionTaskSlotRatio,
|
||||||
|
@ -130,7 +149,10 @@ public class CoordinatorCompactionConfigsResource
|
||||||
{
|
{
|
||||||
Callable<SetResult> callable = () -> {
|
Callable<SetResult> callable = () -> {
|
||||||
final byte[] currentBytes = getCurrentConfigInByteFromDb();
|
final byte[] currentBytes = getCurrentConfigInByteFromDb();
|
||||||
final CoordinatorCompactionConfig current = CoordinatorCompactionConfig.convertByteToConfig(manager, currentBytes);
|
final CoordinatorCompactionConfig current = CoordinatorCompactionConfig.convertByteToConfig(
|
||||||
|
manager,
|
||||||
|
currentBytes
|
||||||
|
);
|
||||||
final CoordinatorCompactionConfig newCompactionConfig;
|
final CoordinatorCompactionConfig newCompactionConfig;
|
||||||
final Map<String, DataSourceCompactionConfig> newConfigs = current
|
final Map<String, DataSourceCompactionConfig> newConfigs = current
|
||||||
.getCompactionConfigs()
|
.getCompactionConfigs()
|
||||||
|
@ -168,6 +190,51 @@ public class CoordinatorCompactionConfigsResource
|
||||||
return Response.ok().entity(config).build();
|
return Response.ok().entity(config).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/{dataSource}/history")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public Response getCompactionConfigHistory(
|
||||||
|
@PathParam("dataSource") String dataSource,
|
||||||
|
@QueryParam("interval") String interval,
|
||||||
|
@QueryParam("count") Integer count
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Interval theInterval = interval == null ? null : Intervals.of(interval);
|
||||||
|
try {
|
||||||
|
List<AuditEntry> auditEntries;
|
||||||
|
if (theInterval == null && count != null) {
|
||||||
|
auditEntries = auditManager.fetchAuditHistory(
|
||||||
|
CoordinatorCompactionConfig.CONFIG_KEY,
|
||||||
|
CoordinatorCompactionConfig.CONFIG_KEY,
|
||||||
|
count
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
auditEntries = auditManager.fetchAuditHistory(
|
||||||
|
CoordinatorCompactionConfig.CONFIG_KEY,
|
||||||
|
CoordinatorCompactionConfig.CONFIG_KEY,
|
||||||
|
theInterval
|
||||||
|
);
|
||||||
|
}
|
||||||
|
DataSourceCompactionConfigHistory history = new DataSourceCompactionConfigHistory(dataSource);
|
||||||
|
for (AuditEntry audit : auditEntries) {
|
||||||
|
CoordinatorCompactionConfig coordinatorCompactionConfig = CoordinatorCompactionConfig.convertByteToConfig(
|
||||||
|
manager,
|
||||||
|
audit.getPayload().getBytes(StandardCharsets.UTF_8)
|
||||||
|
);
|
||||||
|
history.add(coordinatorCompactionConfig, audit.getAuditInfo(), audit.getAuditTime());
|
||||||
|
}
|
||||||
|
if (history.getHistory().isEmpty()) {
|
||||||
|
return Response.status(Response.Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
return Response.ok(history.getHistory()).build();
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST)
|
||||||
|
.entity(ServletResourceUtils.sanitizeException(e))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@DELETE
|
@DELETE
|
||||||
@Path("/{dataSource}")
|
@Path("/{dataSource}")
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
@ -180,7 +247,10 @@ public class CoordinatorCompactionConfigsResource
|
||||||
{
|
{
|
||||||
Callable<SetResult> callable = () -> {
|
Callable<SetResult> callable = () -> {
|
||||||
final byte[] currentBytes = getCurrentConfigInByteFromDb();
|
final byte[] currentBytes = getCurrentConfigInByteFromDb();
|
||||||
final CoordinatorCompactionConfig current = CoordinatorCompactionConfig.convertByteToConfig(manager, currentBytes);
|
final CoordinatorCompactionConfig current = CoordinatorCompactionConfig.convertByteToConfig(
|
||||||
|
manager,
|
||||||
|
currentBytes
|
||||||
|
);
|
||||||
final Map<String, DataSourceCompactionConfig> configs = current
|
final Map<String, DataSourceCompactionConfig> configs = current
|
||||||
.getCompactionConfigs()
|
.getCompactionConfigs()
|
||||||
.stream()
|
.stream()
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.druid.server.coordinator;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class DataSourceCompactionConfigAuditEntryTest
|
||||||
|
{
|
||||||
|
private static final double COMPACTION_TASK_SLOT_RATIO = 0.1;
|
||||||
|
private static final int MAX_COMPACTION_SLOTS = 9;
|
||||||
|
private static final boolean USE_AUTO_SCALE_SLOTS = true;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private CoordinatorCompactionConfig coordinatorCompactionConfig;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
Mockito.when(coordinatorCompactionConfig.getCompactionTaskSlotRatio()).thenReturn(COMPACTION_TASK_SLOT_RATIO);
|
||||||
|
Mockito.when(coordinatorCompactionConfig.getMaxCompactionTaskSlots()).thenReturn(MAX_COMPACTION_SLOTS);
|
||||||
|
Mockito.when(coordinatorCompactionConfig.isUseAutoScaleSlots()).thenReturn(USE_AUTO_SCALE_SLOTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testhasSameConfigWithSameBaseConfigShouldReturnTrue()
|
||||||
|
{
|
||||||
|
DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig config =
|
||||||
|
new DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig(
|
||||||
|
COMPACTION_TASK_SLOT_RATIO,
|
||||||
|
MAX_COMPACTION_SLOTS,
|
||||||
|
USE_AUTO_SCALE_SLOTS
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.assertTrue(config.hasSameConfig(coordinatorCompactionConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testhasSameConfigWithDifferentUseAutoScaleSlotsShouldReturnFalse()
|
||||||
|
{
|
||||||
|
DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig config =
|
||||||
|
new DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig(
|
||||||
|
COMPACTION_TASK_SLOT_RATIO,
|
||||||
|
MAX_COMPACTION_SLOTS,
|
||||||
|
!USE_AUTO_SCALE_SLOTS
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.assertFalse(config.hasSameConfig(coordinatorCompactionConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testhasSameConfigWithDifferentMaxCompactionSlotsShouldReturnFalse()
|
||||||
|
{
|
||||||
|
DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig config =
|
||||||
|
new DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig(
|
||||||
|
COMPACTION_TASK_SLOT_RATIO,
|
||||||
|
MAX_COMPACTION_SLOTS + 1,
|
||||||
|
USE_AUTO_SCALE_SLOTS
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.assertFalse(config.hasSameConfig(coordinatorCompactionConfig));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testhasSameConfigWithDifferentCompactionSlotRatioShouldReturnFalse()
|
||||||
|
{
|
||||||
|
DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig config =
|
||||||
|
new DataSourceCompactionConfigAuditEntry.GlobalCompactionConfig(
|
||||||
|
COMPACTION_TASK_SLOT_RATIO - 0.03,
|
||||||
|
MAX_COMPACTION_SLOTS,
|
||||||
|
USE_AUTO_SCALE_SLOTS
|
||||||
|
);
|
||||||
|
|
||||||
|
Assert.assertFalse(config.hasSameConfig(coordinatorCompactionConfig));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you 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 org.apache.druid.server.coordinator;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import org.apache.druid.audit.AuditInfo;
|
||||||
|
import org.apache.druid.java.util.common.DateTimes;
|
||||||
|
import org.joda.time.DateTime;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Answers;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.mockito.junit.MockitoJUnitRunner;
|
||||||
|
|
||||||
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
|
public class DataSourceCompactionConfigHistoryTest
|
||||||
|
{
|
||||||
|
private static final String DATASOURCE = "DATASOURCE";
|
||||||
|
private static final String DATASOURCE_2 = "DATASOURCE_2";
|
||||||
|
private static final String DATASOURCE_NOT_EXISTS = "DATASOURCE_NOT_EXISTS";
|
||||||
|
private static final double COMPACTION_TASK_SLOT_RATIO = 0.1;
|
||||||
|
private static final int MAX_COMPACTION_TASK_SLOTS = 9;
|
||||||
|
private static final boolean USE_AUTO_SCALE_SLOTS = false;
|
||||||
|
private static final DateTime AUDIT_TIME = DateTimes.of(2023, 1, 13, 9, 0);
|
||||||
|
private static final DateTime AUDIT_TIME_2 = DateTimes.of(2023, 1, 13, 9, 30);
|
||||||
|
private static final DateTime AUDIT_TIME_3 = DateTimes.of(2023, 1, 13, 10, 0);
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private CoordinatorCompactionConfig compactionConfig;
|
||||||
|
@Mock(answer = Answers.RETURNS_MOCKS)
|
||||||
|
private DataSourceCompactionConfig configForDataSource;
|
||||||
|
@Mock(answer = Answers.RETURNS_MOCKS)
|
||||||
|
private DataSourceCompactionConfig configForDataSourceWithChange;
|
||||||
|
@Mock(answer = Answers.RETURNS_MOCKS)
|
||||||
|
private DataSourceCompactionConfig configForDataSource2;
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private AuditInfo auditInfo;
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private AuditInfo auditInfo2;
|
||||||
|
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||||
|
private AuditInfo auditInfo3;
|
||||||
|
|
||||||
|
private DataSourceCompactionConfigHistory target;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
Mockito.when(compactionConfig.getCompactionTaskSlotRatio()).thenReturn(COMPACTION_TASK_SLOT_RATIO);
|
||||||
|
Mockito.when(compactionConfig.getMaxCompactionTaskSlots()).thenReturn(MAX_COMPACTION_TASK_SLOTS);
|
||||||
|
Mockito.when(compactionConfig.isUseAutoScaleSlots()).thenReturn(USE_AUTO_SCALE_SLOTS);
|
||||||
|
Mockito.when(configForDataSource.getDataSource()).thenReturn(DATASOURCE);
|
||||||
|
Mockito.when(configForDataSourceWithChange.getDataSource()).thenReturn(DATASOURCE);
|
||||||
|
Mockito.when(configForDataSource2.getDataSource()).thenReturn(DATASOURCE_2);
|
||||||
|
Mockito.when(compactionConfig.getCompactionConfigs())
|
||||||
|
.thenReturn(ImmutableList.of(configForDataSource, configForDataSource2));
|
||||||
|
target = new DataSourceCompactionConfigHistory(DATASOURCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddCompactionConfigShouldAddToHistory()
|
||||||
|
{
|
||||||
|
target.add(compactionConfig, auditInfo, AUDIT_TIME);
|
||||||
|
Assert.assertEquals(1, target.getHistory().size());
|
||||||
|
DataSourceCompactionConfigAuditEntry auditEntry = target.getHistory().get(0);
|
||||||
|
Assert.assertEquals(DATASOURCE, auditEntry.getCompactionConfig().getDataSource());
|
||||||
|
Assert.assertEquals(auditInfo, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME, auditEntry.getAuditTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddAndDeleteCompactionConfigShouldAddBothToHistory()
|
||||||
|
{
|
||||||
|
target.add(compactionConfig, auditInfo, AUDIT_TIME);
|
||||||
|
Mockito.when(compactionConfig.getCompactionConfigs()).thenReturn(ImmutableList.of(configForDataSource2));
|
||||||
|
target.add(compactionConfig, auditInfo2, AUDIT_TIME_2);
|
||||||
|
Assert.assertEquals(2, target.getHistory().size());
|
||||||
|
DataSourceCompactionConfigAuditEntry auditEntry = target.getHistory().get(0);
|
||||||
|
Assert.assertEquals(DATASOURCE, auditEntry.getCompactionConfig().getDataSource());
|
||||||
|
Assert.assertEquals(auditInfo, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME, auditEntry.getAuditTime());
|
||||||
|
auditEntry = target.getHistory().get(1);
|
||||||
|
Assert.assertEquals(null, auditEntry.getCompactionConfig());
|
||||||
|
Assert.assertEquals(auditInfo2, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME_2, auditEntry.getAuditTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddAndDeleteAnotherCompactionConfigShouldNotAddToHistory()
|
||||||
|
{
|
||||||
|
target.add(compactionConfig, auditInfo, AUDIT_TIME);
|
||||||
|
Mockito.when(compactionConfig.getCompactionConfigs()).thenReturn(ImmutableList.of(configForDataSource));
|
||||||
|
target.add(compactionConfig, auditInfo2, AUDIT_TIME_2);
|
||||||
|
Assert.assertEquals(1, target.getHistory().size());
|
||||||
|
DataSourceCompactionConfigAuditEntry auditEntry = target.getHistory().get(0);
|
||||||
|
Assert.assertEquals(DATASOURCE, auditEntry.getCompactionConfig().getDataSource());
|
||||||
|
Assert.assertEquals(auditInfo, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME, auditEntry.getAuditTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddDeletedAddCompactionConfigShouldAddAllToHistory()
|
||||||
|
{
|
||||||
|
target.add(compactionConfig, auditInfo, AUDIT_TIME);
|
||||||
|
Mockito.when(compactionConfig.getCompactionConfigs()).thenReturn(ImmutableList.of(configForDataSource2));
|
||||||
|
target.add(compactionConfig, auditInfo2, AUDIT_TIME_2);
|
||||||
|
Mockito.when(compactionConfig.getCompactionConfigs())
|
||||||
|
.thenReturn(ImmutableList.of(configForDataSourceWithChange, configForDataSource2));
|
||||||
|
target.add(compactionConfig, auditInfo3, AUDIT_TIME_3);
|
||||||
|
Assert.assertEquals(3, target.getHistory().size());
|
||||||
|
DataSourceCompactionConfigAuditEntry auditEntry = target.getHistory().get(0);
|
||||||
|
Assert.assertEquals(DATASOURCE, auditEntry.getCompactionConfig().getDataSource());
|
||||||
|
Assert.assertEquals(auditInfo, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME, auditEntry.getAuditTime());
|
||||||
|
auditEntry = target.getHistory().get(2);
|
||||||
|
Assert.assertEquals(configForDataSourceWithChange, auditEntry.getCompactionConfig());
|
||||||
|
Assert.assertEquals(auditInfo3, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME_3, auditEntry.getAuditTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddAndChangeCompactionConfigShouldAddBothToHistory()
|
||||||
|
{
|
||||||
|
target.add(compactionConfig, auditInfo, AUDIT_TIME);
|
||||||
|
Mockito.when(compactionConfig.getCompactionConfigs()).thenReturn(ImmutableList.of(configForDataSourceWithChange));
|
||||||
|
target.add(compactionConfig, auditInfo2, AUDIT_TIME_2);
|
||||||
|
Assert.assertEquals(2, target.getHistory().size());
|
||||||
|
DataSourceCompactionConfigAuditEntry auditEntry = target.getHistory().get(0);
|
||||||
|
Assert.assertEquals(DATASOURCE, auditEntry.getCompactionConfig().getDataSource());
|
||||||
|
Assert.assertEquals(auditInfo, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME, auditEntry.getAuditTime());
|
||||||
|
auditEntry = target.getHistory().get(1);
|
||||||
|
Assert.assertEquals(DATASOURCE, auditEntry.getCompactionConfig().getDataSource());
|
||||||
|
Assert.assertEquals(auditInfo2, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME_2, auditEntry.getAuditTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddAndChangeGlobalSettingsShouldAddTwice()
|
||||||
|
{
|
||||||
|
target.add(compactionConfig, auditInfo, AUDIT_TIME);
|
||||||
|
int newMaxTaskSlots = MAX_COMPACTION_TASK_SLOTS - 1;
|
||||||
|
Mockito.when(compactionConfig.getMaxCompactionTaskSlots()).thenReturn(newMaxTaskSlots);
|
||||||
|
target.add(compactionConfig, auditInfo2, AUDIT_TIME_2);
|
||||||
|
Assert.assertEquals(2, target.getHistory().size());
|
||||||
|
DataSourceCompactionConfigAuditEntry auditEntry = target.getHistory().get(0);
|
||||||
|
Assert.assertEquals(DATASOURCE, auditEntry.getCompactionConfig().getDataSource());
|
||||||
|
Assert.assertEquals(auditInfo, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME, auditEntry.getAuditTime());
|
||||||
|
Assert.assertEquals(MAX_COMPACTION_TASK_SLOTS, auditEntry.getGlobalConfig().getMaxCompactionTaskSlots());
|
||||||
|
auditEntry = target.getHistory().get(1);
|
||||||
|
Assert.assertEquals(DATASOURCE, auditEntry.getCompactionConfig().getDataSource());
|
||||||
|
Assert.assertEquals(auditInfo2, auditEntry.getAuditInfo());
|
||||||
|
Assert.assertEquals(AUDIT_TIME_2, auditEntry.getAuditTime());
|
||||||
|
Assert.assertEquals(newMaxTaskSlots, auditEntry.getGlobalConfig().getMaxCompactionTaskSlots());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddCompactionConfigDoesNotHaveDataSourceWithNoHistoryShouldNotAdd()
|
||||||
|
{
|
||||||
|
target = new DataSourceCompactionConfigHistory(DATASOURCE_NOT_EXISTS);
|
||||||
|
target.add(compactionConfig, auditInfo, AUDIT_TIME);
|
||||||
|
Assert.assertTrue(target.getHistory().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -22,8 +22,10 @@ package org.apache.druid.server.http;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import org.apache.commons.lang3.mutable.MutableInt;
|
import org.apache.commons.lang3.mutable.MutableInt;
|
||||||
|
import org.apache.druid.audit.AuditManager;
|
||||||
import org.apache.druid.common.config.ConfigManager;
|
import org.apache.druid.common.config.ConfigManager;
|
||||||
import org.apache.druid.common.config.JacksonConfigManager;
|
import org.apache.druid.common.config.JacksonConfigManager;
|
||||||
|
import org.apache.druid.jackson.DefaultObjectMapper;
|
||||||
import org.apache.druid.java.util.common.granularity.Granularities;
|
import org.apache.druid.java.util.common.granularity.Granularities;
|
||||||
import org.apache.druid.metadata.MetadataStorageConnector;
|
import org.apache.druid.metadata.MetadataStorageConnector;
|
||||||
import org.apache.druid.metadata.MetadataStorageTablesConfig;
|
import org.apache.druid.metadata.MetadataStorageTablesConfig;
|
||||||
|
@ -64,7 +66,10 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
);
|
);
|
||||||
private static final byte[] OLD_CONFIG_IN_BYTES = {1, 2, 3};
|
private static final byte[] OLD_CONFIG_IN_BYTES = {1, 2, 3};
|
||||||
|
|
||||||
private static final CoordinatorCompactionConfig ORIGINAL_CONFIG = CoordinatorCompactionConfig.from(ImmutableList.of(OLD_CONFIG));
|
private static final CoordinatorCompactionConfig ORIGINAL_CONFIG = CoordinatorCompactionConfig.from(ImmutableList.of(
|
||||||
|
OLD_CONFIG));
|
||||||
|
|
||||||
|
private static final String DATASOURCE_NOT_EXISTS = "notExists";
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private JacksonConfigManager mockJacksonConfigManager;
|
private JacksonConfigManager mockJacksonConfigManager;
|
||||||
|
@ -78,27 +83,40 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
@Mock
|
@Mock
|
||||||
private MetadataStorageTablesConfig mockConnectorConfig;
|
private MetadataStorageTablesConfig mockConnectorConfig;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AuditManager mockAuditManager;
|
||||||
|
|
||||||
private CoordinatorCompactionConfigsResource coordinatorCompactionConfigsResource;
|
private CoordinatorCompactionConfigsResource coordinatorCompactionConfigsResource;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setup()
|
public void setup()
|
||||||
{
|
{
|
||||||
Mockito.when(mockConnector.lookup(
|
Mockito.when(mockConnector.lookup(
|
||||||
ArgumentMatchers.anyString(),
|
ArgumentMatchers.anyString(),
|
||||||
ArgumentMatchers.eq("name"),
|
ArgumentMatchers.eq("name"),
|
||||||
ArgumentMatchers.eq("payload"),
|
ArgumentMatchers.eq("payload"),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY)
|
||||||
|
)
|
||||||
).thenReturn(OLD_CONFIG_IN_BYTES);
|
).thenReturn(OLD_CONFIG_IN_BYTES);
|
||||||
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
||||||
ArgumentMatchers.eq(OLD_CONFIG_IN_BYTES),
|
ArgumentMatchers.eq(OLD_CONFIG_IN_BYTES),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
|
||||||
|
)
|
||||||
).thenReturn(ORIGINAL_CONFIG);
|
).thenReturn(ORIGINAL_CONFIG);
|
||||||
Mockito.when(mockConnectorConfig.getConfigTable()).thenReturn("druid_config");
|
Mockito.when(mockConnectorConfig.getConfigTable()).thenReturn("druid_config");
|
||||||
|
Mockito.when(mockAuditManager.fetchAuditHistory(
|
||||||
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
||||||
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
||||||
|
ArgumentMatchers.any()
|
||||||
|
)
|
||||||
|
).thenReturn(ImmutableList.of());
|
||||||
coordinatorCompactionConfigsResource = new CoordinatorCompactionConfigsResource(
|
coordinatorCompactionConfigsResource = new CoordinatorCompactionConfigsResource(
|
||||||
mockJacksonConfigManager,
|
mockJacksonConfigManager,
|
||||||
mockConnector,
|
mockConnector,
|
||||||
mockConnectorConfig
|
mockConnectorConfig,
|
||||||
|
mockAuditManager,
|
||||||
|
new DefaultObjectMapper()
|
||||||
);
|
);
|
||||||
Mockito.when(mockHttpServletRequest.getRemoteAddr()).thenReturn("123");
|
Mockito.when(mockHttpServletRequest.getRemoteAddr()).thenReturn("123");
|
||||||
}
|
}
|
||||||
|
@ -107,12 +125,14 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
public void testSetCompactionTaskLimitWithExistingConfig()
|
public void testSetCompactionTaskLimitWithExistingConfig()
|
||||||
{
|
{
|
||||||
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||||
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(CoordinatorCompactionConfig.class);
|
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(
|
||||||
|
CoordinatorCompactionConfig.class);
|
||||||
Mockito.when(mockJacksonConfigManager.set(
|
Mockito.when(mockJacksonConfigManager.set(
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
||||||
oldConfigCaptor.capture(),
|
oldConfigCaptor.capture(),
|
||||||
newConfigCaptor.capture(),
|
newConfigCaptor.capture(),
|
||||||
ArgumentMatchers.any())
|
ArgumentMatchers.any()
|
||||||
|
)
|
||||||
).thenReturn(ConfigManager.SetResult.ok());
|
).thenReturn(ConfigManager.SetResult.ok());
|
||||||
|
|
||||||
double compactionTaskSlotRatio = 0.5;
|
double compactionTaskSlotRatio = 0.5;
|
||||||
|
@ -140,12 +160,14 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
public void testAddOrUpdateCompactionConfigWithExistingConfig()
|
public void testAddOrUpdateCompactionConfigWithExistingConfig()
|
||||||
{
|
{
|
||||||
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||||
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(CoordinatorCompactionConfig.class);
|
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(
|
||||||
|
CoordinatorCompactionConfig.class);
|
||||||
Mockito.when(mockJacksonConfigManager.set(
|
Mockito.when(mockJacksonConfigManager.set(
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
||||||
oldConfigCaptor.capture(),
|
oldConfigCaptor.capture(),
|
||||||
newConfigCaptor.capture(),
|
newConfigCaptor.capture(),
|
||||||
ArgumentMatchers.any())
|
ArgumentMatchers.any()
|
||||||
|
)
|
||||||
).thenReturn(ConfigManager.SetResult.ok());
|
).thenReturn(ConfigManager.SetResult.ok());
|
||||||
|
|
||||||
final DataSourceCompactionConfig newConfig = new DataSourceCompactionConfig(
|
final DataSourceCompactionConfig newConfig = new DataSourceCompactionConfig(
|
||||||
|
@ -183,12 +205,14 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
public void testDeleteCompactionConfigWithExistingConfig()
|
public void testDeleteCompactionConfigWithExistingConfig()
|
||||||
{
|
{
|
||||||
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||||
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(CoordinatorCompactionConfig.class);
|
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(
|
||||||
|
CoordinatorCompactionConfig.class);
|
||||||
Mockito.when(mockJacksonConfigManager.set(
|
Mockito.when(mockJacksonConfigManager.set(
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
||||||
oldConfigCaptor.capture(),
|
oldConfigCaptor.capture(),
|
||||||
newConfigCaptor.capture(),
|
newConfigCaptor.capture(),
|
||||||
ArgumentMatchers.any())
|
ArgumentMatchers.any()
|
||||||
|
)
|
||||||
).thenReturn(ConfigManager.SetResult.ok());
|
).thenReturn(ConfigManager.SetResult.ok());
|
||||||
final String datasourceName = "dataSource";
|
final String datasourceName = "dataSource";
|
||||||
final DataSourceCompactionConfig toDelete = new DataSourceCompactionConfig(
|
final DataSourceCompactionConfig toDelete = new DataSourceCompactionConfig(
|
||||||
|
@ -207,9 +231,10 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
);
|
);
|
||||||
final CoordinatorCompactionConfig originalConfig = CoordinatorCompactionConfig.from(ImmutableList.of(toDelete));
|
final CoordinatorCompactionConfig originalConfig = CoordinatorCompactionConfig.from(ImmutableList.of(toDelete));
|
||||||
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
||||||
ArgumentMatchers.eq(OLD_CONFIG_IN_BYTES),
|
ArgumentMatchers.eq(OLD_CONFIG_IN_BYTES),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
|
||||||
|
)
|
||||||
).thenReturn(originalConfig);
|
).thenReturn(originalConfig);
|
||||||
|
|
||||||
String author = "maytas";
|
String author = "maytas";
|
||||||
|
@ -255,23 +280,27 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
public void testSetCompactionTaskLimitWithoutExistingConfig()
|
public void testSetCompactionTaskLimitWithoutExistingConfig()
|
||||||
{
|
{
|
||||||
Mockito.when(mockConnector.lookup(
|
Mockito.when(mockConnector.lookup(
|
||||||
ArgumentMatchers.anyString(),
|
ArgumentMatchers.anyString(),
|
||||||
ArgumentMatchers.eq("name"),
|
ArgumentMatchers.eq("name"),
|
||||||
ArgumentMatchers.eq("payload"),
|
ArgumentMatchers.eq("payload"),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY)
|
||||||
|
)
|
||||||
).thenReturn(null);
|
).thenReturn(null);
|
||||||
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
||||||
ArgumentMatchers.eq(null),
|
ArgumentMatchers.eq(null),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
|
||||||
|
)
|
||||||
).thenReturn(CoordinatorCompactionConfig.empty());
|
).thenReturn(CoordinatorCompactionConfig.empty());
|
||||||
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||||
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(CoordinatorCompactionConfig.class);
|
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(
|
||||||
|
CoordinatorCompactionConfig.class);
|
||||||
Mockito.when(mockJacksonConfigManager.set(
|
Mockito.when(mockJacksonConfigManager.set(
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
||||||
oldConfigCaptor.capture(),
|
oldConfigCaptor.capture(),
|
||||||
newConfigCaptor.capture(),
|
newConfigCaptor.capture(),
|
||||||
ArgumentMatchers.any())
|
ArgumentMatchers.any()
|
||||||
|
)
|
||||||
).thenReturn(ConfigManager.SetResult.ok());
|
).thenReturn(ConfigManager.SetResult.ok());
|
||||||
|
|
||||||
double compactionTaskSlotRatio = 0.5;
|
double compactionTaskSlotRatio = 0.5;
|
||||||
|
@ -298,23 +327,27 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
public void testAddOrUpdateCompactionConfigWithoutExistingConfig()
|
public void testAddOrUpdateCompactionConfigWithoutExistingConfig()
|
||||||
{
|
{
|
||||||
Mockito.when(mockConnector.lookup(
|
Mockito.when(mockConnector.lookup(
|
||||||
ArgumentMatchers.anyString(),
|
ArgumentMatchers.anyString(),
|
||||||
ArgumentMatchers.eq("name"),
|
ArgumentMatchers.eq("name"),
|
||||||
ArgumentMatchers.eq("payload"),
|
ArgumentMatchers.eq("payload"),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY)
|
||||||
|
)
|
||||||
).thenReturn(null);
|
).thenReturn(null);
|
||||||
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
||||||
ArgumentMatchers.eq(null),
|
ArgumentMatchers.eq(null),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
|
||||||
|
)
|
||||||
).thenReturn(CoordinatorCompactionConfig.empty());
|
).thenReturn(CoordinatorCompactionConfig.empty());
|
||||||
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
final ArgumentCaptor<byte[]> oldConfigCaptor = ArgumentCaptor.forClass(byte[].class);
|
||||||
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(CoordinatorCompactionConfig.class);
|
final ArgumentCaptor<CoordinatorCompactionConfig> newConfigCaptor = ArgumentCaptor.forClass(
|
||||||
|
CoordinatorCompactionConfig.class);
|
||||||
Mockito.when(mockJacksonConfigManager.set(
|
Mockito.when(mockJacksonConfigManager.set(
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
|
||||||
oldConfigCaptor.capture(),
|
oldConfigCaptor.capture(),
|
||||||
newConfigCaptor.capture(),
|
newConfigCaptor.capture(),
|
||||||
ArgumentMatchers.any())
|
ArgumentMatchers.any()
|
||||||
|
)
|
||||||
).thenReturn(ConfigManager.SetResult.ok());
|
).thenReturn(ConfigManager.SetResult.ok());
|
||||||
|
|
||||||
final DataSourceCompactionConfig newConfig = new DataSourceCompactionConfig(
|
final DataSourceCompactionConfig newConfig = new DataSourceCompactionConfig(
|
||||||
|
@ -350,24 +383,37 @@ public class CoordinatorCompactionConfigsResourceTest
|
||||||
public void testDeleteCompactionConfigWithoutExistingConfigShouldFailAsDatasourceNotExist()
|
public void testDeleteCompactionConfigWithoutExistingConfigShouldFailAsDatasourceNotExist()
|
||||||
{
|
{
|
||||||
Mockito.when(mockConnector.lookup(
|
Mockito.when(mockConnector.lookup(
|
||||||
ArgumentMatchers.anyString(),
|
ArgumentMatchers.anyString(),
|
||||||
ArgumentMatchers.eq("name"),
|
ArgumentMatchers.eq("name"),
|
||||||
ArgumentMatchers.eq("payload"),
|
ArgumentMatchers.eq("payload"),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY)
|
||||||
|
)
|
||||||
).thenReturn(null);
|
).thenReturn(null);
|
||||||
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
Mockito.when(mockJacksonConfigManager.convertByteToConfig(
|
||||||
ArgumentMatchers.eq(null),
|
ArgumentMatchers.eq(null),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
|
||||||
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
|
ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
|
||||||
|
)
|
||||||
).thenReturn(CoordinatorCompactionConfig.empty());
|
).thenReturn(CoordinatorCompactionConfig.empty());
|
||||||
String author = "maytas";
|
String author = "maytas";
|
||||||
String comment = "hello";
|
String comment = "hello";
|
||||||
Response result = coordinatorCompactionConfigsResource.deleteCompactionConfig(
|
Response result = coordinatorCompactionConfigsResource.deleteCompactionConfig(
|
||||||
"notExist",
|
DATASOURCE_NOT_EXISTS,
|
||||||
author,
|
author,
|
||||||
comment,
|
comment,
|
||||||
mockHttpServletRequest
|
mockHttpServletRequest
|
||||||
);
|
);
|
||||||
Assert.assertEquals(Response.Status.NOT_FOUND.getStatusCode(), result.getStatus());
|
Assert.assertEquals(Response.Status.NOT_FOUND.getStatusCode(), result.getStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetCompactionConfigHistoryForUnknownDataSourceShouldReturnNotFound()
|
||||||
|
{
|
||||||
|
Response response = coordinatorCompactionConfigsResource.getCompactionConfigHistory(
|
||||||
|
DATASOURCE_NOT_EXISTS,
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
Assert.assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue