Skip to content

Conversation

@diegomrsantos
Copy link
Contributor

@diegomrsantos diegomrsantos commented Aug 11, 2024

The race proc in chronos doesn't cancel the remaining futures; sometimes that's what we need to do. This PR creates a proc that executes a race between a provided sequence of futures and cancels any remaining futures that have not yet been completed.

Related to #1165 and #1170

@diegomrsantos diegomrsantos changed the title create raceCancell fix: create raceCancell proc Aug 12, 2024
@diegomrsantos diegomrsantos requested a review from lchenut August 12, 2024 10:53
@diegomrsantos diegomrsantos marked this pull request as ready for review August 12, 2024 10:53
@lchenut lchenut mentioned this pull request Aug 12, 2024
@diegomrsantos diegomrsantos changed the title fix: create raceCancell proc fix: create raceAndCancelPending proc Aug 29, 2024
@richard-ramos
Copy link
Member

This looks useful, and perhaps should exist in chronos 🤔

@richard-ramos richard-ramos requested review from a team, Ben-PH, gmelodie and vladopajic and removed request for a team, Ben-PH and lchenut September 12, 2025 15:21
@github-project-automation github-project-automation bot moved this from backlog to In Progress in nim-libp2p Sep 12, 2025
Comment on lines +36 to +38
proc raceAndCancelPending*(
futs: seq[SomeFuture]
): Future[void] {.async: (raises: [ValueError, CancelledError]).} =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

raceAndCancelPending should return future that finished the race, aka result from race, because one might need this future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should indeed, mostly because race is declared that way - that said, returning the future is actually of limited use since the value type is lost - most uses of race end up discarding it and using the "original" instance.

The other risk is that one forgets that more than one future might be finished by the time race resumes.

let index = requests.find(raceFut)
requests.del(index)

proc raceAndCancelPending*(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about raceAndCancelPending -> raceAndCancel ?

@vladopajic
Copy link
Member

This looks useful, and perhaps should exist in chronos 🤔

seems better suited for cronos.

@arnetheduck wdyt?

## - `CancelledError` if the operation is canceled.
try:
discard await race(futs)
finally:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no need for finally .. in particular, if race is cancelled, it should not cancel futs to maintain the race contract in general - ValueError means there are no futures, so nothing to cancel either

@arnetheduck
Copy link
Contributor

arnetheduck commented Sep 15, 2025

This looks useful

It looks useful, but the question is whether it is useful ;) It would be good to see a motivating example where it's actually put to use before adding to chronos proper - ie where in libp2p would you use it, for example?

@vladopajic
Copy link
Member

This looks useful

It looks useful, but the question is whether it is useful ;) It would be good to see a motivating example where it's actually put to use before adding to chronos proper - ie where in libp2p would you use it, for example?

closest usecase:
https://github.com/vacp2p/nim-quic/blob/e5bcee4b909a9924fa6fbea305884888ce466330/quic/connection.nim#L173-L202

@arnetheduck
Copy link
Contributor

closest usecase:

This is a classic example of the trap I mentioned - even if the handshake completes successfully by the time the race finishes, the code might prefer to treat it as a timeout which often isn't what you want - but more than that, it's worth rewriting the code to use raceOrCancel in a few different situations to see that it truly works (with all the generics, error conditions etc) and that the outcome really looks better - it's a lot easier to add things to chronos (and libp2p btw) than it is to remove them, so we want to make sure the ergonomics have been practically stressed before adding too much

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

7 participants