Skip to content

Conversation

phausler
Copy link
Member

@phausler phausler commented Jan 12, 2022

This is a fundamental building block for zip, combineLatest, debounce and numerous other operations on AsyncSequence, but is also useful generally for handling tasks.

} catch {
XCTAssertEqual((error as NSError).code, -1)
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Should we test task cancellation as well?

Copy link
Member Author

Choose a reason for hiding this comment

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

That is another aspect I am considering about this - should these first methods have a cancellation handler? if so that would make the return value optional.

or should that be a second set of functions?

Copy link
Member

Choose a reason for hiding this comment

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

If a task is cancelled and "finishes first", then first will throw the CancellationError, no? Is that not enough? What did you have in mind?

Copy link
Member Author

Choose a reason for hiding this comment

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

well I guess I am thinking of perhaps an initializer on Task that takes N blocks and returns an actual Task object that can be cancelled is one option. The other option is to pass a cancelHandler and make the return type optional.

Copy link
Member

Choose a reason for hiding this comment

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

OK. We can discuss the shape of an API like that separately I think. In the meantime, with the current methods, is cancelling a task any different than the throwing case? Does it still deserve its own test case?

@phausler
Copy link
Member Author

hmm I think I have a safer idea to explore that might address the cancellation - will be adjusting this PR accordingly

} else {
return task
}
}
Copy link
Member

@kperryua kperryua Jan 14, 2022

Choose a reason for hiding this comment

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

Thoughts on putting the withCriticalSection call in this method proper? I think you could similarly add

mutating func set(continuation: ...) { }
mutating func removeAll() -> [Task<Success, Failure>]? { }

which similarly encapsulate the withCriticalSection invocation. I think this would do a lot to make the callsites more readable.

Copy link
Member Author

Choose a reason for hiding this comment

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

The critical section needs to be outside of the mutation method because the mutation has the write back of the value of the structure so it needs to be external to the change.

/// - Parameters:
/// - tasks: The running tasks to obtain a result from
/// - Returns: The first result from the running tasks
public static func first<Tasks: Sequence>(
Copy link
Member

Choose a reason for hiding this comment

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

This name, in conjunction with a sequence parameter, seems a little confusing, since one could easily read it as the result of the first task in the sequence. Have you thought about alternative names, e.g. firstResult(from: imageLoadingTasks)? It’s hard to disambiguate “first in order” from “first in time”!

Copy link
Member Author

Choose a reason for hiding this comment

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

That is where the name race offers some better connotations; which it is a term of art in the FRP world.... sadly we (I think it is a fine name) don't per-se like those names.

Copy link
Member Author

Choose a reason for hiding this comment

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

we can keep this internal for now since I was able to bring it into the same module.

@phausler phausler merged commit 1c11d4a into main Jan 14, 2022
@phausler phausler deleted the pr/task_first branch January 14, 2022 16:25
@parkera
Copy link
Member

parkera commented Jan 14, 2022

As far as the name goes, select may be closer to the behavior we want here.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants