This is an automated email from the ASF dual-hosted git repository.

suneet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 016c881795 Add API to return automatic compaction config history 
(#13699)
016c881795 is described below

commit 016c881795c03fc6a107f46243ffc71854088e53
Author: Suneet Saldanha <[email protected]>
AuthorDate: Mon Jan 23 13:23:45 2023 -0800

    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.
---
 docs/operations/api-reference.md                   |  12 ++
 .../DataSourceCompactionConfigAuditEntry.java      | 124 ++++++++++++++
 .../DataSourceCompactionConfigHistory.java         |  95 +++++++++++
 .../http/CoordinatorCompactionConfigsResource.java |  78 ++++++++-
 .../DataSourceCompactionConfigAuditEntryTest.java  |  99 +++++++++++
 .../DataSourceCompactionConfigHistoryTest.java     | 185 +++++++++++++++++++++
 .../CoordinatorCompactionConfigsResourceTest.java  | 164 +++++++++++-------
 7 files changed, 694 insertions(+), 63 deletions(-)

diff --git a/docs/operations/api-reference.md b/docs/operations/api-reference.md
index 687fa6e5c5..99d69d4246 100644
--- a/docs/operations/api-reference.md
+++ b/docs/operations/api-reference.md
@@ -470,6 +470,18 @@ Returns all automatic compaction configs.
 
 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}`
 
 Update the capacity for compaction tasks. `ratio` and `max` are used to limit 
the max number of compaction tasks.
diff --git 
a/server/src/main/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigAuditEntry.java
 
b/server/src/main/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigAuditEntry.java
new file mode 100644
index 0000000000..3424212446
--- /dev/null
+++ 
b/server/src/main/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigAuditEntry.java
@@ -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;
+    }
+  }
+}
diff --git 
a/server/src/main/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigHistory.java
 
b/server/src/main/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigHistory.java
new file mode 100644
index 0000000000..ceb4be0d8a
--- /dev/null
+++ 
b/server/src/main/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigHistory.java
@@ -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;
+  }
+}
diff --git 
a/server/src/main/java/org/apache/druid/server/http/CoordinatorCompactionConfigsResource.java
 
b/server/src/main/java/org/apache/druid/server/http/CoordinatorCompactionConfigsResource.java
index e791b6a49d..743654ee88 100644
--- 
a/server/src/main/java/org/apache/druid/server/http/CoordinatorCompactionConfigsResource.java
+++ 
b/server/src/main/java/org/apache/druid/server/http/CoordinatorCompactionConfigsResource.java
@@ -19,21 +19,28 @@
 
 package org.apache.druid.server.http;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.inject.Inject;
 import com.sun.jersey.spi.container.ResourceFilters;
+import org.apache.druid.audit.AuditEntry;
 import org.apache.druid.audit.AuditInfo;
 import org.apache.druid.audit.AuditManager;
 import org.apache.druid.common.config.ConfigManager.SetResult;
 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.metadata.MetadataStorageConnector;
 import org.apache.druid.metadata.MetadataStorageTablesConfig;
 import org.apache.druid.server.coordinator.CoordinatorCompactionConfig;
 import org.apache.druid.server.coordinator.DataSourceCompactionConfig;
+import org.apache.druid.server.coordinator.DataSourceCompactionConfigHistory;
 import org.apache.druid.server.http.security.ConfigResourceFilter;
+import org.joda.time.Interval;
 
 import javax.servlet.http.HttpServletRequest;
 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.MediaType;
 import javax.ws.rs.core.Response;
+
+import java.nio.charset.StandardCharsets;
+import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.concurrent.Callable;
@@ -67,17 +77,23 @@ public class CoordinatorCompactionConfigsResource
   private final JacksonConfigManager manager;
   private final MetadataStorageConnector connector;
   private final MetadataStorageTablesConfig connectorConfig;
+  private final AuditManager auditManager;
+  private final ObjectMapper jsonMapperOnlyNonNullValue;
 
   @Inject
   public CoordinatorCompactionConfigsResource(
       JacksonConfigManager manager,
       MetadataStorageConnector connector,
-      MetadataStorageTablesConfig connectorConfig
+      MetadataStorageTablesConfig connectorConfig,
+      AuditManager auditManager,
+      @JsonNonNull ObjectMapper jsonMapperOnlyNonNullValue
   )
   {
     this.manager = manager;
     this.connector = connector;
     this.connectorConfig = connectorConfig;
+    this.auditManager = auditManager;
+    this.jsonMapperOnlyNonNullValue = jsonMapperOnlyNonNullValue;
   }
 
   @GET
@@ -101,7 +117,10 @@ public class CoordinatorCompactionConfigsResource
   {
     Callable<SetResult> callable = () -> {
       final byte[] currentBytes = getCurrentConfigInByteFromDb();
-      final CoordinatorCompactionConfig current = 
CoordinatorCompactionConfig.convertByteToConfig(manager, currentBytes);
+      final CoordinatorCompactionConfig current = 
CoordinatorCompactionConfig.convertByteToConfig(
+          manager,
+          currentBytes
+      );
       final CoordinatorCompactionConfig newCompactionConfig = 
CoordinatorCompactionConfig.from(
           current,
           compactionTaskSlotRatio,
@@ -130,7 +149,10 @@ public class CoordinatorCompactionConfigsResource
   {
     Callable<SetResult> callable = () -> {
       final byte[] currentBytes = getCurrentConfigInByteFromDb();
-      final CoordinatorCompactionConfig current = 
CoordinatorCompactionConfig.convertByteToConfig(manager, currentBytes);
+      final CoordinatorCompactionConfig current = 
CoordinatorCompactionConfig.convertByteToConfig(
+          manager,
+          currentBytes
+      );
       final CoordinatorCompactionConfig newCompactionConfig;
       final Map<String, DataSourceCompactionConfig> newConfigs = current
           .getCompactionConfigs()
@@ -168,6 +190,51 @@ public class CoordinatorCompactionConfigsResource
     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
   @Path("/{dataSource}")
   @Produces(MediaType.APPLICATION_JSON)
@@ -180,7 +247,10 @@ public class CoordinatorCompactionConfigsResource
   {
     Callable<SetResult> callable = () -> {
       final byte[] currentBytes = getCurrentConfigInByteFromDb();
-      final CoordinatorCompactionConfig current = 
CoordinatorCompactionConfig.convertByteToConfig(manager, currentBytes);
+      final CoordinatorCompactionConfig current = 
CoordinatorCompactionConfig.convertByteToConfig(
+          manager,
+          currentBytes
+      );
       final Map<String, DataSourceCompactionConfig> configs = current
           .getCompactionConfigs()
           .stream()
diff --git 
a/server/src/test/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigAuditEntryTest.java
 
b/server/src/test/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigAuditEntryTest.java
new file mode 100644
index 0000000000..365c872165
--- /dev/null
+++ 
b/server/src/test/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigAuditEntryTest.java
@@ -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));
+  }
+}
diff --git 
a/server/src/test/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigHistoryTest.java
 
b/server/src/test/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigHistoryTest.java
new file mode 100644
index 0000000000..bf4badb44d
--- /dev/null
+++ 
b/server/src/test/java/org/apache/druid/server/coordinator/DataSourceCompactionConfigHistoryTest.java
@@ -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());
+  }
+
+}
diff --git 
a/server/src/test/java/org/apache/druid/server/http/CoordinatorCompactionConfigsResourceTest.java
 
b/server/src/test/java/org/apache/druid/server/http/CoordinatorCompactionConfigsResourceTest.java
index 6a38d5bcc6..5159d86594 100644
--- 
a/server/src/test/java/org/apache/druid/server/http/CoordinatorCompactionConfigsResourceTest.java
+++ 
b/server/src/test/java/org/apache/druid/server/http/CoordinatorCompactionConfigsResourceTest.java
@@ -22,8 +22,10 @@ package org.apache.druid.server.http;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 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.JacksonConfigManager;
+import org.apache.druid.jackson.DefaultObjectMapper;
 import org.apache.druid.java.util.common.granularity.Granularities;
 import org.apache.druid.metadata.MetadataStorageConnector;
 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 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
   private JacksonConfigManager mockJacksonConfigManager;
@@ -78,27 +83,40 @@ public class CoordinatorCompactionConfigsResourceTest
   @Mock
   private MetadataStorageTablesConfig mockConnectorConfig;
 
+  @Mock
+  private AuditManager mockAuditManager;
+
   private CoordinatorCompactionConfigsResource 
coordinatorCompactionConfigsResource;
 
   @Before
   public void setup()
   {
     Mockito.when(mockConnector.lookup(
-        ArgumentMatchers.anyString(),
-        ArgumentMatchers.eq("name"),
-        ArgumentMatchers.eq("payload"),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY))
+                     ArgumentMatchers.anyString(),
+                     ArgumentMatchers.eq("name"),
+                     ArgumentMatchers.eq("payload"),
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY)
+                 )
     ).thenReturn(OLD_CONFIG_IN_BYTES);
     Mockito.when(mockJacksonConfigManager.convertByteToConfig(
-        ArgumentMatchers.eq(OLD_CONFIG_IN_BYTES),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
+                     ArgumentMatchers.eq(OLD_CONFIG_IN_BYTES),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
+                 )
     ).thenReturn(ORIGINAL_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(
         mockJacksonConfigManager,
         mockConnector,
-        mockConnectorConfig
+        mockConnectorConfig,
+        mockAuditManager,
+        new DefaultObjectMapper()
     );
     Mockito.when(mockHttpServletRequest.getRemoteAddr()).thenReturn("123");
   }
@@ -107,12 +125,14 @@ public class CoordinatorCompactionConfigsResourceTest
   public void testSetCompactionTaskLimitWithExistingConfig()
   {
     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(
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
-        oldConfigCaptor.capture(),
-        newConfigCaptor.capture(),
-        ArgumentMatchers.any())
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
+                     oldConfigCaptor.capture(),
+                     newConfigCaptor.capture(),
+                     ArgumentMatchers.any()
+                 )
     ).thenReturn(ConfigManager.SetResult.ok());
 
     double compactionTaskSlotRatio = 0.5;
@@ -140,12 +160,14 @@ public class CoordinatorCompactionConfigsResourceTest
   public void testAddOrUpdateCompactionConfigWithExistingConfig()
   {
     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(
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
-        oldConfigCaptor.capture(),
-        newConfigCaptor.capture(),
-        ArgumentMatchers.any())
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
+                     oldConfigCaptor.capture(),
+                     newConfigCaptor.capture(),
+                     ArgumentMatchers.any()
+                 )
     ).thenReturn(ConfigManager.SetResult.ok());
 
     final DataSourceCompactionConfig newConfig = new 
DataSourceCompactionConfig(
@@ -183,12 +205,14 @@ public class CoordinatorCompactionConfigsResourceTest
   public void testDeleteCompactionConfigWithExistingConfig()
   {
     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(
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
-        oldConfigCaptor.capture(),
-        newConfigCaptor.capture(),
-        ArgumentMatchers.any())
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
+                     oldConfigCaptor.capture(),
+                     newConfigCaptor.capture(),
+                     ArgumentMatchers.any()
+                 )
     ).thenReturn(ConfigManager.SetResult.ok());
     final String datasourceName = "dataSource";
     final DataSourceCompactionConfig toDelete = new DataSourceCompactionConfig(
@@ -207,9 +231,10 @@ public class CoordinatorCompactionConfigsResourceTest
     );
     final CoordinatorCompactionConfig originalConfig = 
CoordinatorCompactionConfig.from(ImmutableList.of(toDelete));
     Mockito.when(mockJacksonConfigManager.convertByteToConfig(
-        ArgumentMatchers.eq(OLD_CONFIG_IN_BYTES),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
+                     ArgumentMatchers.eq(OLD_CONFIG_IN_BYTES),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
+                 )
     ).thenReturn(originalConfig);
 
     String author = "maytas";
@@ -255,23 +280,27 @@ public class CoordinatorCompactionConfigsResourceTest
   public void testSetCompactionTaskLimitWithoutExistingConfig()
   {
     Mockito.when(mockConnector.lookup(
-        ArgumentMatchers.anyString(),
-        ArgumentMatchers.eq("name"),
-        ArgumentMatchers.eq("payload"),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY))
+                     ArgumentMatchers.anyString(),
+                     ArgumentMatchers.eq("name"),
+                     ArgumentMatchers.eq("payload"),
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY)
+                 )
     ).thenReturn(null);
     Mockito.when(mockJacksonConfigManager.convertByteToConfig(
-        ArgumentMatchers.eq(null),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
+                     ArgumentMatchers.eq(null),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
+                 )
     ).thenReturn(CoordinatorCompactionConfig.empty());
     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(
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
-        oldConfigCaptor.capture(),
-        newConfigCaptor.capture(),
-        ArgumentMatchers.any())
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
+                     oldConfigCaptor.capture(),
+                     newConfigCaptor.capture(),
+                     ArgumentMatchers.any()
+                 )
     ).thenReturn(ConfigManager.SetResult.ok());
 
     double compactionTaskSlotRatio = 0.5;
@@ -298,23 +327,27 @@ public class CoordinatorCompactionConfigsResourceTest
   public void testAddOrUpdateCompactionConfigWithoutExistingConfig()
   {
     Mockito.when(mockConnector.lookup(
-        ArgumentMatchers.anyString(),
-        ArgumentMatchers.eq("name"),
-        ArgumentMatchers.eq("payload"),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY))
+                     ArgumentMatchers.anyString(),
+                     ArgumentMatchers.eq("name"),
+                     ArgumentMatchers.eq("payload"),
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY)
+                 )
     ).thenReturn(null);
     Mockito.when(mockJacksonConfigManager.convertByteToConfig(
-        ArgumentMatchers.eq(null),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
+                     ArgumentMatchers.eq(null),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
+                 )
     ).thenReturn(CoordinatorCompactionConfig.empty());
     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(
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
-        oldConfigCaptor.capture(),
-        newConfigCaptor.capture(),
-        ArgumentMatchers.any())
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY),
+                     oldConfigCaptor.capture(),
+                     newConfigCaptor.capture(),
+                     ArgumentMatchers.any()
+                 )
     ).thenReturn(ConfigManager.SetResult.ok());
 
     final DataSourceCompactionConfig newConfig = new 
DataSourceCompactionConfig(
@@ -350,24 +383,37 @@ public class CoordinatorCompactionConfigsResourceTest
   public void 
testDeleteCompactionConfigWithoutExistingConfigShouldFailAsDatasourceNotExist()
   {
     Mockito.when(mockConnector.lookup(
-        ArgumentMatchers.anyString(),
-        ArgumentMatchers.eq("name"),
-        ArgumentMatchers.eq("payload"),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY))
+                     ArgumentMatchers.anyString(),
+                     ArgumentMatchers.eq("name"),
+                     ArgumentMatchers.eq("payload"),
+                     
ArgumentMatchers.eq(CoordinatorCompactionConfig.CONFIG_KEY)
+                 )
     ).thenReturn(null);
     Mockito.when(mockJacksonConfigManager.convertByteToConfig(
-        ArgumentMatchers.eq(null),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
-        ArgumentMatchers.eq(CoordinatorCompactionConfig.empty()))
+                     ArgumentMatchers.eq(null),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.class),
+                     ArgumentMatchers.eq(CoordinatorCompactionConfig.empty())
+                 )
     ).thenReturn(CoordinatorCompactionConfig.empty());
     String author = "maytas";
     String comment = "hello";
     Response result = 
coordinatorCompactionConfigsResource.deleteCompactionConfig(
-        "notExist",
+        DATASOURCE_NOT_EXISTS,
         author,
         comment,
         mockHttpServletRequest
     );
     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());
+  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to