Skip to content

Commit

Permalink
fixed comments and added tests
Browse files Browse the repository at this point in the history
  • Loading branch information
sajid riaz committed Oct 24, 2023
1 parent dee3d47 commit 9d9ba02
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,20 +1,44 @@
/*
* Copyright 2023 Telefonaktiebolaget LM Ericsson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ericsson.bss.cassandra.ecchronos.application.config.repair;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.EnumSet;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class Priority
{
private static final String DEFAULT_PRIORITY_GRANULARITY_UNIT = "HOURS";

private static final Set<TimeUnit> ALLOWED_UNITS = EnumSet.of(TimeUnit.HOURS, TimeUnit.MINUTES, TimeUnit.SECONDS);
private static final String ALLOWED_VALUES_STR = String.join(", ", ALLOWED_UNITS.stream()
.map(TimeUnit::name)
.collect(Collectors.toList()));

private TimeUnit myGranularityUnit = TimeUnit.HOURS;

public Priority()
{
// Default constructor for jackson
}

public Priority(final TimeUnit granularityUnit)
@JsonCreator
public Priority(@JsonProperty("granularity_unit") final TimeUnit granularityUnit)
{
myGranularityUnit = granularityUnit;
}
Expand All @@ -27,6 +51,17 @@ public final TimeUnit getPriorityGranularityUnit()
@JsonProperty ("granularity_unit")
public final void setPriorityGranularityUnit(final TimeUnit granularityUnit)
{
Optional.ofNullable(granularityUnit)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"Granularity unit cannot be null. Allowed values are: %s.", ALLOWED_VALUES_STR)));

if (!ALLOWED_UNITS.contains(granularityUnit))
{
throw new IllegalArgumentException(String.format(
"Invalid granularity unit '%s'. Allowed values are: %s.",
granularityUnit.name(), ALLOWED_VALUES_STR));
}

myGranularityUnit = granularityUnit;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public final Priority getPriority()
{
return myPriority;
}

@JsonProperty("priority")
public final void setPriority(final Priority priority)
{
Expand Down
2 changes: 1 addition & 1 deletion application/src/main/resources/ecc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ repair:
unit: days
##
## The unit of time granularity for priority calculation, can be HOURS, MINUTES, or SECONDS.
## It determines how often the priority is recalculated.
## This unit is used in the calculation of priority.
## Default is HOURS for backward compatibility.
## Ensure to pause repair operations when changing the granularity to maintain consistency.
## HOURS # or MINUTES, SECONDS
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2023 Telefonaktiebolaget LM Ericsson
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.ericsson.bss.cassandra.ecchronos.application.config.repair;

import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

public class TestPriority
{
private Priority priority;

@Before
public void setUp() {
priority = new Priority();
}

@Test
public void testDefaultConstructorSetsHours()
{
assertThat(priority.getPriorityGranularityUnit()).isEqualTo(TimeUnit.HOURS);
}

@Test
public void testSetValidGranularityUnit()
{
priority.setPriorityGranularityUnit(TimeUnit.MINUTES);
assertThat(priority.getPriorityGranularityUnit()).isEqualTo(TimeUnit.MINUTES);
}

@Test(expected = IllegalArgumentException.class)
public void testSetInvalidGranularityUnit()
{
priority.setPriorityGranularityUnit(TimeUnit.DAYS);
}

@Test(expected = IllegalArgumentException.class)
public void testSetNullGranularityUnit()
{
priority.setPriorityGranularityUnit(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ private ScheduledRepairJob createScheduledRepairJob(final TableReference tableRe
.withPriority(ScheduledJob.Priority.LOW)
.withRunInterval(repairConfiguration.getRepairIntervalInMs(), TimeUnit.MILLISECONDS)
.withBackoff(repairConfiguration.getBackoffInMs(), TimeUnit.MILLISECONDS)
.withGranularityUnit(repairConfiguration.getPriorityGranularityUnit())
.withPriorityGranularity(repairConfiguration.getPriorityGranularityUnit())
.build();
ScheduledRepairJob job;
if (repairConfiguration.getRepairType().equals(RepairOptions.RepairType.INCREMENTAL))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public abstract class ScheduledJob implements Iterable<ScheduledTask>
private volatile long myNextRunTime = -1;
private volatile long myRunOffset = 0;
private final UUID myId;
private final TimeUnit myGranularityUnit;
private final TimeUnit myPriorityGranularity;

public ScheduledJob(final Configuration configuration)
{
Expand All @@ -48,7 +48,7 @@ public ScheduledJob(final Configuration configuration, final UUID id)
myRunIntervalInMs = configuration.runIntervalInMs;
myBackoffInMs = configuration.backoffInMs;
myLastSuccessfulRun = System.currentTimeMillis() - myRunIntervalInMs;
myGranularityUnit = configuration.granularityUnit;
myPriorityGranularity = configuration.priorityGranularity;
}

/**
Expand Down Expand Up @@ -173,7 +173,7 @@ public final int getRealPriority(final long lastSuccessfulRun)
return -1;
}

long granularityInMs = TimeUnit.MILLISECONDS.convert(1, myGranularityUnit);
long granularityInMs = myPriorityGranularity.toMillis(1);
long unitsPassed = diff / granularityInMs + 1;

// Overflow protection
Expand Down Expand Up @@ -223,7 +223,7 @@ public boolean equals(final Object o)
&& myRunOffset == that.myRunOffset
&& myPriority == that.myPriority
&& Objects.equals(myId, that.myId)
&& Objects.equals(myGranularityUnit, that.myGranularityUnit);
&& Objects.equals(myPriorityGranularity, that.myPriorityGranularity);
}

/**
Expand All @@ -233,7 +233,7 @@ public boolean equals(final Object o)
public int hashCode()
{
return Objects.hash(myPriority, myBackoffInMs, myRunIntervalInMs, myLastSuccessfulRun,
myNextRunTime, myRunOffset, myId, myGranularityUnit);
myNextRunTime, myRunOffset, myId, myPriorityGranularity);
}

/**
Expand Down Expand Up @@ -325,14 +325,14 @@ public static class Configuration
/**
* The unit of time granularity used for priority calculation in scheduling jobs.
*/
public final TimeUnit granularityUnit;
public final TimeUnit priorityGranularity;

Configuration(final ConfigurationBuilder builder)
{
priority = builder.priority;
runIntervalInMs = builder.runIntervalInMs;
backoffInMs = builder.backoffInMs;
granularityUnit = builder.granularityUnit;
priorityGranularity = builder.granularityUnit;
}
}

Expand All @@ -346,7 +346,7 @@ public static class ConfigurationBuilder
private long backoffInMs = TimeUnit.MINUTES.toMillis(DEFAULT_BACKOFF_IN_MINUTES);
private TimeUnit granularityUnit = TimeUnit.HOURS;

public final ConfigurationBuilder withGranularityUnit(final TimeUnit granularityTimeUnit)
public final ConfigurationBuilder withPriorityGranularity(final TimeUnit granularityTimeUnit)
{
this.granularityUnit = granularityTimeUnit;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ public void testGetRealPriorityWithMinuteGranularity()
ScheduledJob.Configuration configuration = new ScheduledJob.ConfigurationBuilder()
.withPriority(ScheduledJob.Priority.LOW)
.withRunInterval(RUN_INTERVAL_IN_DAYS, TimeUnit.DAYS)
.withGranularityUnit(TimeUnit.MINUTES)
.withPriorityGranularity(TimeUnit.MINUTES)
.build();

myRepairJob = new TableRepairJob.Builder()
Expand Down Expand Up @@ -709,6 +709,44 @@ public void testGetRealPriorityWithMinuteGranularity()
mockRepairGroup(lastRepaired);
assertThat(myRepairJob.getRealPriority()).isEqualTo(2);
}
@Test
public void testGetRealPriorityOverflow()
{
ScheduledJob.Configuration configuration = new ScheduledJob.ConfigurationBuilder()
.withPriority(ScheduledJob.Priority.HIGHEST)
.withPriorityGranularity(TimeUnit.MILLISECONDS)
.build();

myRepairJob = new TableRepairJob.Builder()
.withConfiguration(configuration)
.withTableReference(myTableReference)
.withJmxProxyFactory(myJmxProxyFactory)
.withRepairState(myRepairState)
.withTableRepairMetrics(myTableRepairMetrics)
.withRepairConfiguration(myRepairConfiguration)
.withRepairLockType(RepairLockType.VNODE)
.withTableStorageStates(myTableStorageStates)
.withRepairHistory(myRepairHistory)
.build();

long diffLargeEnoughForOverflow = (long) (Integer.MAX_VALUE / myRepairJob.getPriority().getValue())
* myRepairJob
.getRepairConfiguration()
.getPriorityGranularityUnit()
.toMillis(1) + 1;

long currentTimeMillis = System.currentTimeMillis();
long lastRepaired = currentTimeMillis - diffLargeEnoughForOverflow - myRepairJob
.getRepairConfiguration()
.getRepairIntervalInMs();

doReturn(lastRepaired).when(myRepairStateSnapshot).lastCompletedAt();
doReturn(true).when(myRepairStateSnapshot).canRepair();
mockRepairGroup(lastRepaired);

assertThat(myRepairJob.getRealPriority()).isEqualTo(Integer.MAX_VALUE);
}


@Test
public void testGetRealPriority()
Expand Down
8 changes: 8 additions & 0 deletions docs/UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ directly within the `ecc.yaml` file.

It’s important to note that while making these changes, the default behavior remains unchanged.

## Priority Calculation

The unit of time granularity for priority calculation, can be HOURS, MINUTES, or SECONDS.
This unit is used in the calculation of priority. Default is HOURS for backward compatibility.
Ensure to pause repair operations when changing the granularity to maintain consistency.
HOURS # or MINUTES, SECONDS. It’s important to note that while making these changes,
the default behavior remains unchanged.

# Upgrade to 4.x

## Metrics
Expand Down

0 comments on commit 9d9ba02

Please sign in to comment.