Skip to content

Commit c9e4a07

Browse files
authored
feat: stop embedding category, app and dataset models in deal model (#163)
1 parent 82293b5 commit c9e4a07

File tree

7 files changed

+174
-74
lines changed

7 files changed

+174
-74
lines changed

src/main/java/com/iexec/commons/poco/chain/ChainDeal.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,20 @@
2828
public class ChainDeal {
2929

3030
String chainDealId;
31+
/**
32+
* @deprecated not consistent with Smart Contracts
33+
*/
34+
@Deprecated(forRemoval = true)
3135
ChainApp chainApp;
36+
/**
37+
* @deprecated not consistent with Smart Contracts
38+
*/
39+
@Deprecated(forRemoval = true)
3240
ChainDataset chainDataset;
41+
/**
42+
* @deprecated not consistent with Smart Contracts
43+
*/
44+
@Deprecated(forRemoval = true)
3345
ChainCategory chainCategory;
3446
// deal_pt1
3547
String dappPointer;
@@ -59,9 +71,7 @@ public class ChainDeal {
5971
BigInteger schedulerRewardRatio;
6072

6173
public boolean containsDataset() {
62-
return getChainDataset() != null &&
63-
getChainDataset().getChainDatasetId() != null &&
64-
!getChainDataset().getChainDatasetId().equals(BytesUtils.EMPTY_ADDRESS);
74+
return dataPointer != null && !BytesUtils.EMPTY_ADDRESS.equals(dataPointer);
6575
}
6676

6777
public static ChainDeal parts2ChainDeal(String chainDealId, IexecHubContract.Deal deal, ChainCategory category) {
@@ -71,6 +81,10 @@ public static ChainDeal parts2ChainDeal(String chainDealId, IexecHubContract.Dea
7181
return create(chainDealId, deal, category, null, null);
7282
}
7383

84+
/**
85+
* @deprecated app, category and dataset will no more be embedded in deal to stick to on-chain models
86+
*/
87+
@Deprecated(forRemoval = true)
7488
public static ChainDeal parts2ChainDeal(String chainDealId, IexecHubContract.Deal deal, ChainApp app, ChainCategory category, ChainDataset dataset) {
7589
if (deal == null || app == null || category == null) {
7690
return ChainDeal.builder().build();

src/main/java/com/iexec/commons/poco/chain/IexecHubAbstractService.java

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,11 @@ public IexecHubContract getHubContract() {
162162
* @param maxRetry number of maximum retry
163163
* @return optional ChainDeal
164164
*/
165-
Optional<ChainDeal> repeatGetChainDeal(String chainDealId,
166-
long retryDelay,
167-
int maxRetry) {
165+
Optional<ChainDeal> repeatGetChainDeal(final String chainDealId,
166+
final long retryDelay,
167+
final int maxRetry) {
168168
return new Retryer<Optional<ChainDeal>>()
169-
.repeatCall(() -> getChainDealWithDetails(chainDealId),
169+
.repeatCall(() -> getChainDeal(chainDealId),
170170
Optional::isEmpty,
171171
retryDelay, maxRetry,
172172
String.format("getChainDeal(chainDealId) [chainDealId:%s]", chainDealId));
@@ -210,7 +210,9 @@ public Optional<ChainDeal> getChainDeal(String chainDealId) {
210210
*
211211
* @param chainDealId blockchain ID of the deal (e.g: 0x123..abc)
212212
* @return deal object
213+
* @deprecated on-chain app, category, dataset and deal are fetched separately (see repeatGetTaskDescriptionFromChain)
213214
*/
215+
@Deprecated(forRemoval = true)
214216
public Optional<ChainDeal> getChainDealWithDetails(String chainDealId) {
215217
final byte[] chainDealIdBytes = BytesUtils.stringToBytes(chainDealId);
216218
try {
@@ -258,9 +260,9 @@ private Optional<ChainDeal> validateChainDeal(final ChainDeal chainDeal) {
258260
* @param maxRetry number of maximum retry
259261
* @return optional ChainTask
260262
*/
261-
Optional<ChainTask> repeatGetChainTask(String chainTaskId,
262-
long retryDelay,
263-
int maxRetry) {
263+
Optional<ChainTask> repeatGetChainTask(final String chainTaskId,
264+
final long retryDelay,
265+
final int maxRetry) {
264266
return new Retryer<Optional<ChainTask>>()
265267
.repeatCall(() -> getChainTask(chainTaskId),
266268
Optional::isEmpty,
@@ -458,9 +460,18 @@ public TaskDescription getTaskDescription(String chainTaskId) {
458460
return taskDescriptions.get(chainTaskId);
459461
}
460462

461-
Optional<TaskDescription> repeatGetTaskDescriptionFromChain(String chainTaskId,
462-
long retryDelay,
463-
int maxRetry) {
463+
/**
464+
* Retrieves task, deal, category, app and dataset models on PoCo Smart Contracts to build a task description.
465+
*
466+
* @param chainTaskId ID of the task
467+
* @param retryDelay Interval between consecutive attempts while reading on the blockchain network
468+
* @param maxRetry Maximum number of attempts
469+
* @return The aggregate {@code TaskDescription}.
470+
* If the maximum number of attempts is reached without retrieving data, an empty result will be returned.
471+
*/
472+
Optional<TaskDescription> repeatGetTaskDescriptionFromChain(final String chainTaskId,
473+
final long retryDelay,
474+
final int maxRetry) {
464475
// If retryDelay is 0, a runtime exception will be thrown from failsafe library
465476
if (retryDelay == 0) {
466477
log.warn("retry delay cannot be 0 [chainTaskId:{}]", chainTaskId);
@@ -478,9 +489,31 @@ Optional<TaskDescription> repeatGetTaskDescriptionFromChain(String chainTaskId,
478489
return Optional.empty();
479490
}
480491

481-
final TaskDescription taskDescription = TaskDescription.toTaskDescription(chainDeal, chainTask);
492+
final ChainCategory chainCategory = new Retryer<Optional<ChainCategory>>()
493+
.repeatCall(() -> getChainCategory(chainDeal.getCategory().longValue()),
494+
Optional::isEmpty,
495+
retryDelay, maxRetry,
496+
String.format("getChainCategory() [category:%s]", chainDeal.getCategory().longValue()))
497+
.orElse(null);
498+
499+
final ChainApp chainApp = new Retryer<Optional<ChainApp>>()
500+
.repeatCall(() -> getChainApp(chainDeal.getDappPointer()),
501+
Optional::isEmpty,
502+
retryDelay, maxRetry,
503+
String.format("getChainApp() [address:%s]", chainDeal.getDappPointer()))
504+
.orElse(null);
505+
506+
final ChainDataset chainDataset = new Retryer<Optional<ChainDataset>>()
507+
.repeatCall(() -> getChainDataset(chainDeal.getDataPointer()),
508+
Optional::isEmpty,
509+
retryDelay, maxRetry,
510+
String.format("getChainDataset() [address:%s]", chainDeal.getDataPointer()))
511+
.orElse(null);
512+
513+
final TaskDescription taskDescription = TaskDescription.toTaskDescription(
514+
chainDeal, chainTask, chainCategory, chainApp, chainDataset);
482515
// taskDescription cannot be null here as chainTask and ChainDeal are not
483-
return taskDescription != null ? Optional.of(taskDescription) : Optional.empty();
516+
return Optional.ofNullable(taskDescription);
484517
}
485518

486519
/**

src/main/java/com/iexec/commons/poco/task/TaskDescription.java

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,7 @@
1717
package com.iexec.commons.poco.task;
1818

1919
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
20-
import com.iexec.commons.poco.chain.ChainDeal;
21-
import com.iexec.commons.poco.chain.ChainTask;
22-
import com.iexec.commons.poco.chain.DealParams;
20+
import com.iexec.commons.poco.chain.*;
2321
import com.iexec.commons.poco.dapp.DappType;
2422
import com.iexec.commons.poco.tee.TeeEnclaveConfiguration;
2523
import com.iexec.commons.poco.tee.TeeFramework;
@@ -42,6 +40,7 @@ public class TaskDescription {
4240
// assets
4341
DappType appType;
4442
String appUri;
43+
String appChecksum;
4544
TeeEnclaveConfiguration appEnclaveConfiguration;
4645
String datasetUri;
4746
String datasetChecksum;
@@ -181,24 +180,50 @@ public boolean requiresTdx() {
181180
* @param chainDeal On-chain deal from PoCo smart contracts
182181
* @param chainTask On-chain task from PoCo smart contracts
183182
* @return the created taskDescription
183+
* @deprecated app, category and dataset models will be removed from deal model
184184
*/
185+
@Deprecated(forRemoval = true)
185186
public static TaskDescription toTaskDescription(final ChainDeal chainDeal, final ChainTask chainTask) {
186187
if (chainDeal == null || chainTask == null) {
187188
return null;
188189
}
189-
String datasetUri = "";
190-
String datasetChecksum = "";
190+
return toTaskDescription(
191+
chainDeal, chainTask, chainDeal.getChainCategory(), chainDeal.getChainApp(), chainDeal.getChainDataset());
192+
}
193+
194+
/**
195+
* Create a {@link TaskDescription} from the provided chain deal. This method
196+
* if preferred to constructors or the builder method.
197+
*
198+
* @param chainDeal On-chain deal from PoCo smart contracts
199+
* @param chainTask On-chain task from PoCo smart contracts
200+
* @param chainCategory On-chain category from PoCo smart contracts
201+
* @param chainApp On-chain application from PoCo smart contracts
202+
* @param chainDataset On-chain dataset from PoCo smart contracts
203+
* @return the created taskDescription
204+
*/
205+
public static TaskDescription toTaskDescription(final ChainDeal chainDeal,
206+
final ChainTask chainTask,
207+
final ChainCategory chainCategory,
208+
final ChainApp chainApp,
209+
final ChainDataset chainDataset) {
210+
if (chainDeal == null || chainTask == null || chainCategory == null || chainApp == null || (chainDeal.containsDataset() && chainDataset == null)) {
211+
return null;
212+
}
213+
String datasetUri = null;
214+
String datasetChecksum = null;
191215
if (chainDeal.containsDataset()) {
192-
datasetUri = chainDeal.getChainDataset().getMultiaddr();
193-
datasetChecksum = chainDeal.getChainDataset().getChecksum();
216+
datasetUri = chainDataset.getMultiaddr();
217+
datasetChecksum = chainDataset.getChecksum();
194218
}
195219
final String tag = chainDeal.getTag();
196220
return TaskDescription.builder()
197221
.chainTaskId(chainTask.getChainTaskId())
198222
// assets
199223
.appType(DappType.DOCKER)
200-
.appUri(chainDeal.getChainApp().getMultiaddr())
201-
.appEnclaveConfiguration(chainDeal.getChainApp().getEnclaveConfiguration())
224+
.appUri(chainApp.getMultiaddr())
225+
.appChecksum(chainApp.getChecksum())
226+
.appEnclaveConfiguration(chainApp.getEnclaveConfiguration())
202227
.datasetUri(datasetUri)
203228
.datasetChecksum(datasetChecksum)
204229
// deal
@@ -227,7 +252,7 @@ public static TaskDescription toTaskDescription(final ChainDeal chainDeal, final
227252
// task
228253
.chainDealId(chainDeal.getChainDealId())
229254
.botIndex(chainTask.getIdx())
230-
.maxExecutionTime(chainDeal.getChainCategory().getMaxExecutionTime()) // https://github.com/iExecBlockchainComputing/PoCo/blob/v5/contracts/modules/delegates/IexecPoco2Delegate.sol#L111
255+
.maxExecutionTime(chainCategory.getMaxExecutionTime())
231256
.contributionDeadline(chainTask.getContributionDeadline())
232257
.finalDeadline(chainTask.getFinalDeadline())
233258
.build();

src/main/java/com/iexec/commons/poco/utils/Retryer.java

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2023 IEXEC BLOCKCHAIN TECH
2+
* Copyright 2020-2025 IEXEC BLOCKCHAIN TECH
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -35,41 +35,39 @@ public class Retryer<T> {
3535
* @param retryIfPredicate condition for retrying the supplying method call
3636
* @param retryDelay delay in ms between two tries
3737
* @param maxRetry number of maximum retries
38-
* @param logContext human readable content to be display
38+
* @param logContext human-readable content to be displayed
3939
* @return an object that the supplying method provides
4040
*/
41-
public T repeatCall(CheckedSupplier<T> supplier,
42-
Predicate<T> retryIfPredicate,
43-
long retryDelay,
44-
int maxRetry,
45-
String logContext) {
46-
String context = "\"" + logContext + "\"";
41+
public T repeatCall(final CheckedSupplier<T> supplier,
42+
final Predicate<T> retryIfPredicate,
43+
final long retryDelay,
44+
final int maxRetry,
45+
final String logContext) {
4746
if (retryDelay == 0) {
48-
log.error("Cannot repeat call {} without delay " +
49-
"[retryDelay:{}ms, maxRetry:{}]",
47+
log.error("Cannot repeat call {} without delay [retryDelay:{}ms, maxRetry:{}]",
5048
logContext, retryDelay, maxRetry);
5149
return null;
5250
}
53-
RetryPolicy<T> retryPolicy =
51+
final RetryPolicy<T> retryPolicy =
5452
new RetryPolicy<T>()
5553
.handleResultIf(retryIfPredicate) //retry if
5654
.withDelay(Duration.ofMillis(retryDelay))
5755
.withMaxRetries(maxRetry)
58-
.onRetry(e -> logWarnRetry(context,
59-
retryDelay, maxRetry, e.getAttemptCount()))
60-
.onRetriesExceeded(e -> logErrorOnMaxRetry(context,
61-
retryDelay, maxRetry));
56+
.onRetry(e -> logWarnRetry(
57+
logContext, retryDelay, maxRetry, e.getAttemptCount()))
58+
.onRetriesExceeded(e -> logErrorOnMaxRetry(
59+
logContext, retryDelay, maxRetry));
6260
return Failsafe.with(retryPolicy)
6361
.get(supplier);
6462
}
6563

66-
private void logWarnRetry(String context, long retryDelay, int maxRetry, int attempt) {
67-
log.warn("Failed to {}, about to retry [retryDelay:{}ms, maxRetry:{}" +
68-
", attempt:{}]", context, retryDelay, maxRetry, attempt);
64+
private void logWarnRetry(final String context, final long retryDelay, final int maxRetry, final int attempt) {
65+
log.warn("Failed to \"{}\", about to retry [retryDelay:{}ms, maxRetry:{}, attempt:{}]",
66+
context, retryDelay, maxRetry, attempt);
6967
}
7068

71-
private void logErrorOnMaxRetry(String context, long retryDelay, int maxRetry) {
72-
log.error("Failed to {} after max retry [retryDelay:{}ms, maxRetry:{}]",
69+
private void logErrorOnMaxRetry(final String context, final long retryDelay, final int maxRetry) {
70+
log.error("Failed to \"{}\" after max retry [retryDelay:{}ms, maxRetry:{}]",
7371
context, retryDelay, maxRetry);
7472
}
7573

src/test/java/com/iexec/commons/poco/chain/IexecHubAbstractServiceTest.java

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2020-2024 IEXEC BLOCKCHAIN TECH
2+
* Copyright 2020-2025 IEXEC BLOCKCHAIN TECH
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
1717
package com.iexec.commons.poco.chain;
1818

1919
import com.iexec.commons.poco.contract.generated.IexecHubContract;
20+
import com.iexec.commons.poco.dapp.DappType;
2021
import com.iexec.commons.poco.task.TaskDescription;
2122
import com.iexec.commons.poco.utils.BytesUtils;
2223
import org.junit.jupiter.api.Test;
@@ -133,7 +134,7 @@ void repeatGetChainTaskWithFailure() {
133134
void repeatGetChainDealWithSuccess() {
134135
ChainDeal chainDeal = getMockDeal();
135136

136-
when(iexecHubAbstractService.getChainDealWithDetails(CHAIN_DEAL_ID))
137+
when(iexecHubAbstractService.getChainDeal(CHAIN_DEAL_ID))
137138
.thenReturn(Optional.empty())
138139
.thenReturn(Optional.empty())
139140
.thenReturn(Optional.of(chainDeal));
@@ -145,12 +146,12 @@ void repeatGetChainDealWithSuccess() {
145146

146147
assertThat(foundDeal).isEqualTo(Optional.of(chainDeal));
147148
verify(iexecHubAbstractService, times(3))
148-
.getChainDealWithDetails(CHAIN_DEAL_ID);
149+
.getChainDeal(CHAIN_DEAL_ID);
149150
}
150151

151152
@Test
152153
void repeatGetChainDealWithFailure() {
153-
when(iexecHubAbstractService.getChainDealWithDetails(CHAIN_DEAL_ID))
154+
when(iexecHubAbstractService.getChainDeal(CHAIN_DEAL_ID))
154155
.thenReturn(Optional.empty());
155156
when(iexecHubAbstractService.repeatGetChainDeal(CHAIN_DEAL_ID, RETRY_DELAY, MAX_RETRY))
156157
.thenCallRealMethod();
@@ -160,26 +161,44 @@ void repeatGetChainDealWithFailure() {
160161

161162
assertThat(foundDeal).isEmpty();
162163
verify(iexecHubAbstractService, times(1 + MAX_RETRY))
163-
.getChainDealWithDetails(CHAIN_DEAL_ID);
164+
.getChainDeal(CHAIN_DEAL_ID);
164165
}
165166

166167
@Test
167168
void repeatGetTaskDescriptionFromChainWithSuccess() {
168-
ChainTask task = getMockTask();
169-
ChainDeal deal = getMockDeal();
169+
final ChainTask task = getMockTask();
170+
final ChainDeal deal = getMockDeal();
170171

171172
when(iexecHubAbstractService.repeatGetChainTask(CHAIN_TASK_ID, RETRY_DELAY, MAX_RETRY))
172173
.thenReturn(Optional.of(task));
173174
when(iexecHubAbstractService.repeatGetChainDeal(CHAIN_DEAL_ID, RETRY_DELAY, MAX_RETRY))
174175
.thenReturn(Optional.of(deal));
176+
when(iexecHubAbstractService.getChainCategory(anyLong()))
177+
.thenReturn(Optional.of(ChainCategory.builder().build()));
178+
when(iexecHubAbstractService.getChainApp(anyString()))
179+
.thenReturn(Optional.of(ChainApp.builder().build()));
180+
when(iexecHubAbstractService.getChainDataset(anyString()))
181+
.thenReturn(Optional.of(ChainDataset.builder().build()));
175182

176183
when(iexecHubAbstractService.repeatGetTaskDescriptionFromChain(CHAIN_TASK_ID, RETRY_DELAY, MAX_RETRY))
177184
.thenCallRealMethod();
178-
Optional<TaskDescription> taskDescription =
179-
iexecHubAbstractService.repeatGetTaskDescriptionFromChain(CHAIN_TASK_ID, RETRY_DELAY, MAX_RETRY);
185+
final TaskDescription taskDescription = iexecHubAbstractService
186+
.repeatGetTaskDescriptionFromChain(CHAIN_TASK_ID, RETRY_DELAY, MAX_RETRY)
187+
.orElse(null);
188+
189+
final TaskDescription expectedTaskDescription = TaskDescription.builder()
190+
.chainTaskId(CHAIN_TASK_ID)
191+
.appType(DappType.DOCKER)
192+
.appAddress(deal.getDappPointer())
193+
.datasetAddress(deal.getDataPointer())
194+
.category(deal.getCategory())
195+
.dealParams(DealParams.builder().build())
196+
.startTime(deal.getStartTime().intValue())
197+
.botFirstIndex(deal.getBotFirst().intValue())
198+
.botSize(deal.getBotSize().intValue())
199+
.build();
180200

181-
assertThat(taskDescription.map(TaskDescription::getChainTaskId)).hasValue(task.getChainTaskId());
182-
assertThat(taskDescription.map(TaskDescription::getBotSize)).hasValue(deal.getBotSize().intValue());
201+
assertThat(taskDescription).isEqualTo(expectedTaskDescription);
183202
}
184203

185204
@Test
@@ -276,11 +295,14 @@ private ChainTask getMockTask() {
276295
private ChainDeal getMockDeal() {
277296
return ChainDeal.builder()
278297
.chainApp(ChainApp.builder().multiaddr("").build())
279-
.params(DealParams.builder().build())
280298
.chainCategory(ChainCategory.builder().build())
299+
.dappPointer("0x1")
300+
.dataPointer(BytesUtils.EMPTY_ADDRESS)
301+
.category(BigInteger.ZERO)
302+
.params(DealParams.builder().build())
281303
.startTime(BigInteger.TEN)
282-
.botSize(BigInteger.ONE)
283304
.botFirst(BigInteger.ONE)
305+
.botSize(BigInteger.ONE)
284306
.build();
285307
}
286-
}
308+
}

0 commit comments

Comments
 (0)