Skip to content

Commit

Permalink
fix: ContractDefinition.Validity breaks catalog requests if number is…
Browse files Browse the repository at this point in the history
… too big (#2399)

* Catch Arithmetic exception and warn about it

* Separate method to get contract end time from createContractOffer method

* Add Unit test for maximum ContractEndTime

* Change name of shouldReturnMaximumContractEndtime UnitTest

* Add Max constraint to 10 years for validity

* Add Max constraint to 10 years for validity in open-api

* Correct zone in ContractEndtime

* Remove unused import

* Change name of method for calculating contractEnd

* Remove max Constraint for validity.

* Remove max Constraint for validity.
  • Loading branch information
diegogomez-zf authored Jan 13, 2023
1 parent c88eadc commit bcf7c87
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ private void registerServices(ServiceExtensionContext context) {
var definitionService = new ContractDefinitionServiceImpl(monitor, contractDefinitionStore, policyEngine, policyStore);
context.registerService(ContractDefinitionService.class, definitionService);

var contractOfferResolver = new ContractOfferResolverImpl(agentService, definitionService, assetIndex, policyStore, clock);
var contractOfferResolver = new ContractOfferResolverImpl(agentService, definitionService, assetIndex, policyStore, clock, monitor);
context.registerService(ContractOfferResolver.class, contractOfferResolver);

var policyEquality = new PolicyEquality(context.getTypeManager());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@
import org.eclipse.edc.policy.model.Policy;
import org.eclipse.edc.spi.agent.ParticipantAgentService;
import org.eclipse.edc.spi.asset.AssetIndex;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.types.domain.asset.Asset;
import org.jetbrains.annotations.NotNull;

import java.time.Clock;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -51,13 +53,15 @@ public class ContractOfferResolverImpl implements ContractOfferResolver {
private final AssetIndex assetIndex;
private final PolicyDefinitionStore policyStore;
private final Clock clock;
private final Monitor monitor;

public ContractOfferResolverImpl(ParticipantAgentService agentService, ContractDefinitionService definitionService, AssetIndex assetIndex, PolicyDefinitionStore policyStore, Clock clock) {
public ContractOfferResolverImpl(ParticipantAgentService agentService, ContractDefinitionService definitionService, AssetIndex assetIndex, PolicyDefinitionStore policyStore, Clock clock, Monitor monitor) {
this.agentService = agentService;
this.definitionService = definitionService;
this.assetIndex = assetIndex;
this.policyStore = policyStore;
this.clock = clock;
this.monitor = monitor;
}

@Override
Expand Down Expand Up @@ -117,11 +121,28 @@ private Stream<ContractOffer.Builder> createContractOffers(ContractDefinition de

@NotNull
private ContractOffer.Builder createContractOffer(ContractDefinition definition, Policy policy, Asset asset) {

var contractEndTime = calculateContractEnd(definition);

return ContractOffer.Builder.newInstance()
.id(ContractId.createContractId(definition.getId()))
.policy(policy.withTarget(asset.getId()))
.asset(asset)
.contractStart(ZonedDateTime.now())
.contractEnd(ZonedDateTime.ofInstant(clock.instant().plusSeconds(definition.getValidity()), clock.getZone()));
.contractEnd(contractEndTime);
}

@NotNull
private ZonedDateTime calculateContractEnd(ContractDefinition definition) {

var contractEndTime = Instant.ofEpochMilli(Long.MAX_VALUE).atZone(clock.getZone());
try {
contractEndTime = ZonedDateTime.ofInstant(clock.instant().plusSeconds(definition.getValidity()), clock.getZone());
} catch (ArithmeticException exception) {
monitor.warning("The added ContractEnd value is bigger than the maximum number allowed by a long value. " +
"Changing contractEndTime to Maximum value possible in the ContractOffer");
}
return contractEndTime;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.eclipse.edc.spi.asset.AssetSelectorExpression;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.message.Range;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.query.Criterion;
import org.eclipse.edc.spi.types.domain.DataAddress;
import org.eclipse.edc.spi.types.domain.asset.Asset;
Expand Down Expand Up @@ -66,13 +67,14 @@ class ContractOfferResolverImplIntegrationTest {
private final ContractDefinitionService contractDefinitionService = mock(ContractDefinitionService.class);
private final ParticipantAgentService agentService = mock(ParticipantAgentService.class);
private final PolicyDefinitionStore policyStore = mock(PolicyDefinitionStore.class);
private final Monitor monitor = mock(Monitor.class);
private AssetIndex assetIndex;
private ContractOfferResolver contractOfferResolver;

@BeforeEach
void setUp() {
assetIndex = new InMemoryAssetIndex();
contractOfferResolver = new ContractOfferResolverImpl(agentService, contractDefinitionService, assetIndex, policyStore, clock);
contractOfferResolver = new ContractOfferResolverImpl(agentService, contractDefinitionService, assetIndex, policyStore, clock, monitor);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.eclipse.edc.spi.asset.AssetSelectorExpression;
import org.eclipse.edc.spi.iam.ClaimToken;
import org.eclipse.edc.spi.message.Range;
import org.eclipse.edc.spi.monitor.Monitor;
import org.eclipse.edc.spi.query.Criterion;
import org.eclipse.edc.spi.query.QuerySpec;
import org.eclipse.edc.spi.types.domain.asset.Asset;
Expand All @@ -38,6 +39,7 @@
import java.net.URI;
import java.time.Clock;
import java.time.Instant;
import java.time.ZoneOffset;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
Expand All @@ -62,19 +64,20 @@

class ContractOfferResolverImplTest {

private static final Range DEFAULT_RANGE = new Range(0, 10);
private final Instant now = Instant.now();
private final Clock clock = Clock.fixed(now, UTC);
private static final Range DEFAULT_RANGE = new Range(0, 10);
private final ContractDefinitionService contractDefinitionService = mock(ContractDefinitionService.class);
private final AssetIndex assetIndex = mock(AssetIndex.class);
private final ParticipantAgentService agentService = mock(ParticipantAgentService.class);
private final PolicyDefinitionStore policyStore = mock(PolicyDefinitionStore.class);
private final Monitor monitor = mock(Monitor.class);

private ContractOfferResolver contractOfferResolver;

@BeforeEach
void setUp() {
contractOfferResolver = new ContractOfferResolverImpl(agentService, contractDefinitionService, assetIndex, policyStore, clock);
contractOfferResolver = new ContractOfferResolverImpl(agentService, contractDefinitionService, assetIndex, policyStore, clock, monitor);
}

@Test
Expand Down Expand Up @@ -280,6 +283,31 @@ void shouldGetContractOffersWithAssetFilteringApplied() {
verify(assetIndex).queryAssets(expectedQuerySpec);
}

@Test
void shouldReturnMaximumContractEndtime_whenItExceedsMaximimLongValue() {

var contractDefinition = getContractDefBuilder("ContractForever").validity(Long.MAX_VALUE).build();

when(agentService.createFor(isA(ClaimToken.class))).thenReturn(new ParticipantAgent(emptyMap(), emptyMap()));
when(contractDefinitionService.definitionsFor(isA(ParticipantAgent.class))).thenReturn(Stream.of(contractDefinition));
var assetStream = Stream.of(Asset.Builder.newInstance().build());
when(assetIndex.countAssets(anyList())).thenReturn(1L);
when(assetIndex.queryAssets(isA(QuerySpec.class))).thenReturn(assetStream);
when(policyStore.findById(any())).thenReturn(PolicyDefinition.Builder.newInstance().policy(Policy.Builder.newInstance().build()).build());
var query = ContractOfferQuery.builder()
.claimToken(ClaimToken.Builder.newInstance().build())
.provider(URI.create("urn:connector:edc-provider"))
.consumer(URI.create("urn:connector:edc-consumer"))
.build();

var offers = contractOfferResolver.queryContractOffers(query);

assertThat(offers)
.hasSize(1)
.allSatisfy(contractOffer -> assertThat(contractOffer.getContractEnd()).isEqualTo(Instant.ofEpochMilli(Long.MAX_VALUE).atZone(ZoneOffset.UTC)));

}

private ContractOfferQuery getQuery(int from, int to) {
return ContractOfferQuery.builder()
.range(new Range(from, to))
Expand Down

0 comments on commit bcf7c87

Please sign in to comment.