Skip to content

Commit fe433e2

Browse files
authored
Merge pull request #533 from iExecBlockchainComputing/release/8.1.2
Release/8.1.2
2 parents c578b41 + 2c2c0cc commit fe433e2

File tree

8 files changed

+251
-38
lines changed

8 files changed

+251
-38
lines changed

CHANGELOG.md

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

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

5+
## [[8.1.2]](https://github.com/iExecBlockchainComputing/iexec-worker/releases/tag/v8.1.2) 2023-06-22
6+
7+
### Features
8+
- Retry dataset download on several IPFS gateways. (#532)
9+
### Bug Fixes
10+
- Improve interruptions handling in `IexecHubService`. (#529)
11+
- Return application execution `exitCause` as computed in `AppComputeService#getExitCauseFromFinalStatus`. (#531)
12+
### Dependency upgrade
13+
- Upgrade to `iexec-commons-poco` 3.0.3 dependency. (#532)
14+
515
## [[8.1.1]](https://github.com/iExecBlockchainComputing/iexec-worker/releases/tag/v8.1.1) 2023-06-15
616

717
### Bug Fixes

gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
version=8.1.1
1+
version=8.1.2
22
iexecCommonVersion=8.2.0
33
iexecCommonsContainersVersion=1.0.2
4-
iexecCommonsPocoVersion=3.0.2
4+
iexecCommonsPocoVersion=3.0.3
55
iexecBlockchainAdapterVersion=8.1.0
66
iexecResultVersion=8.1.0
77
iexecSmsVersion=8.1.0

src/main/java/com/iexec/worker/chain/IexecHubService.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,11 @@ IexecHubContract.TaskContributeEventResponse contribute(Contribution contributio
7777
contribution.getChainTaskId(), getWaitingTransactionCount());
7878
return sendContributeTransaction(contribution);
7979
}, executor).get();
80-
} catch (InterruptedException | ExecutionException e) {
80+
} catch (ExecutionException e) {
8181
log.error("contribute asynchronous execution did not complete", e);
82+
} catch (InterruptedException e) {
83+
log.error("contribute thread has been interrupted", e);
84+
Thread.currentThread().interrupt();
8285
}
8386
return null;
8487
}
@@ -143,8 +146,11 @@ IexecHubContract.TaskRevealEventResponse reveal(String chainTaskId, String resul
143146
log.info("Requested reveal [chainTaskId:{}, waitingTxCount:{}]", chainTaskId, getWaitingTransactionCount());
144147
return sendRevealTransaction(chainTaskId, resultDigest);
145148
}, executor).get();
146-
} catch (InterruptedException | ExecutionException e) {
149+
} catch (ExecutionException e) {
147150
log.error("reveal asynchronous execution did not complete", e);
151+
} catch (InterruptedException e) {
152+
log.error("reveal thread has been interrupted", e);
153+
Thread.currentThread().interrupt();
148154
}
149155
return null;
150156
}

src/main/java/com/iexec/worker/dataset/DataService.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.iexec.common.utils.FileHelper;
2222
import com.iexec.common.utils.IexecFileHelper;
2323
import com.iexec.commons.poco.task.TaskDescription;
24+
import com.iexec.commons.poco.utils.MultiAddressHelper;
2425
import com.iexec.worker.config.WorkerConfigurationService;
2526
import com.iexec.worker.utils.WorkflowException;
2627
import lombok.extern.slf4j.Slf4j;
@@ -47,7 +48,7 @@ public DataService(WorkerConfigurationService workerConfigurationService) {
4748
* Download dataset file for the given standard task and save
4849
* it in {@link IexecFileHelper#SLASH_IEXEC_IN}.
4950
*
50-
* @param taskDescription
51+
* @param taskDescription Task description containing dataset related parameters
5152
* @return downloaded dataset file path
5253
* @throws WorkflowException if download fails or bad checksum.
5354
*/
@@ -57,8 +58,20 @@ public String downloadStandardDataset(@Nonnull TaskDescription taskDescription)
5758
String uri = taskDescription.getDatasetUri();
5859
String filename = taskDescription.getDatasetAddress();
5960
String parentDirectoryPath = workerConfigurationService.getTaskInputDir(chainTaskId);
60-
String datasetLocalFilePath =
61-
downloadFile(chainTaskId, uri, parentDirectoryPath, filename);
61+
String datasetLocalFilePath = "";
62+
if (MultiAddressHelper.isMultiAddress(uri)) {
63+
for (String ipfsGateway : MultiAddressHelper.IPFS_GATEWAYS) {
64+
log.debug("Try to download dataset from {}", ipfsGateway);
65+
datasetLocalFilePath =
66+
downloadFile(chainTaskId, ipfsGateway + uri, parentDirectoryPath, filename);
67+
if (!datasetLocalFilePath.isEmpty()) {
68+
break;
69+
}
70+
}
71+
} else {
72+
datasetLocalFilePath =
73+
downloadFile(chainTaskId, uri, parentDirectoryPath, filename);
74+
}
6275
if (datasetLocalFilePath.isEmpty()) {
6376
throw new WorkflowException(ReplicateStatusCause.DATASET_FILE_DOWNLOAD_FAILED);
6477
}
@@ -82,8 +95,8 @@ public String downloadStandardDataset(@Nonnull TaskDescription taskDescription)
8295
* Download input files for the given standard task and save them
8396
* in the input folder.
8497
*
85-
* @param chainTaskId
86-
* @param uriList
98+
* @param chainTaskId Task ID used to create input files download folder
99+
* @param uriList List of input files to download
87100
* @throws WorkflowException if download fails.
88101
*/
89102
public void downloadStandardInputFiles(String chainTaskId, @Nonnull List<String> uriList)
@@ -103,14 +116,14 @@ public void downloadStandardInputFiles(String chainTaskId, @Nonnull List<String>
103116
* Download a file from a URI in the provided parent
104117
* directory and save it with the provided filename.
105118
*
106-
* @param chainTaskId
107-
* @param uri
108-
* @param parentDirectoryPath
109-
* @param filename
110-
* @return absolute path of the saved file
119+
* @param chainTaskId Task ID, for logging purpose
120+
* @param uri URI of single file to download
121+
* @param parentDirectoryPath Destination folder on worker host
122+
* @param filename Name of downloaded file in destination folder
123+
* @return absolute path of the saved file on worker host
111124
*/
112-
private String downloadFile(String chainTaskId, String uri,
113-
String parentDirectoryPath, String filename) {
125+
String downloadFile(String chainTaskId, String uri,
126+
String parentDirectoryPath, String filename) {
114127
if (StringUtils.isEmpty(chainTaskId) ||
115128
StringUtils.isEmpty(uri) ||
116129
StringUtils.isEmpty(parentDirectoryPath) ||

src/main/java/com/iexec/worker/executor/TaskManagerService.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ ReplicateActionResponse compute(TaskDescription taskDescription) {
262262
computeManagerService.runCompute(taskDescription,
263263
preResponse.getSecureSession());
264264
if (!appResponse.isSuccessful()) {
265-
ReplicateStatusCause cause = APP_COMPUTE_FAILED;
265+
final ReplicateStatusCause cause = appResponse.getExitCause();
266266
logError(cause, context, chainTaskId);
267267
return ReplicateActionResponse.failureWithDetails(
268268
ReplicateStatusDetails.builder()
@@ -438,7 +438,6 @@ ReplicateActionResponse uploadResult(String chainTaskId) {
438438
return ReplicateActionResponse.success(resultLink, callbackData);
439439
}
440440

441-
//TODO add getCannotContributeAndFinalizeStatusCause
442441
ReplicateActionResponse contributeAndFinalize(String chainTaskId) {
443442
return contributeOrContributeAndFinalize(chainTaskId, CONTRIBUTE_AND_FINALIZE);
444443
}

src/test/java/com/iexec/worker/chain/IexecHubServiceTests.java

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
import java.time.Duration;
4747
import java.util.List;
4848
import java.util.Optional;
49+
import java.util.concurrent.CompletableFuture;
50+
import java.util.concurrent.ExecutionException;
4951

5052
import static org.assertj.core.api.Assertions.assertThat;
5153
import static org.mockito.ArgumentMatchers.any;
@@ -73,6 +75,8 @@ class IexecHubServiceTests {
7375
private Web3j web3jClient;
7476
private IexecHubService iexecHubService;
7577
private Credentials credentials;
78+
@Mock
79+
private CompletableFuture<?> completableFuture;
7680

7781
@BeforeEach
7882
void init() throws Exception {
@@ -127,6 +131,43 @@ void shouldContribute() throws Exception {
127131
IexecHubContract.TaskContributeEventResponse response = iexecHubService.contribute(contribution);
128132
assertThat(response).isNotNull();
129133
}
134+
135+
@Test
136+
void shouldNotContributeOnExecutionException() throws ExecutionException, InterruptedException {
137+
final Contribution contribution = Contribution.builder()
138+
.chainTaskId(CHAIN_TASK_ID)
139+
.enclaveChallenge("enclaveChallenge")
140+
.enclaveSignature("enclaveSignature")
141+
.resultHash("resultHash")
142+
.resultSeal("resultSeal")
143+
.workerPoolSignature("workerPoolSignature")
144+
.build();
145+
try (MockedStatic<CompletableFuture> mockedStatic = mockStatic(CompletableFuture.class)) {
146+
mockedStatic.when(() -> CompletableFuture.supplyAsync(any(), any())).thenReturn(completableFuture);
147+
when(completableFuture.get()).thenThrow(ExecutionException.class);
148+
IexecHubContract.TaskContributeEventResponse response = iexecHubService.contribute(contribution);
149+
assertThat(response).isNull();
150+
}
151+
}
152+
153+
@Test
154+
void shouldNotContributeWhenInterrupted() throws ExecutionException, InterruptedException {
155+
final Contribution contribution = Contribution.builder()
156+
.chainTaskId(CHAIN_TASK_ID)
157+
.enclaveChallenge("enclaveChallenge")
158+
.enclaveSignature("enclaveSignature")
159+
.resultHash("resultHash")
160+
.resultSeal("resultSeal")
161+
.workerPoolSignature("workerPoolSignature")
162+
.build();
163+
try (MockedStatic<CompletableFuture> mockedStatic = mockStatic(CompletableFuture.class)) {
164+
mockedStatic.when(() -> CompletableFuture.supplyAsync(any(), any())).thenReturn(completableFuture);
165+
when(completableFuture.get()).thenThrow(InterruptedException.class);
166+
IexecHubContract.TaskContributeEventResponse response = iexecHubService.contribute(contribution);
167+
assertThat(response).isNull();
168+
assertThat(Thread.currentThread().isInterrupted()).isTrue();
169+
}
170+
}
130171
// endregion
131172

132173
// region reveal
@@ -145,6 +186,27 @@ void shouldReveal() throws Exception {
145186
IexecHubContract.TaskRevealEventResponse response = iexecHubService.reveal(CHAIN_TASK_ID, "resultDigest");
146187
assertThat(response).isNotNull();
147188
}
189+
190+
@Test
191+
void shouldNotRevealOnExecutionException() throws ExecutionException, InterruptedException {
192+
try (MockedStatic<CompletableFuture> mockedStatic = mockStatic(CompletableFuture.class)) {
193+
mockedStatic.when(() -> CompletableFuture.supplyAsync(any(), any())).thenReturn(completableFuture);
194+
when(completableFuture.get()).thenThrow(ExecutionException.class);
195+
IexecHubContract.TaskRevealEventResponse response = iexecHubService.reveal(CHAIN_TASK_ID, "resultDigest");
196+
assertThat(response).isNull();
197+
}
198+
}
199+
200+
@Test
201+
void shouldNotContributeRevealWhenInterrupted() throws ExecutionException, InterruptedException {
202+
try (MockedStatic<CompletableFuture> mockedStatic = mockStatic(CompletableFuture.class)) {
203+
mockedStatic.when(() -> CompletableFuture.supplyAsync(any(), any())).thenReturn(completableFuture);
204+
when(completableFuture.get()).thenThrow(InterruptedException.class);
205+
IexecHubContract.TaskRevealEventResponse response = iexecHubService.reveal(CHAIN_TASK_ID, "resultDigest");
206+
assertThat(response).isNull();
207+
assertThat(Thread.currentThread().isInterrupted()).isTrue();
208+
}
209+
}
148210
// end region
149211

150212
// region contributeAndFinalize
@@ -168,6 +230,43 @@ void shouldContributeAndFinalize() throws Exception {
168230
Optional<ChainReceipt> chainReceipt = iexecHubService.contributeAndFinalize(contribution, "resultLink", "callbackData");
169231
assertThat(chainReceipt).isNotEmpty();
170232
}
233+
234+
@Test
235+
void shouldNotContributeAndFinalizeOnExecutionException() throws ExecutionException, InterruptedException {
236+
final Contribution contribution = Contribution.builder()
237+
.chainTaskId(CHAIN_TASK_ID)
238+
.enclaveChallenge("enclaveChallenge")
239+
.enclaveSignature("enclaveSignature")
240+
.resultHash("resultHash")
241+
.resultSeal("resultSeal")
242+
.workerPoolSignature("workerPoolSignature")
243+
.build();
244+
try (MockedStatic<CompletableFuture> mockedStatic = mockStatic(CompletableFuture.class)) {
245+
mockedStatic.when(() -> CompletableFuture.supplyAsync(any(), any())).thenReturn(completableFuture);
246+
when(completableFuture.get()).thenThrow(ExecutionException.class);
247+
Optional<ChainReceipt> chainReceipt = iexecHubService.contributeAndFinalize(contribution, "resultLink", "callbackData");
248+
assertThat(chainReceipt).isEmpty();
249+
}
250+
}
251+
252+
@Test
253+
void shouldNotContributeAndFinalizeWhenInterrupted() throws ExecutionException, InterruptedException {
254+
final Contribution contribution = Contribution.builder()
255+
.chainTaskId(CHAIN_TASK_ID)
256+
.enclaveChallenge("enclaveChallenge")
257+
.enclaveSignature("enclaveSignature")
258+
.resultHash("resultHash")
259+
.resultSeal("resultSeal")
260+
.workerPoolSignature("workerPoolSignature")
261+
.build();
262+
try (MockedStatic<CompletableFuture> mockedStatic = mockStatic(CompletableFuture.class)) {
263+
mockedStatic.when(() -> CompletableFuture.supplyAsync(any(), any())).thenReturn(completableFuture);
264+
when(completableFuture.get()).thenThrow(InterruptedException.class);
265+
Optional<ChainReceipt> chainReceipt = iexecHubService.contributeAndFinalize(contribution, "resultLink", "callbackData");
266+
assertThat(chainReceipt).isEmpty();
267+
assertThat(Thread.currentThread().isInterrupted()).isTrue();
268+
}
269+
}
171270
// endregion
172271

173272
// region ChainTask status

0 commit comments

Comments
 (0)