Skip to content

Commit

Permalink
Merge pull request #14 from t0mmili/feature/13-unclear-issues-count
Browse files Browse the repository at this point in the history
[Feature] Separate PRs from Issues
  • Loading branch information
vladkens authored Oct 12, 2024
2 parents f19252a + d218cc6 commit 5ca9bf8
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 7 deletions.
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ curl -H "x-api-token:1234" http://127.0.0.1:8080/api/repos
"forks": 1,
"watchers": 110,
"issues": 5,
"prs": 1,
"clones_count": 90,
"clones_uniques": 45,
"views_count": 1726,
Expand Down
63 changes: 56 additions & 7 deletions src/db_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use serde_variant::to_variant_name;
use sqlx::{sqlite::SqliteConnectOptions, FromRow, SqlitePool};

use crate::gh_client::{Repo, RepoClones, RepoPopularPath, RepoReferrer, RepoViews};
use crate::gh_client::{PullRequest, Repo, RepoClones, RepoPopularPath, RepoReferrer, RepoViews};
use crate::types::Res;

// MARK: Migrations
Expand Down Expand Up @@ -87,11 +87,22 @@ async fn migrate_v2(db: &SqlitePool) -> Res {
Ok(())
}

async fn migrate_v3(db: &SqlitePool) -> Res {
let queries = vec!["ALTER TABLE repo_stats ADD COLUMN prs INTEGER NOT NULL DEFAULT 0;"];

for qs in queries {
let _ = sqlx::query(qs).execute(db).await?;
}

Ok(())
}

async fn migrate<'a>(db: &'a SqlitePool) -> Res {
type BoxFn = Box<dyn for<'a> Fn(&'a SqlitePool) -> Pin<Box<dyn Future<Output = Res> + 'a>>>;
let migrations: Vec<BoxFn> = vec![
Box::new(|db| Box::pin(migrate_v1(db))), //
Box::new(|db| Box::pin(migrate_v2(db))),
Box::new(|db| Box::pin(migrate_v3(db))),
];

let version: (i32,) = sqlx::query_as("PRAGMA user_version").fetch_one(db).await?;
Expand Down Expand Up @@ -129,6 +140,7 @@ pub struct RepoTotals {
pub forks: i32,
pub watchers: i32,
pub issues: i32,
pub prs: i32,
pub clones_count: i32,
pub clones_uniques: i32,
pub views_count: i32,
Expand Down Expand Up @@ -199,6 +211,7 @@ pub enum RepoSort {
Forks,
Watchers,
Issues,
Prs,
#[serde(rename = "clones_count")]
Clones,
#[serde(rename = "views_count")]
Expand Down Expand Up @@ -264,7 +277,7 @@ INNER JOIN (
latest.*
FROM repo_stats rs
INNER JOIN (
SELECT repo_id, MAX(date) AS date, stars, forks, watchers, issues
SELECT repo_id, MAX(date) AS date, stars, forks, watchers, issues, prs
FROM repo_stats GROUP BY repo_id
) latest ON latest.repo_id = rs.repo_id
GROUP BY rs.repo_id
Expand Down Expand Up @@ -412,13 +425,12 @@ impl DbClient {

pub async fn insert_stats(&self, repo: &Repo, date: &str) -> Res {
let qs = "
INSERT INTO repo_stats AS t (repo_id, date, stars, forks, watchers, issues)
VALUES ($1, $2, $3, $4, $5, $6)
INSERT INTO repo_stats AS t (repo_id, date, stars, forks, watchers)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT(repo_id, date) DO UPDATE SET
stars = MAX(t.stars, excluded.stars),
forks = MAX(t.forks, excluded.forks),
watchers = MAX(t.watchers, excluded.watchers),
issues = MAX(t.issues, excluded.issues);
watchers = MAX(t.watchers, excluded.watchers);
";

let _ = sqlx::query(qs)
Expand All @@ -427,7 +439,44 @@ impl DbClient {
.bind(repo.stargazers_count as i32)
.bind(repo.forks_count as i32)
.bind(repo.watchers_count as i32)
.bind(repo.open_issues_count as i32)
.execute(&self.db)
.await?;

Ok(())
}

pub async fn insert_issues(&self, repo: &Repo, date: &str, prs: &[PullRequest]) -> Res {
let issues_count = repo.open_issues_count - prs.len() as u32;

let qs = "
INSERT INTO repo_stats AS t (repo_id, date, issues)
VALUES ($1, $2, $3)
ON CONFLICT(repo_id, date) DO UPDATE SET
issues = excluded.issues;
";

let _ = sqlx::query(qs)
.bind(repo.id as i64)
.bind(&date)
.bind(issues_count as i32)
.execute(&self.db)
.await?;

Ok(())
}

pub async fn insert_prs(&self, repo: &Repo, date: &str, prs: &[PullRequest]) -> Res {
let qs = "
INSERT INTO repo_stats AS t (repo_id, date, prs)
VALUES ($1, $2, $3)
ON CONFLICT(repo_id, date) DO UPDATE SET
prs = excluded.prs;
";

let _ = sqlx::query(qs)
.bind(repo.id as i64)
.bind(&date)
.bind(prs.len() as i32)
.execute(&self.db)
.await?;

Expand Down
13 changes: 13 additions & 0 deletions src/gh_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ pub struct Repo {
pub archived: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct PullRequest {
pub id: u64,
pub title: String,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct TrafficDaily {
pub timestamp: String,
Expand Down Expand Up @@ -129,6 +135,13 @@ impl GhClient {
Ok(dat)
}

pub async fn get_open_pull_requests(&self, repo: &str) -> Res<Vec<PullRequest>> {
let url = format!("{}/repos/{}/pulls?state=open", self.base_url, repo);
let req = self.client.get(url);
let dat: Vec<PullRequest> = self.with_pagination(req).await?;
Ok(dat)
}

// https://docs.github.com/en/rest/metrics/traffic?apiVersion=2022-11-28
pub async fn traffic_clones(&self, repo: &str) -> Res<RepoClones> {
let url = format!("{}/repos/{}/traffic/clones", self.base_url, repo);
Expand Down
4 changes: 4 additions & 0 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@ pub async fn update_metrics(db: &DbClient, gh: &GhClient) -> Res {
}

async fn update_repo_metrics(db: &DbClient, gh: &GhClient, repo: &Repo, date: &str) -> Res {
let prs = gh.get_open_pull_requests(&repo.full_name).await?;
let views = gh.traffic_views(&repo.full_name).await?;
let clones = gh.traffic_clones(&repo.full_name).await?;
let referrers = gh.traffic_refs(&repo.full_name).await?;

let popular_paths = gh.traffic_paths(&repo.full_name).await?;

db.insert_repo(&repo).await?;
db.insert_stats(&repo, date).await?;
db.insert_issues(&repo, date, &prs).await?;
db.insert_prs(&repo, date, &prs).await?;
db.insert_views(&repo, &views).await?;
db.insert_clones(&repo, &clones).await?;
db.insert_referrers(&repo, date, &referrers).await?;
Expand Down
1 change: 1 addition & 0 deletions src/routes/html.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ pub async fn index(State(state): State<Arc<AppState>>, req: Request) -> HtmlRes
let cols: Vec<(&str, Box<dyn Fn(&RepoTotals) -> Markup>, RepoSort)> = vec![
("Name", Box::new(|x| html!(a href=(format!("/{}", x.name)) { (x.name) })), RepoSort::Name),
("Issues", Box::new(|x| html!((x.issues.separate_with_commas()))), RepoSort::Issues),
("PRs", Box::new(|x| html!((x.prs.separate_with_commas()))), RepoSort::Prs),
("Forks", Box::new(|x| html!((x.forks.separate_with_commas()))), RepoSort::Forks),
("Clones", Box::new(|x| html!((x.clones_count.separate_with_commas()))), RepoSort::Clones),
("Stars", Box::new(|x| html!((x.stars.separate_with_commas()))), RepoSort::Stars),
Expand Down

0 comments on commit 5ca9bf8

Please sign in to comment.