Add resolved_issue_size_distribution field - #238
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #238 +/- ##
==========================================
+ Coverage 34.42% 35.51% +1.08%
==========================================
Files 17 17
Lines 1008 1025 +17
==========================================
+ Hits 347 364 +17
Misses 661 661 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
danbi2990
left a comment
There was a problem hiding this comment.
Could you add a changelog entry for the new API?
| impl TryFrom<&str> for IssueSize { | ||
| type Error = (); | ||
|
|
||
| fn try_from(value: &str) -> Result<Self, Self::Error> { |
There was a problem hiding this comment.
How about using the from trait, because we already added a None variant for exceptions?
There was a problem hiding this comment.
Thanks for the suggestion. I’ve applied it.
| item.project_title == super::issue::TODO_LIST_PROJECT_TITLE | ||
| && item.todo_status.as_deref() == Some(super::issue::TODO_LIST_STATUS_DONE) |
There was a problem hiding this comment.
This seems redundant because the issues are already validated as resolved.
| .map_or(IssueSize::None, |item| { | ||
| item.todo_size | ||
| .as_deref() | ||
| .and_then(|s| IssueSize::try_from(s).ok()) |
There was a problem hiding this comment.
How about creating a HashMap<&str, usize> first and then converting it to a Vec<IssueSize>? This would allow IssueSize to drop the hash derive.
There was a problem hiding this comment.
Thanks for the suggestion. I’ve applied it.
| .try_into() | ||
| .expect("The number of resolved issues will not exceed i32::MAX"); | ||
|
|
||
| let mut size_counts = HashMap::new(); |
There was a problem hiding this comment.
Using fold would simplify the transformation.
There was a problem hiding this comment.
Thanks for the suggestion. I’ve applied it.
b6b8f44 to
cbeb8f2
Compare
|
I have a suggestion regarding the implementation of the Current ApproachThe current implementation processes the issues in multiple steps:
This approach involves multiple passes over the data and creates intermediate collections, which can be inefficient. Proposed ImprovementWe could refactor this to calculate all statistics in a single pass. By applying the filter and then using a single Benefits
This is just a suggestion for a potential optimization, as the current code is functionally correct. Let me know what you think! |
I've thought about this as well. My idea can be illustrated as follows: let mut stat1 = 0;
let mut stat2 = 0;
for issue in issues {
// calculate and mutate in one pass
}My concern is that this approach couples the calculation logic together, which reduces modularity. If we later change the calculation structure, it would be harder to refactor. In my opinion, we should delay this discussion until the structure is more stable. |
| - Added `resolvedIssueSizeDistribution` field to `issueStat` query. | ||
| - Added new statistics to GraphQL API `issueStat` query. A field | ||
| `resolvedIssueCount` is added, indicating the number of resolved issues. | ||
| Currently, an issue is defined to be resolved if and only if (1) it is |
There was a problem hiding this comment.
Could you move these entries (line 11-15) to line 23? I believe they should come after the creation of the issueStat query.
| .map_or("None", |s| match s { | ||
| "XS" | "S" | "M" | "L" | "XL" => s, | ||
| _ => "None", | ||
| }); |
There was a problem hiding this comment.
Sorry for the confusion, but using HashMap<IssueSize, usize> with Hash derived seems more robust, since this match code is redundant given the From impl for IssueSize.
Could you revert to the previous code with Hash derived for IssueSize?
It will look like this:
let size_str = issue
.project_items
.nodes
.iter()
.find(|item| item.project_title == super::issue::TODO_LIST_PROJECT_TITLE)
.and_then(|item| item.todo_size.as_deref())
.unwrap_or_default();
*acc.entry(IssueSize::from(size_str)).or_insert(0) += 1;The reason I suggested using HashMap<&str, usize> is that I only considered the fixed set of strings: XS, S, M, L, XL and blank. However, if a new size such as "XXS" is introduced, it should first be filtered by the From implementation of IssueSize before being stored in the hashmap.
Please let me know if you have other ideas.
There was a problem hiding this comment.
I've made a change: I used into instead of from. What do you think?
| count, | ||
| }) | ||
| .collect(); | ||
| resolved_issue_size_distribution.sort_by_key(|item| item.size); |
There was a problem hiding this comment.
Consider using sort_unstable_by_key, as it has some benefits over sort_by_key. See the "Rules on Sorting" page on Notion for details.
There was a problem hiding this comment.
What do you think about using a BTreeMap instead of a HashMap here? Since the data size is usually small (around 5 items), the overhead would be negligible, and it would let us remove the extra sort_by_key step for a simpler implementation.
cbeb8f2 to
3fe20bb
Compare
3fe20bb to
adc4d5d
Compare
| - Added `resolvedIssueSizeDistribution` field to `issueStat` query, which | ||
| shows the distribution of sizes for resolved issues. |
There was a problem hiding this comment.
issueStat 도 Unreleased 섹션에서 새롭게 added 된 것이므로, resolvedIssueSizeDistribution 에 관한 것은 issueStat 의 addition에 관한 것에 포함되도록 해주세요.
adc4d5d to
fe8ad8d
Compare
Close #197
Graphql Response