Skip to content

Commit 7c93c40

Browse files
authored
Merge pull request #668 from iExecBlockchainComputing/release/8.4.0
Release/8.4.0
2 parents 6400aa8 + 4846bf9 commit 7c93c40

24 files changed

+852
-860
lines changed

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [[8.4.0]](https://github.com/iExecBlockchainComputing/iexec-core/releases/tag/v8.4.0) 2024-02-29
6+
7+
### New Features
8+
9+
- Use `MongoTemplate` to enable document update without full rewrite. (#661)
10+
11+
### Bug Fixes
12+
13+
- Filter out `CONTRIBUTE_AND_FINALIZE` tasks when detecting missed `REVEALED` status update. (#658)
14+
- Fetch `results` on-chain when updating a replicate status in `CONTRIBUTE_AND_FINALIZE` workflow. (#659 #660)
15+
- Properly catch all runtime exceptions when an enclave challenge generation fails. (#663)
16+
17+
### Quality
18+
19+
- Use `@DataMongoTest` and `@Testcontainers` annotations in replicates, compute logs and tasks tests. (#662 #664 #665)
20+
21+
### Dependency Upgrades
22+
23+
- Upgrade to `iexec-common` 8.4.0. (#666)
24+
- Upgrade to `iexec-blockchain-adapter` 8.4.0. (#667)
25+
- Upgrade to `iexec-result-proxy` 8.4.0. (#667)
26+
- Upgrade to `iexec-sms` 8.5.0. (#667)
27+
528
## [[8.3.0]](https://github.com/iExecBlockchainComputing/iexec-core/releases/tag/v8.3.0) 2024-01-11
629

730
### New Features

build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ tasks.named("bootJar") {
130130

131131
test {
132132
useJUnitPlatform()
133+
systemProperty "mongo.image", "mongo:4.4.28-focal"
133134
}
134135

135136
tasks.register('itest') {

gradle.properties

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
version=8.3.0
2-
iexecCommonVersion=8.3.1
1+
version=8.4.0
2+
iexecCommonVersion=8.4.0
33
iexecCommonsPocoVersion=3.2.0
4-
iexecBlockchainAdapterVersion=8.3.0
5-
iexecResultVersion=8.3.0
6-
iexecSmsVersion=8.4.0
4+
iexecBlockchainAdapterVersion=8.4.0
5+
iexecResultVersion=8.4.0
6+
iexecSmsVersion=8.5.0
77

88
nexusUser
99
nexusPassword

src/main/java/com/iexec/core/detector/replicate/ContributionAndFinalizationUnnotifiedDetector.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.iexec.commons.poco.chain.ChainContributionStatus;
2121
import com.iexec.core.chain.IexecHubService;
2222
import com.iexec.core.configuration.CronConfiguration;
23+
import com.iexec.core.replicate.Replicate;
2324
import com.iexec.core.replicate.ReplicatesService;
2425
import com.iexec.core.task.TaskService;
2526
import com.iexec.core.task.TaskStatus;
@@ -51,4 +52,14 @@ public ContributionAndFinalizationUnnotifiedDetector(TaskService taskService,
5152
public void detectOnChainChanges() {
5253
super.detectOnChainChanges();
5354
}
55+
56+
@Override
57+
protected final boolean checkDetectionIsValid(Replicate replicate) {
58+
return iexecHubService.getTaskDescription(replicate.getChainTaskId()).isEligibleToContributeAndFinalize();
59+
}
60+
61+
@Override
62+
protected boolean detectStatusReachedOnChain(Replicate replicate) {
63+
return iexecHubService.isRevealed(replicate.getChainTaskId(), replicate.getWalletAddress());
64+
}
5465
}

src/main/java/com/iexec/core/detector/replicate/ContributionUnnotifiedDetector.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.iexec.commons.poco.chain.ChainContributionStatus;
2121
import com.iexec.core.chain.IexecHubService;
2222
import com.iexec.core.configuration.CronConfiguration;
23+
import com.iexec.core.replicate.Replicate;
2324
import com.iexec.core.replicate.ReplicatesService;
2425
import com.iexec.core.task.TaskService;
2526
import com.iexec.core.task.TaskStatus;
@@ -51,4 +52,14 @@ public ContributionUnnotifiedDetector(TaskService taskService,
5152
public void detectOnChainChanges() {
5253
super.detectOnChainChanges();
5354
}
55+
56+
@Override
57+
protected final boolean checkDetectionIsValid(Replicate replicate) {
58+
return !iexecHubService.getTaskDescription(replicate.getChainTaskId()).isEligibleToContributeAndFinalize();
59+
}
60+
61+
@Override
62+
protected boolean detectStatusReachedOnChain(Replicate replicate) {
63+
return iexecHubService.isContributed(replicate.getChainTaskId(), replicate.getWalletAddress());
64+
}
5465
}

src/main/java/com/iexec/core/detector/replicate/RevealUnnotifiedDetector.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.iexec.commons.poco.chain.ChainContributionStatus;
2121
import com.iexec.core.chain.IexecHubService;
2222
import com.iexec.core.configuration.CronConfiguration;
23+
import com.iexec.core.replicate.Replicate;
2324
import com.iexec.core.replicate.ReplicatesService;
2425
import com.iexec.core.task.TaskService;
2526
import com.iexec.core.task.TaskStatus;
@@ -51,4 +52,14 @@ public RevealUnnotifiedDetector(TaskService taskService,
5152
public void detectOnChainChanges() {
5253
super.detectOnChainChanges();
5354
}
55+
56+
@Override
57+
protected final boolean checkDetectionIsValid(Replicate replicate) {
58+
return !iexecHubService.getTaskDescription(replicate.getChainTaskId()).isEligibleToContributeAndFinalize();
59+
}
60+
61+
@Override
62+
protected boolean detectStatusReachedOnChain(Replicate replicate) {
63+
return iexecHubService.isRevealed(replicate.getChainTaskId(), replicate.getWalletAddress());
64+
}
5465
}

src/main/java/com/iexec/core/detector/replicate/UnnotifiedAbstractDetector.java

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,15 @@
3030

3131
import java.util.List;
3232

33-
import static com.iexec.common.replicate.ReplicateStatus.*;
33+
import static com.iexec.common.replicate.ReplicateStatus.getMissingStatuses;
3434

3535
@Slf4j
3636
public abstract class UnnotifiedAbstractDetector {
3737
private static final int LESS_OFTEN_DETECTOR_FREQUENCY = 10;
3838

3939
private final TaskService taskService;
4040
private final ReplicatesService replicatesService;
41-
private final IexecHubService iexecHubService;
41+
protected final IexecHubService iexecHubService;
4242

4343
private final List<TaskStatus> detectWhenOffChainTaskStatuses;
4444
private final ReplicateStatus offchainOngoing;
@@ -129,32 +129,15 @@ public void detectOnchainDone() {
129129
* @param replicate The replicate to check
130130
* @return {@literal true} if the replicate is eligible, {@literal false} otherwise
131131
*/
132-
private boolean checkDetectionIsValid(Replicate replicate) {
133-
final boolean isEligibleToContributeAndFinalize = iexecHubService.getTaskDescription(replicate.getChainTaskId())
134-
.isEligibleToContributeAndFinalize();
135-
return offchainDone == REVEALED
136-
|| (!isEligibleToContributeAndFinalize && offchainDone == CONTRIBUTED)
137-
|| (isEligibleToContributeAndFinalize && offchainDone == CONTRIBUTE_AND_FINALIZE_DONE);
138-
}
132+
protected abstract boolean checkDetectionIsValid(Replicate replicate);
139133

140134
/**
141135
* Checks if {@code onchainDone} status has been reached on blockchain network.
142136
*
143137
* @param replicate Replicate whose on-chain status will be checked
144138
* @return {@literal true} if given status has been found on-chain, {@literal false} otherwise.
145139
*/
146-
private boolean detectStatusReachedOnChain(Replicate replicate) {
147-
final String chainTaskId = replicate.getChainTaskId();
148-
final String walletAddress = replicate.getWalletAddress();
149-
switch (onchainDone) {
150-
case CONTRIBUTED:
151-
return iexecHubService.isContributed(chainTaskId, walletAddress);
152-
case REVEALED:
153-
return iexecHubService.isRevealed(chainTaskId, walletAddress);
154-
default:
155-
return false;
156-
}
157-
}
140+
protected abstract boolean detectStatusReachedOnChain(Replicate replicate);
158141

159142
/*
160143
* This method should stay private. We need to ensure that

src/main/java/com/iexec/core/replicate/ReplicatesService.java

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.iexec.common.replicate.*;
2020
import com.iexec.common.utils.ContextualLockRunner;
2121
import com.iexec.commons.poco.chain.ChainContribution;
22+
import com.iexec.commons.poco.chain.ChainTask;
2223
import com.iexec.commons.poco.notification.TaskNotificationType;
2324
import com.iexec.commons.poco.task.TaskDescription;
2425
import com.iexec.core.chain.IexecHubService;
@@ -30,10 +31,15 @@
3031
import lombok.extern.slf4j.Slf4j;
3132
import org.springframework.context.ApplicationEventPublisher;
3233
import org.springframework.dao.OptimisticLockingFailureException;
34+
import org.springframework.data.mongodb.core.MongoTemplate;
35+
import org.springframework.data.mongodb.core.query.Criteria;
36+
import org.springframework.data.mongodb.core.query.Query;
37+
import org.springframework.data.mongodb.core.query.Update;
3338
import org.springframework.retry.annotation.Recover;
3439
import org.springframework.retry.annotation.Retryable;
3540
import org.springframework.stereotype.Service;
3641
import org.springframework.util.StringUtils;
42+
import org.web3j.utils.Numeric;
3743

3844
import java.util.Collections;
3945
import java.util.List;
@@ -47,6 +53,7 @@
4753
@Service
4854
public class ReplicatesService {
4955

56+
private final MongoTemplate mongoTemplate;
5057
private final ReplicatesRepository replicatesRepository;
5158
private final IexecHubService iexecHubService;
5259
private final ApplicationEventPublisher applicationEventPublisher;
@@ -57,12 +64,14 @@ public class ReplicatesService {
5764
private final ContextualLockRunner<String> replicatesUpdateLockRunner =
5865
new ContextualLockRunner<>(10, TimeUnit.MINUTES);
5966

60-
public ReplicatesService(ReplicatesRepository replicatesRepository,
67+
public ReplicatesService(MongoTemplate mongoTemplate,
68+
ReplicatesRepository replicatesRepository,
6169
IexecHubService iexecHubService,
6270
ApplicationEventPublisher applicationEventPublisher,
6371
Web3jService web3jService,
6472
ResultService resultService,
6573
TaskLogsService taskLogsService) {
74+
this.mongoTemplate = mongoTemplate;
6675
this.replicatesRepository = replicatesRepository;
6776
this.iexecHubService = iexecHubService;
6877
this.applicationEventPublisher = applicationEventPublisher;
@@ -101,26 +110,16 @@ public Optional<ReplicatesList> getReplicatesList(String chainTaskId) {
101110
}
102111

103112
public List<Replicate> getReplicates(String chainTaskId) {
104-
Optional<ReplicatesList> optionalList = getReplicatesList(chainTaskId);
105-
if (optionalList.isEmpty()) {
106-
return Collections.emptyList();
107-
}
108-
return optionalList.get().getReplicates();
113+
return getReplicatesList(chainTaskId)
114+
.map(ReplicatesList::getReplicates)
115+
.orElse(Collections.emptyList());
109116
}
110117

111118
public Optional<Replicate> getReplicate(String chainTaskId, String walletAddress) {
112-
Optional<ReplicatesList> optional = getReplicatesList(chainTaskId);
113-
if (optional.isEmpty()) {
114-
return Optional.empty();
115-
}
116-
117-
for (Replicate replicate : optional.get().getReplicates()) {
118-
if (replicate.getWalletAddress().equals(walletAddress)) {
119-
return Optional.of(replicate);
120-
}
121-
}
122-
123-
return Optional.empty();
119+
return getReplicates(chainTaskId)
120+
.stream()
121+
.filter(replicate -> replicate.getWalletAddress().equals(walletAddress))
122+
.findFirst();
124123
}
125124

126125
public int getNbReplicatesWithCurrentStatus(String chainTaskId, ReplicateStatus... listStatus) {
@@ -250,6 +249,15 @@ public UpdateReplicateStatusArgs computeUpdateReplicateStatusArgs(String chainTa
250249
}
251250
}
252251

252+
if (statusUpdate.getStatus() == CONTRIBUTE_AND_FINALIZE_DONE) {
253+
// TODO read chainCallbackData if CONTRIBUTE_AND_FINALIZE becomes applicable some day in the future and if latest ABI is used
254+
resultLink = iexecHubService.getChainTask(chainTaskId)
255+
.map(ChainTask::getResults)
256+
.map(Numeric::hexStringToByteArray)
257+
.map(String::new)
258+
.orElse(null);
259+
}
260+
253261
return UpdateReplicateStatusArgs.builder()
254262
.workerWeight(workerWeight)
255263
.chainContribution(chainContribution)
@@ -402,31 +410,34 @@ Either<ReplicateStatusUpdateError, TaskNotificationType> updateReplicateStatusWi
402410
log.info("Replicate update request [status:{}, chainTaskId:{}, walletAddress:{}, details:{}]",
403411
statusUpdate.getStatus(), chainTaskId, walletAddress, statusUpdate.getDetailsWithoutLogs());
404412

405-
final Optional<ReplicatesList> oReplicatesList = getReplicatesList(chainTaskId);
406-
final Optional<Replicate> oReplicate = oReplicatesList
407-
.flatMap(replicatesList -> replicatesList.getReplicateOfWorker(walletAddress));
408-
if (oReplicatesList.isEmpty() || oReplicate.isEmpty()) {
413+
final Replicate replicate = getReplicatesList(chainTaskId)
414+
.flatMap(replicatesList -> replicatesList.getReplicateOfWorker(walletAddress))
415+
.orElse(null);
416+
if (replicate == null) {
409417
log.error("Cannot update replicate, could not get replicate [chainTaskId:{}, UpdateRequest:{}]",
410418
chainTaskId, statusUpdate);
411419
return Either.left(ReplicateStatusUpdateError.UNKNOWN_REPLICATE);
412420
}
413-
final ReplicatesList replicatesList = oReplicatesList.get();
414-
final Replicate replicate = oReplicate.get();
415421
final ReplicateStatus newStatus = statusUpdate.getStatus();
416422

417423
final ReplicateStatusUpdateError error = canUpdateReplicateStatus(replicate, statusUpdate, updateReplicateStatusArgs);
418424
if (ReplicateStatusUpdateError.NO_ERROR != error) {
419425
return Either.left(error);
420426
}
421427

428+
Update update = new Update();
422429
if (newStatus == CONTRIBUTED || newStatus == CONTRIBUTE_AND_FINALIZE_DONE) {
423430
replicate.setContributionHash(updateReplicateStatusArgs.getChainContribution().getResultHash());
424431
replicate.setWorkerWeight(updateReplicateStatusArgs.getWorkerWeight());
432+
update.set("replicates.$.contributionHash", updateReplicateStatusArgs.getChainContribution().getResultHash());
433+
update.set("replicates.$.workerWeight", updateReplicateStatusArgs.getWorkerWeight());
425434
}
426435

427436
if (newStatus == RESULT_UPLOADED || newStatus == CONTRIBUTE_AND_FINALIZE_DONE) {
428437
replicate.setResultLink(updateReplicateStatusArgs.getResultLink());
429438
replicate.setChainCallbackData(updateReplicateStatusArgs.getChainCallbackData());
439+
update.set("replicates.$.resultLink", updateReplicateStatusArgs.getResultLink());
440+
update.set("replicates.$.chainCallbackData", updateReplicateStatusArgs.getChainCallbackData());
430441
}
431442

432443
if (statusUpdate.getDetails() != null &&
@@ -436,10 +447,13 @@ Either<ReplicateStatusUpdateError, TaskNotificationType> updateReplicateStatusWi
436447
taskLogsService.addComputeLogs(chainTaskId, computeLogs);
437448
statusUpdate.getDetails().setComputeLogs(null);//using null here to keep light replicate
438449
replicate.setAppComputeLogsPresent(true);
450+
update.set("replicates.$.appComputeLogsPresent", true);
439451
}
440452

453+
update.push("replicates.$.statusUpdateList", statusUpdate);
454+
Query query = Query.query(Criteria.where("chainTaskId").is(chainTaskId).and("replicates.walletAddress").is(walletAddress));
455+
mongoTemplate.updateFirst(query, update, ReplicatesList.class);
441456
replicate.updateStatus(statusUpdate);
442-
replicatesRepository.save(replicatesList);
443457
applicationEventPublisher.publishEvent(new ReplicateUpdatedEvent(chainTaskId, walletAddress, statusUpdate));
444458
ReplicateStatusCause newStatusCause = statusUpdate.getDetails() != null ?
445459
statusUpdate.getDetails().getCause() : null;

0 commit comments

Comments
 (0)