|
27 | 27 | import org.springframework.beans.factory.annotation.Autowired; |
28 | 28 | import org.springframework.stereotype.Service; |
29 | 29 | import org.web3j.protocol.core.RemoteCall; |
30 | | -import org.web3j.protocol.core.methods.response.BaseEventResponse; |
| 30 | +import org.web3j.protocol.core.methods.response.Log; |
31 | 31 | import org.web3j.protocol.core.methods.response.TransactionReceipt; |
32 | 32 |
|
33 | 33 | import java.nio.charset.StandardCharsets; |
|
38 | 38 | import java.util.concurrent.ExecutionException; |
39 | 39 | import java.util.concurrent.Executors; |
40 | 40 | import java.util.concurrent.ThreadPoolExecutor; |
41 | | -import java.util.function.Function; |
42 | 41 | import java.util.stream.Collectors; |
43 | 42 |
|
44 | 43 | import static com.iexec.commons.poco.chain.ChainContributionStatus.CONTRIBUTED; |
@@ -70,6 +69,7 @@ public IexecHubService(CredentialsService credentialsService, |
70 | 69 | this.executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1); |
71 | 70 | } |
72 | 71 |
|
| 72 | + // region contribute |
73 | 73 | IexecHubContract.TaskContributeEventResponse contribute(Contribution contribution) { |
74 | 74 | try { |
75 | 75 | return CompletableFuture.supplyAsync(() -> { |
@@ -113,33 +113,21 @@ private IexecHubContract.TaskContributeEventResponse sendContributeTransaction(C |
113 | 113 | .collect(Collectors.toList()); |
114 | 114 | log.debug("contributeEvents count {} [chainTaskId: {}]", contributeEvents.size(), chainTaskId); |
115 | 115 |
|
116 | | - IexecHubContract.TaskContributeEventResponse contributeEvent = null; |
117 | 116 | if (!contributeEvents.isEmpty()) { |
118 | | - contributeEvent = contributeEvents.get(0); |
119 | | - } |
120 | | - |
121 | | - if (isSuccessTx(chainTaskId, contributeEvent, CONTRIBUTED)) { |
122 | | - log.info("Contributed [chainTaskId:{}, contribution:{}, gasUsed:{}, log:{}]", |
123 | | - chainTaskId, contribution, contributeReceipt.getGasUsed(), contributeEvent.log); |
124 | | - return contributeEvent; |
| 117 | + IexecHubContract.TaskContributeEventResponse contributeEvent = contributeEvents.get(0); |
| 118 | + if (isSuccessTx(chainTaskId, contributeEvent.log, CONTRIBUTED)) { |
| 119 | + log.info("Contributed [chainTaskId:{}, contribution:{}, gasUsed:{}, log:{}]", |
| 120 | + chainTaskId, contribution, contributeReceipt.getGasUsed(), contributeEvent.log); |
| 121 | + return contributeEvent; |
| 122 | + } |
125 | 123 | } |
126 | 124 |
|
127 | 125 | log.error("Failed to contribute [chainTaskId:{}]", chainTaskId); |
128 | 126 | return null; |
129 | 127 | } |
| 128 | + // endregion |
130 | 129 |
|
131 | | - boolean isSuccessTx(String chainTaskId, BaseEventResponse txEvent, ChainContributionStatus pretendedStatus) { |
132 | | - if (txEvent == null || txEvent.log == null) { |
133 | | - return false; |
134 | | - } |
135 | | - |
136 | | - if (txEvent.log.getType() == null || txEvent.log.getType().equals(PENDING_RECEIPT_STATUS)) { |
137 | | - return isStatusValidOnChainAfterPendingReceipt(chainTaskId, pretendedStatus, this::isContributionStatusValidOnChain); |
138 | | - } |
139 | | - |
140 | | - return true; |
141 | | - } |
142 | | - |
| 130 | + // region reveal |
143 | 131 | IexecHubContract.TaskRevealEventResponse reveal(String chainTaskId, String resultDigest) { |
144 | 132 | try { |
145 | 133 | return CompletableFuture.supplyAsync(() -> { |
@@ -176,21 +164,21 @@ private IexecHubContract.TaskRevealEventResponse sendRevealTransaction(String ch |
176 | 164 | .collect(Collectors.toList()); |
177 | 165 | log.debug("revealEvents count {} [chainTaskId:{}]", revealEvents.size(), chainTaskId); |
178 | 166 |
|
179 | | - IexecHubContract.TaskRevealEventResponse revealEvent = null; |
180 | 167 | if (!revealEvents.isEmpty()) { |
181 | | - revealEvent = revealEvents.get(0); |
182 | | - } |
183 | | - |
184 | | - if (isSuccessTx(chainTaskId, revealEvent, REVEALED)) { |
185 | | - log.info("Revealed [chainTaskId:{}, resultDigest:{}, gasUsed:{}, log:{}]", |
186 | | - chainTaskId, resultDigest, revealReceipt.getGasUsed(), revealEvent.log); |
187 | | - return revealEvent; |
| 168 | + IexecHubContract.TaskRevealEventResponse revealEvent = revealEvents.get(0); |
| 169 | + if (isSuccessTx(chainTaskId, revealEvent.log, REVEALED)) { |
| 170 | + log.info("Revealed [chainTaskId:{}, resultDigest:{}, gasUsed:{}, log:{}]", |
| 171 | + chainTaskId, resultDigest, revealReceipt.getGasUsed(), revealEvent.log); |
| 172 | + return revealEvent; |
| 173 | + } |
188 | 174 | } |
189 | 175 |
|
190 | 176 | log.error("Failed to reveal [chainTaskId:{}]", chainTaskId); |
191 | 177 | return null; |
192 | 178 | } |
| 179 | + // endregion reveal |
193 | 180 |
|
| 181 | + // region contributeAndFinalize |
194 | 182 | public Optional<ChainReceipt> contributeAndFinalize(Contribution contribution, String resultLink, String callbackData) { |
195 | 183 | try { |
196 | 184 | return CompletableFuture.supplyAsync(() -> { |
@@ -238,72 +226,86 @@ private IexecHubContract.TaskFinalizeEventResponse sendContributeAndFinalizeTran |
238 | 226 | .collect(Collectors.toList()); |
239 | 227 | log.debug("finalizeEvents count {} [chainTaskId:{}]", finalizeEvents.size(), chainTaskId); |
240 | 228 |
|
241 | | - IexecHubContract.TaskFinalizeEventResponse finalizeEvent = null; |
242 | 229 | if (!finalizeEvents.isEmpty()) { |
243 | | - finalizeEvent = finalizeEvents.get(0); |
244 | | - } |
245 | | - |
246 | | - if (isSuccessTx(chainTaskId, finalizeEvent, REVEALED)) { |
247 | | - log.info("contributeAndFinalize done [chainTaskId:{}, contribution:{}, gasUsed:{}, log:{}]", |
248 | | - chainTaskId, contribution, receipt.getGasUsed(), finalizeEvent.log); |
249 | | - return finalizeEvent; |
| 230 | + IexecHubContract.TaskFinalizeEventResponse finalizeEvent = finalizeEvents.get(0); |
| 231 | + if (isSuccessTx(chainTaskId, finalizeEvent.log, REVEALED)) { |
| 232 | + log.info("contributeAndFinalize done [chainTaskId:{}, contribution:{}, gasUsed:{}, log:{}]", |
| 233 | + chainTaskId, contribution, receipt.getGasUsed(), finalizeEvent.log); |
| 234 | + return finalizeEvent; |
| 235 | + } |
250 | 236 | } |
251 | 237 |
|
252 | 238 | log.error("contributeAndFinalize failed [chainTaskId:{}]", chainTaskId); |
253 | 239 | return null; |
254 | 240 | } |
| 241 | + // endregion |
255 | 242 |
|
| 243 | + // region isSuccessTx |
256 | 244 | private long getWaitingTransactionCount() { |
257 | 245 | return executor.getTaskCount() - 1 - executor.getCompletedTaskCount(); |
258 | 246 | } |
259 | 247 |
|
260 | | - Optional<ChainContribution> getChainContribution(String chainTaskId) { |
261 | | - return getChainContribution(chainTaskId, credentialsService.getCredentials().getAddress()); |
262 | | - } |
263 | | - |
264 | | - Optional<ChainAccount> getChainAccount() { |
265 | | - return getChainAccount(credentialsService.getCredentials().getAddress()); |
266 | | - } |
267 | | - |
268 | | - public boolean hasEnoughGas() { |
269 | | - return web3jService.hasEnoughGas(credentialsService.getCredentials().getAddress()); |
270 | | - } |
| 248 | + boolean isSuccessTx(String chainTaskId, Log eventLog, ChainContributionStatus pretendedStatus) { |
| 249 | + if (eventLog == null) { |
| 250 | + return false; |
| 251 | + } |
271 | 252 |
|
272 | | - public long getLatestBlockNumber() { |
273 | | - return web3jService.getLatestBlockNumber(); |
274 | | - } |
| 253 | + log.info("event log type {}", eventLog.getType()); |
| 254 | + if (PENDING_RECEIPT_STATUS.equals(eventLog.getType())) { |
| 255 | + return isStatusValidOnChainAfterPendingReceipt(chainTaskId, pretendedStatus); |
| 256 | + } |
275 | 257 |
|
276 | | - public long getMaxWaitingTimeWhenNotSync() { |
277 | | - return web3jService.getMaxWaitingTimeWhenPendingReceipt(); |
| 258 | + return true; |
278 | 259 | } |
279 | 260 |
|
280 | | - private Boolean isContributionStatusValidOnChain(String chainTaskId, ChainStatus chainContributionStatus) { |
281 | | - if (chainContributionStatus instanceof ChainContributionStatus) { |
282 | | - Optional<ChainContribution> chainContribution = getChainContribution(chainTaskId); |
283 | | - return chainContribution.isPresent() && chainContribution.get().getStatus().equals(chainContributionStatus); |
284 | | - } |
285 | | - return false; |
| 261 | + private boolean isContributionStatusValidOnChain(String chainTaskId, ChainContributionStatus chainContributionStatus) { |
| 262 | + Optional<ChainContribution> chainContribution = getChainContribution(chainTaskId); |
| 263 | + return chainContribution.isPresent() && chainContribution.get().getStatus() == chainContributionStatus; |
286 | 264 | } |
287 | 265 |
|
288 | | - private boolean isBlockchainReadTrueWhenNodeNotSync(String chainTaskId, Function<String, Boolean> booleanBlockchainReadFunction) { |
289 | | - long maxWaitingTime = web3jService.getMaxWaitingTimeWhenPendingReceipt(); |
290 | | - long startTime = System.currentTimeMillis(); |
| 266 | + private boolean isStatusValidOnChainAfterPendingReceipt(String chainTaskId, ChainContributionStatus onchainStatus) { |
| 267 | + long maxWaitingTime = 10 * web3jService.getBlockTime().toMillis(); |
| 268 | + log.info("Waiting for on-chain status after pending receipt " + |
| 269 | + "[chainTaskId:{}, status:{}, maxWaitingTime:{}]", |
| 270 | + chainTaskId, onchainStatus, maxWaitingTime); |
291 | 271 |
|
292 | | - for (long duration = 0L; duration < maxWaitingTime; duration = System.currentTimeMillis() - startTime) { |
| 272 | + final long startTime = System.currentTimeMillis(); |
| 273 | + long duration = 0; |
| 274 | + while (duration < maxWaitingTime) { |
293 | 275 | try { |
294 | | - if (booleanBlockchainReadFunction.apply(chainTaskId)) { |
| 276 | + if (isContributionStatusValidOnChain(chainTaskId, onchainStatus)) { |
295 | 277 | return true; |
296 | 278 | } |
297 | | - |
298 | | - Thread.sleep(500L); |
| 279 | + Thread.sleep(500); |
299 | 280 | } catch (InterruptedException e) { |
300 | | - log.error("Error in checking the latest block number [chainTaskId:{}, maxWaitingTime:{}]", |
301 | | - chainTaskId, maxWaitingTime); |
| 281 | + log.error("Error in checking the latest block number", e); |
| 282 | + Thread.currentThread().interrupt(); |
302 | 283 | } |
| 284 | + duration = System.currentTimeMillis() - startTime; |
303 | 285 | } |
304 | 286 |
|
| 287 | + log.error("Timeout reached after waiting for on-chain status " + |
| 288 | + "[chainTaskId:{}, maxWaitingTime:{}]", |
| 289 | + chainTaskId, maxWaitingTime); |
305 | 290 | return false; |
306 | 291 | } |
| 292 | + // endregion |
| 293 | + |
| 294 | + Optional<ChainContribution> getChainContribution(String chainTaskId) { |
| 295 | + return getChainContribution(chainTaskId, credentialsService.getCredentials().getAddress()); |
| 296 | + } |
| 297 | + |
| 298 | + Optional<ChainAccount> getChainAccount() { |
| 299 | + return getChainAccount(credentialsService.getCredentials().getAddress()); |
| 300 | + } |
| 301 | + |
| 302 | + public boolean hasEnoughGas() { |
| 303 | + return web3jService.hasEnoughGas(credentialsService.getCredentials().getAddress()); |
| 304 | + } |
| 305 | + |
| 306 | + public long getLatestBlockNumber() { |
| 307 | + return web3jService.getLatestBlockNumber(); |
| 308 | + } |
307 | 309 |
|
308 | 310 | boolean isChainTaskActive(String chainTaskId) { |
309 | 311 | Optional<ChainTask> chainTask = getChainTask(chainTaskId); |
|
0 commit comments