steid

@jamesgill /

steid/src/domain/repository/pull_request_repo.rs
Rust3.6 KBCode·Blame·History·Raw
1use super::RepositoryResult;
2use crate::domain::{
3 IssueNumber, PullRequest, PullRequestComment, PullRequestId, PullRequestState, RepoId,
4};
5
6/// How many pull requests a repository has in each state.
7///
8/// Three counts in one round trip, for [`IssueCounts`](super::IssueCounts)'s reason: the
9/// toolbar renders all of them, and asking three times would be three queries to draw
10/// one line.
11#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
12pub struct PullRequestCounts {
13 pub open: u64,
14 pub merged: u64,
15 pub closed: u64,
16}
17
18impl PullRequestCounts {
19 /// How many the repository has in one state.
20 pub fn of(self, state: PullRequestState) -> u64 {
21 match state {
22 PullRequestState::Open => self.open,
23 PullRequestState::Merged => self.merged,
24 PullRequestState::Closed => self.closed,
25 }
26 }
27}
28
29/// Persistence for the [`PullRequest`] aggregate.
30///
31/// Comments live behind this port rather than one of their own, for the reason issue
32/// comments do: a comment is not an aggregate root and nothing addresses one except
33/// through the request it hangs off.
34///
35/// **There is no `next_number` here.** Numbers come from
36/// [`IssueRepository::next_number`](super::IssueRepository), which is the single
37/// sequence a repository has — that is what makes `#7` name one thing whether it is an
38/// issue or a pull request, and a second allocator would immediately collide with the
39/// first.
40pub trait PullRequestRepository: Send + Sync {
41 /// Looks a request up by the `/{handle}/repos/{name}/pulls/{number}` pair.
42 fn find_by_number(
43 &self,
44 repo_id: &RepoId,
45 number: IssueNumber,
46 ) -> impl Future<Output = RepositoryResult<Option<PullRequest>>> + Send;
47
48 /// One page of a repository's pull requests in the given state, newest first —
49 /// which for a monotonic sequence is descending number, an order that cannot tie.
50 ///
51 /// A `limit` past the end of the list is a short page, not an error: a request
52 /// merged between two page loads is ordinary, and so is a stale link.
53 fn list_by_repo(
54 &self,
55 repo_id: &RepoId,
56 state: PullRequestState,
57 offset: usize,
58 limit: usize,
59 ) -> impl Future<Output = RepositoryResult<Vec<PullRequest>>> + Send;
60
61 /// How many the repository has open, merged and closed.
62 fn counts(
63 &self,
64 repo_id: &RepoId,
65 ) -> impl Future<Output = RepositoryResult<PullRequestCounts>> + Send;
66
67 /// How many comments each pull request on the repository carries.
68 ///
69 /// Per repository rather than per request, because the list renders a count on
70 /// every row: asking per row is a query per row.
71 fn comment_counts(
72 &self,
73 repo_id: &RepoId,
74 ) -> impl Future<Output = RepositoryResult<Vec<(PullRequestId, u64)>>> + Send;
75
76 /// Inserts or replaces a pull request.
77 fn save(&self, pull: &PullRequest) -> impl Future<Output = RepositoryResult<()>> + Send;
78
79 /// Every comment on a request, oldest first — a conversation reads forwards.
80 ///
81 /// Comments written in the same second keep the order they were written in, which
82 /// both implementations take from insertion order rather than from the id: ids are
83 /// random UUIDs, so a tie broken by one would occasionally read backwards.
84 fn list_comments(
85 &self,
86 pull_request_id: &PullRequestId,
87 ) -> impl Future<Output = RepositoryResult<Vec<PullRequestComment>>> + Send;
88
89 /// Adds a comment to a pull request.
90 fn add_comment(
91 &self,
92 comment: &PullRequestComment,
93 ) -> impl Future<Output = RepositoryResult<()>> + Send;
94}