From 4402a44a78cd8d152c632325a8d5f5c3d59e0005 Mon Sep 17 00:00:00 2001
From: Julia Shtal
Date: Wed, 16 Sep 2026 14:11:36 +0200
Subject: [PATCH] refactor(github): replace the flat service package with
seven by concern
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
github/service held sixteen classes with no structure. They now sit in client,
repo, identity, commit, pullrequest, issue and scheduler.
commit and pullrequest are deliberately symmetrical — collector, ingest service,
stats enrichment service — so the two-phase pattern is visible in the tree rather
than only in Javadoc.
refreshReviews becomes public: the attribution backfill that calls it now lives
in a different package, which is the use its Javadoc already described.
No route changes: the sorted set of mapping literals hashes identically before
and after.
docs: update PROJECT_DESCRIPTION for the github package reorganisation
Four class names changed, one service was split out, and the flat service package
became seven. The document names each service, so it drifts the moment the code
moves.
---
PROJECT_DESCRIPTION.md | 47 ++++++++----
.../attribution/AttributionMigrationJob.java | 2 +-
.../collect/GitHubSourceCollector.java | 14 ++--
.../controller/DataSourceRepoController.java | 2 +-
.../datasource/service/DataSourceService.java | 2 +-
.../git/controller/RepoController.java | 6 +-
.../GitHubClientFactory.java | 2 +-
.../GitHubCommitCollector.java} | 4 +-
.../GitHubCommitIngestService.java | 3 +-
.../GitHubCommitStatsEnrichmentService.java | 2 +-
.../github/controller/GitHubController.java | 8 +-
.../GitHubPullRequestController.java | 8 +-
.../GitHubAccountLookup.java | 2 +-
.../GitHubAccountLookupImpl.java | 3 +-
.../GitHubIdentityBackfill.java | 2 +-
.../GitHubIdentityBackfillService.java | 7 +-
.../AsyncIssuesCollector.java} | 4 +-
.../GitHubIssuesCollector.java | 3 +-
.../GitHubPullRequestCollector.java} | 18 ++---
.../GitHubPullRequestIngestService.java} | 18 ++---
.../GitHubPullRequestQueryService.java | 32 ++++++++
...HubPullRequestStatsEnrichmentService.java} | 6 +-
.../GitHubRepositoryService.java | 3 +-
.../StatsEnrichmentScheduler.java | 7 +-
.../issue/controller/IssuesController.java | 2 +-
.../user/service/AuthorIdentityService.java | 2 +-
.../attribution/AttributionMigrationTest.java | 2 +-
.../DataSourceServiceAttachDetachTest.java | 2 +-
.../DataSourceServiceCoverageTest.java | 2 +-
.../datasource/DataSourceServiceTest.java | 2 +-
.../collect/GitHubSourceCollectorTest.java | 14 ++--
.../git/RepoTypeDiscriminatorTest.java | 2 +-
.../git/UserRepoRegistrationTest.java | 2 +-
.../GitHubClientFactoryTest.java | 2 +-
.../GitHubCommitCollectorTest.java} | 6 +-
.../GitHubCommitIngestServiceTest.java | 3 +-
...itHubCommitStatsEnrichmentServiceTest.java | 2 +-
.../GitHubAccountLookupImplTest.java | 3 +-
.../GitHubIdentityBackfillServiceTest.java | 7 +-
.../IdentityIngestMappingTest.java | 9 ++-
.../AsyncIssuesCollectorTest.java} | 6 +-
.../GitHubIssuesCollectorTest.java | 3 +-
.../ReviewAndIssueIdentityMappingTest.java | 8 +-
.../GitHubPullRequestCollectorTest.java} | 18 ++---
.../GitHubPullRequestIngestServiceTest.java} | 57 +++-----------
.../GitHubPullRequestQueryServiceTest.java | 74 +++++++++++++++++++
...ullRequestStatsEnrichmentServiceTest.java} | 8 +-
.../{ => repo}/GitHubRepoDiscoveryTest.java | 6 +-
.../GitHubRepositoryServiceRegisterTest.java | 6 +-
.../StatsEnrichmentSchedulerTest.java | 7 +-
.../user/AuthorIdentityServiceTest.java | 2 +-
51 files changed, 285 insertions(+), 177 deletions(-)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => client}/GitHubClientFactory.java (96%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service/GitHubCollector.java => commit/GitHubCommitCollector.java} (97%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => commit}/GitHubCommitIngestService.java (99%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => commit}/GitHubCommitStatsEnrichmentService.java (99%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => identity}/GitHubAccountLookup.java (96%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => identity}/GitHubAccountLookupImpl.java (97%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => identity}/GitHubIdentityBackfill.java (95%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => identity}/GitHubIdentityBackfillService.java (96%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service/AsyncIssuesCollectService.java => issue/AsyncIssuesCollector.java} (94%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => issue}/GitHubIssuesCollector.java (97%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service/GitHubPrCollector.java => pullrequest/GitHubPullRequestCollector.java} (82%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service/GitHubPullRequestCollector.java => pullrequest/GitHubPullRequestIngestService.java} (94%)
create mode 100644 dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestQueryService.java
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service/GitHubPrStatsEnrichmentService.java => pullrequest/GitHubPullRequestStatsEnrichmentService.java} (98%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => repo}/GitHubRepositoryService.java (98%)
rename dev-analytics/src/main/java/com/juliashtal/devanalytics/github/{service => scheduler}/StatsEnrichmentScheduler.java (90%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => client}/GitHubClientFactoryTest.java (98%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service/GitHubCollectorTest.java => commit/GitHubCommitCollectorTest.java} (97%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => commit}/GitHubCommitIngestServiceTest.java (99%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => commit}/GitHubCommitStatsEnrichmentServiceTest.java (99%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => identity}/GitHubAccountLookupImplTest.java (98%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => identity}/GitHubIdentityBackfillServiceTest.java (96%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => identity}/IdentityIngestMappingTest.java (95%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service/AsyncIssuesCollectServiceTest.java => issue/AsyncIssuesCollectorTest.java} (95%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => issue}/GitHubIssuesCollectorTest.java (99%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => issue}/ReviewAndIssueIdentityMappingTest.java (95%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service/GitHubPrCollectorTest.java => pullrequest/GitHubPullRequestCollectorTest.java} (87%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service/GitHubPullRequestCollectorTest.java => pullrequest/GitHubPullRequestIngestServiceTest.java} (86%)
create mode 100644 dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestQueryServiceTest.java
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service/GitHubPrStatsEnrichmentServiceTest.java => pullrequest/GitHubPullRequestStatsEnrichmentServiceTest.java} (98%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{ => repo}/GitHubRepoDiscoveryTest.java (97%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{ => repo}/GitHubRepositoryServiceRegisterTest.java (97%)
rename dev-analytics/src/test/java/com/juliashtal/devanalytics/github/{service => scheduler}/StatsEnrichmentSchedulerTest.java (95%)
diff --git a/PROJECT_DESCRIPTION.md b/PROJECT_DESCRIPTION.md
index 1ad9163..417f802 100644
--- a/PROJECT_DESCRIPTION.md
+++ b/PROJECT_DESCRIPTION.md
@@ -78,10 +78,11 @@ Strict **Controller → Service → Repository** layering. No controller accesse
│ AsyncDataSourceCollectService · SyncJobTracker │
│ GitLocalCollector · RepoService · GitRepositoryService │
│ GitHubClientFactory · GitHubRepositoryService │
-│ GitHubCollector · GitHubCommitIngestService │
+│ GitHubCommitCollector · GitHubCommitIngestService │
│ GitHubCommitStatsEnrichmentService │
-│ GitHubPrCollector · GitHubPullRequestCollector │
-│ GitHubPrStatsEnrichmentService · GitHubIssuesCollector │
+│ GitHubPullRequestCollector · GitHubPullRequestIngestService │
+│ GitHubPullRequestStatsEnrichmentService │
+│ GitHubPullRequestQueryService · GitHubIssuesCollector │
│ JiraCollector · IssueService │
│ MetricsService · MetricSnapshotService · MetricsScheduler │
│ MetricBackfillService · MetricBackfillScheduler │
@@ -121,6 +122,22 @@ Strict **Controller → Service → Repository** layering. No controller accesse
| `messaging/` | 1:1 direct message service and controller, conversation/inbox API |
| `invite/` | Token-based team invitation issuance and redemption |
+`github/` runs two collection pipelines, so it is split further. `controller/`, `model/` and
+`repository/` sit beside these.
+
+| Subpackage | Classes |
+|---|---|
+| `github/client/` | `GitHubClientFactory` |
+| `github/repo/` | `GitHubRepositoryService` |
+| `github/identity/` | `GitHubAccountLookup`, `GitHubAccountLookupImpl`, `GitHubIdentityBackfill`, `GitHubIdentityBackfillService` |
+| `github/commit/` | `GitHubCommitCollector`, `GitHubCommitIngestService`, `GitHubCommitStatsEnrichmentService` |
+| `github/pullrequest/` | `GitHubPullRequestCollector`, `GitHubPullRequestIngestService`, `GitHubPullRequestStatsEnrichmentService`, `GitHubPullRequestQueryService` |
+| `github/issue/` | `GitHubIssuesCollector`, `AsyncIssuesCollector` |
+| `github/scheduler/` | `StatsEnrichmentScheduler` |
+
+`commit/` and `pullrequest/` hold the same three roles — collector, ingest service, stats
+enrichment service — so the two-phase pattern is legible from the tree.
+
---
## 3. Backend — Domain Packages
@@ -430,7 +447,7 @@ CHECK constraints (added V35):
**`DataSourceCollectService`** — Dispatches to collectors based on `DataSourceType`. For GITHUB type it also conditionally collects issues per repo when `repo.isCollectIssues()` is true:
- `GIT_LOCAL` → `GitLocalCollector.collectForRepository()`
-- `GITHUB` → Phase 1: `GitHubCollector.collectForRepository()` (commits), Phase 2: `GitHubPrCollector.collectForRepository()` (PRs), Phase 3 (conditional): `GitHubIssuesCollector.collectIssuesForRepo()` if `repo.collectIssues`
+- `GITHUB` → Phase 1: `GitHubCommitCollector.collectForRepository()` (commits), Phase 2: `GitHubPullRequestCollector.collectForRepository()` (PRs), Phase 3 (conditional): `GitHubIssuesCollector.collectIssuesForRepo()` if `repo.collectIssues`
- `GITHUB_ISSUES` → `GitHubIssuesCollector.collectIssuesForRepo(cfg, repoFullName)` per repo
- `JIRA` → iterates `JiraProjectService.listTrackedProjects(cfg)`; calls `JiraCollector.collectIssues(project)` per project. Logs a warning if no tracked projects exist.
- Updates `lastSuccessSync` on success.
@@ -834,21 +851,23 @@ The datasource a subscription belongs to is derived via `repo_id → git_reposit
- `enrichSingle(entity, ...)` — `GET /repos/{owner}/{repo}/commits/{sha}`. On 200: applies `additions`/`deletions`/`filesChanged`, sets `COMPLETE`. On 403 diff-too-large: sets `SKIPPED`. On 404/422: sets `FAILED`. On 5xx: increments attempts, backs off.
- Rate limiting: synchronized token bucket on `MIN_INTERVAL_NS`; 100–300 ms jitter; proactive throttle when `X-RateLimit-Remaining < 100`; exponential backoff on error.
-**`GitHubCollector`** — Orchestrates commit collection:
+**`GitHubCommitCollector`** — Orchestrates commit collection:
1. `GitHubCommitIngestService.ingestForRepository()` (Phase A).
2. Sort saved by `authorDate` desc.
3. `GitHubCommitStatsEnrichmentService.enrichImmediate()` (Phase B — top 150).
4. Log remaining PENDING count (Phase C handled by scheduler).
-**`GitHubPrCollector`** — Orchestrates PR collection:
-1. `GitHubPullRequestCollector` (ingest): pages all PRs, upserts by `(repoId, number)`, saves with `statsStatus=PENDING`.
+**`GitHubPullRequestCollector`** — Orchestrates PR collection:
+1. `GitHubPullRequestIngestService` (ingest): pages all PRs, upserts by `(repoId, number)`, saves with `statsStatus=PENDING`.
2. Sort saved by `createdAt` desc.
-3. `GitHubPrStatsEnrichmentService.enrichImmediate()` (Phase B — top 150): fetches reviews (delete+save in `github_pr_reviews`) and detail stats per PR.
+3. `GitHubPullRequestStatsEnrichmentService.enrichImmediate()` (Phase B — top 150): fetches reviews (delete+save in `github_pr_reviews`) and detail stats per PR.
4. Phase C handled by scheduler.
-**`GitHubPullRequestCollector`** — Ingest-only service. Pages PRs from GitHub API, upserts into `github_pull_requests`. Also used by `GitHubPullRequestController` for paginated listing. Returns `IngestResult(savedEntities, apiBase, token)`.
+**`GitHubPullRequestIngestService`** — Ingest-only service. Pages PRs from GitHub API, upserts into `github_pull_requests`. Returns `IngestResult(savedEntities, apiBase, token)`.
+
+**`GitHubPullRequestQueryService`** — Read side for stored PRs. `listPullRequests(repoId, pageable)` — the paginated listing `GitHubPullRequestController` serves.
-**`GitHubPrStatsEnrichmentService`** — Enriches PR stats. Same rate-limit pattern as commit enrichment. `enrichSingle(pr, ...)` — `GET /repos/{owner}/{repo}/pulls/{number}` for additions/deletions/changedFiles/commitsCount; `GET .../reviews` for review list (delete+save all reviews then mark PR `COMPLETE`).
+**`GitHubPullRequestStatsEnrichmentService`** — Enriches PR stats. Same rate-limit pattern as commit enrichment. `enrichSingle(pr, ...)` — `GET /repos/{owner}/{repo}/pulls/{number}` for additions/deletions/changedFiles/commitsCount; `GET .../reviews` for review list (delete+save all reviews then mark PR `COMPLETE`).
**`GitHubIssuesCollector`** — Fetches all issues (open + closed) via Kohsuke API, maps to `IssueEntity` with `externalId = owner/repo#{number}`. Upserts by `(dataSourceId, externalId)`. Accepts either a `GitRepositoryEntity` or a bare `repoFullName` string.
@@ -1618,8 +1637,8 @@ POST /datasources/{id}/collect
│ └─▶ reads lastSuccessSync [before collection stamps it → "first run?"]
│ └─▶ DataSourceCollectService.collectForDataSource()
│ ├─ GIT_LOCAL → GitLocalCollector.collectForRepository()
- │ ├─ GITHUB → GitHubCollector.collectForRepository() [commits]
- │ │ GitHubPrCollector.collectForRepository() [PRs]
+ │ ├─ GITHUB → GitHubCommitCollector.collectForRepository() [commits]
+ │ │ GitHubPullRequestCollector.collectForRepository() [PRs]
│ │ GitHubIssuesCollector (if repo.collectIssues) [issues]
│ ├─ GITHUB_ISSUES → GitHubIssuesCollector.collectIssuesForRepo()
│ └─ JIRA → JiraCollector.collectIssues()
@@ -1633,14 +1652,14 @@ Client polls `GET /datasources/{id}/collect/status` every 3 seconds. `SyncJobTra
```
Phase A — Fast ingest (seconds)
- GitHubCommitIngestService / GitHubPullRequestCollector
+ GitHubCommitIngestService / GitHubPullRequestIngestService
→ pages all items from GitHub list endpoint (100/page)
→ saves with statsStatus=PENDING
→ returns List sorted newest-first
Phase B — Immediate enrich top 150 (seconds to minutes)
GitHubCommitStatsEnrichmentService.enrichImmediate() ← 2 worker threads
- GitHubPrStatsEnrichmentService.enrichImmediate()
+ GitHubPullRequestStatsEnrichmentService.enrichImmediate()
→ fetches detail/reviews per item, sets statsStatus=COMPLETE
→ rate-limited: ~1.4 req/s, proactive throttle on X-RateLimit-Remaining < 100
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/attribution/AttributionMigrationJob.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/attribution/AttributionMigrationJob.java
index e28eaab..4951171 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/attribution/AttributionMigrationJob.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/attribution/AttributionMigrationJob.java
@@ -2,7 +2,7 @@
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
-import com.juliashtal.devanalytics.github.service.GitHubIdentityBackfill;
+import com.juliashtal.devanalytics.github.identity.GitHubIdentityBackfill;
import com.juliashtal.devanalytics.jira.service.JiraIdentityBackfill;
import com.juliashtal.devanalytics.metrics.service.MetricBackfillTrigger;
import com.juliashtal.devanalytics.user.model.User;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/collect/GitHubSourceCollector.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/collect/GitHubSourceCollector.java
index 3ffff21..6e67c9d 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/collect/GitHubSourceCollector.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/collect/GitHubSourceCollector.java
@@ -5,10 +5,10 @@
import com.juliashtal.devanalytics.datasource.service.SyncJobTracker;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
-import com.juliashtal.devanalytics.github.service.GitHubAccountLookup;
-import com.juliashtal.devanalytics.github.service.GitHubCollector;
-import com.juliashtal.devanalytics.github.service.GitHubIssuesCollector;
-import com.juliashtal.devanalytics.github.service.GitHubPrCollector;
+import com.juliashtal.devanalytics.github.identity.GitHubAccountLookup;
+import com.juliashtal.devanalytics.github.commit.GitHubCommitCollector;
+import com.juliashtal.devanalytics.github.issue.GitHubIssuesCollector;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestCollector;
import com.juliashtal.devanalytics.user.service.AuthorIdentityService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -24,8 +24,8 @@
public class GitHubSourceCollector implements SourceCollector {
private final GitRepositoryEntityRepository gitRepoRepository;
- private final GitHubCollector gitHubCollector;
- private final GitHubPrCollector prCollector;
+ private final GitHubCommitCollector commitCollector;
+ private final GitHubPullRequestCollector prCollector;
private final GitHubIssuesCollector issuesCollector;
private final GitHubAccountLookup accountLookup;
private final AuthorIdentityService authorIdentityService;
@@ -51,7 +51,7 @@ public int collect(DataSourceConfig cfg, SyncJobTracker.JobState jobState) {
for (var repo : gitRepoRepository.findAllByDataSourceConfig(cfg)) {
try {
if (jobState != null) tracker.setPhase(jobState, "commits", -1);
- int commits = gitHubCollector.collectForRepository(repo.getId(), jobState);
+ int commits = commitCollector.collectForRepository(repo.getId(), jobState);
if (jobState != null) tracker.setPhase(jobState, "pull requests", -1);
int prs = prCollector.collectForRepository(repo.getId(), jobState);
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/controller/DataSourceRepoController.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/controller/DataSourceRepoController.java
index 42c4758..1083254 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/controller/DataSourceRepoController.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/controller/DataSourceRepoController.java
@@ -5,7 +5,7 @@
import com.juliashtal.devanalytics.git.model.dto.RepoDto;
import com.juliashtal.devanalytics.github.model.dto.DiscoveredRepoDto;
import com.juliashtal.devanalytics.github.model.dto.DiscoveryResult;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.security.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/service/DataSourceService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/service/DataSourceService.java
index 415dce4..dba22ad 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/service/DataSourceService.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/datasource/service/DataSourceService.java
@@ -16,7 +16,7 @@
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
import com.juliashtal.devanalytics.git.repository.UserRepoRegistrationRepository;
import com.juliashtal.devanalytics.git.service.GitRepositoryService;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.jira.service.JiraProjectService;
import com.juliashtal.devanalytics.user.model.Role;
import com.juliashtal.devanalytics.user.model.Team;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/git/controller/RepoController.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/git/controller/RepoController.java
index f8beb72..730d48f 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/git/controller/RepoController.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/git/controller/RepoController.java
@@ -2,7 +2,7 @@
import com.juliashtal.devanalytics.git.model.dto.RepoDto;
import com.juliashtal.devanalytics.git.service.RepoService;
-import com.juliashtal.devanalytics.github.service.AsyncIssuesCollectService;
+import com.juliashtal.devanalytics.github.issue.AsyncIssuesCollector;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
@@ -26,7 +26,7 @@
public class RepoController {
private final RepoService repoService;
- private final AsyncIssuesCollectService asyncIssuesCollectService;
+ private final AsyncIssuesCollector asyncIssuesCollector;
@Operation(summary = "List repos visible to the current user (own + team), with subscribed flag")
@GetMapping
@@ -58,6 +58,6 @@ public RepoDto setCollectIssues(
) {
boolean enabled = Boolean.TRUE.equals(body.get("enabled"));
return repoService.setCollectIssues(repoId, enabled,
- asyncIssuesCollectService::collectIssuesForRepo);
+ asyncIssuesCollector::collectIssuesForRepo);
}
}
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubClientFactory.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/client/GitHubClientFactory.java
similarity index 96%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubClientFactory.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/client/GitHubClientFactory.java
index 981516d..b06ff4a 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubClientFactory.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/client/GitHubClientFactory.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.client;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.exception.GitHubException;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCollector.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitCollector.java
similarity index 97%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCollector.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitCollector.java
index 76bcc33..0c28195 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCollector.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitCollector.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.commit;
import com.juliashtal.devanalytics.datasource.service.SyncJobTracker;
import com.juliashtal.devanalytics.git.model.GitCommitEntity;
@@ -35,7 +35,7 @@
@Service
@RequiredArgsConstructor
@Slf4j
-public class GitHubCollector {
+public class GitHubCommitCollector {
private final GitHubCommitIngestService ingestService;
private final GitHubCommitStatsEnrichmentService enrichmentService;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCommitIngestService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitIngestService.java
similarity index 99%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCommitIngestService.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitIngestService.java
index c124260..9e22eb5 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCommitIngestService.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitIngestService.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.commit;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -10,6 +10,7 @@
import com.juliashtal.devanalytics.git.model.StatsStatus;
import com.juliashtal.devanalytics.git.repository.GitCommitEntityRepository;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCommitStatsEnrichmentService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitStatsEnrichmentService.java
similarity index 99%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCommitStatsEnrichmentService.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitStatsEnrichmentService.java
index 48c8f0e..50de1ff 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubCommitStatsEnrichmentService.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/commit/GitHubCommitStatsEnrichmentService.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.commit;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/controller/GitHubController.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/controller/GitHubController.java
index 81e3889..08d1778 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/controller/GitHubController.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/controller/GitHubController.java
@@ -3,8 +3,8 @@
import com.juliashtal.devanalytics.git.model.dto.GitRepositoryDto;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.github.model.dto.RegisterGitHubRepoRequest;
-import com.juliashtal.devanalytics.github.service.GitHubCollector;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.commit.GitHubCommitCollector;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.security.SecurityUtils;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
@@ -23,7 +23,7 @@
public class GitHubController {
private final GitHubRepositoryService gitHubRepositoryService;
- private final GitHubCollector gitHubCollector;
+ private final GitHubCommitCollector commitCollector;
@Operation(summary = "Register a GitHub repository under a data source, reusing an existing entity if already registered")
@PostMapping("/repos")
@@ -40,7 +40,7 @@ public ResponseEntity registerRepo(@RequestBody RegisterGitHub
@Operation(summary = "Synchronously collect new commits for a GitHub repository")
@PostMapping("/repos/{repoId}/collect")
public ResponseEntity collect(@PathVariable Long repoId) {
- int saved = gitHubCollector.collectForRepository(repoId, null);
+ int saved = commitCollector.collectForRepository(repoId, null);
return ResponseEntity.ok("Collected " + saved + " commits from GitHub");
}
}
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/controller/GitHubPullRequestController.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/controller/GitHubPullRequestController.java
index b0bd8b2..ef6b64d 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/controller/GitHubPullRequestController.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/controller/GitHubPullRequestController.java
@@ -2,8 +2,8 @@
import com.juliashtal.devanalytics.github.model.dto.GitHubPullRequestDto;
-import com.juliashtal.devanalytics.github.service.GitHubPrCollector;
-import com.juliashtal.devanalytics.github.service.GitHubPullRequestCollector;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestCollector;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestQueryService;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
@@ -22,8 +22,8 @@
@RequiredArgsConstructor
public class GitHubPullRequestController {
- private final GitHubPrCollector prCollector;
- private final GitHubPullRequestCollector prQueryService;
+ private final GitHubPullRequestCollector prCollector;
+ private final GitHubPullRequestQueryService prQueryService;
@Operation(summary = "Synchronously collect new and updated pull requests for a GitHub repository")
@PostMapping("/repos/{repoId}/pull-requests/collect")
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookup.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookup.java
similarity index 96%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookup.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookup.java
index 7540bd5..181636b 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookup.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookup.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.identity;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookupImpl.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookupImpl.java
similarity index 97%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookupImpl.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookupImpl.java
index bb619d6..0051d52 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookupImpl.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookupImpl.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.identity;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -6,6 +6,7 @@
import com.juliashtal.devanalytics.datasource.model.DataSourceType;
import com.juliashtal.devanalytics.datasource.repository.DataSourceConfigRepository;
import com.juliashtal.devanalytics.exception.GitHubException;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfill.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfill.java
similarity index 95%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfill.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfill.java
index 7e9d6fb..bb6b240 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfill.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfill.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.identity;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfillService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfillService.java
similarity index 96%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfillService.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfillService.java
index c0ecd74..5fe3ed5 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfillService.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfillService.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.identity;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -7,7 +7,10 @@
import com.juliashtal.devanalytics.git.model.GitCommitEntity;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitCommitEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
+import com.juliashtal.devanalytics.github.issue.GitHubIssuesCollector;
import com.juliashtal.devanalytics.github.model.GitHubPullRequestEntity;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestStatsEnrichmentService;
import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -45,7 +48,7 @@ public class GitHubIdentityBackfillService implements GitHubIdentityBackfill {
private final GitCommitEntityRepository commitRepository;
private final GitHubPullRequestRepository prRepository;
- private final GitHubPrStatsEnrichmentService prEnrichmentService;
+ private final GitHubPullRequestStatsEnrichmentService prEnrichmentService;
private final GitHubIssuesCollector issuesCollector;
private final GitHubClientFactory clientFactory;
private final ObjectMapper objectMapper;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/AsyncIssuesCollectService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/issue/AsyncIssuesCollector.java
similarity index 94%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/AsyncIssuesCollectService.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/issue/AsyncIssuesCollector.java
index 6700f98..095c1c8 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/AsyncIssuesCollectService.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/issue/AsyncIssuesCollector.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.issue;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
@@ -16,7 +16,7 @@
@Service
@RequiredArgsConstructor
@Slf4j
-public class AsyncIssuesCollectService {
+public class AsyncIssuesCollector {
private final GitHubIssuesCollector issuesCollector;
private final GitRepositoryEntityRepository gitRepoRepository;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIssuesCollector.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/issue/GitHubIssuesCollector.java
similarity index 97%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIssuesCollector.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/issue/GitHubIssuesCollector.java
index e0cf064..39c06f8 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubIssuesCollector.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/issue/GitHubIssuesCollector.java
@@ -1,9 +1,10 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.issue;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.exception.GitHubException;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import com.juliashtal.devanalytics.issue.IssueRepository;
import com.juliashtal.devanalytics.issue.model.IssueEntity;
import com.juliashtal.devanalytics.issue.model.IssueSource;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPrCollector.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestCollector.java
similarity index 82%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPrCollector.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestCollector.java
index 17c2204..86cd0dd 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPrCollector.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestCollector.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.pullrequest;
import com.juliashtal.devanalytics.datasource.service.SyncJobTracker;
import com.juliashtal.devanalytics.git.model.StatsStatus;
@@ -12,16 +12,16 @@
/**
* Orchestrates two-phase GitHub PR collection for a single repository,
- * mirroring the commit collection design in {@link GitHubCollector}.
+ * mirroring the commit collection design in {@link GitHubCommitCollector}.
*
* Pipeline
*
- * - Phase A — ingest: {@link GitHubPullRequestCollector} pages through the
+ *
- Phase A — ingest: {@link GitHubPullRequestIngestService} pages through the
* GitHub PR list endpoint and saves new or changed PRs with
* {@code statsStatus=PENDING}. No review fetches or per-PR detail calls are made.
* Returns immediately after all pages are saved.
* - Phase B — immediate enrichment: the newest
- * {@value GitHubPrStatsEnrichmentService#IMMEDIATE_ENRICH_LIMIT} PENDING PRs are
+ * {@value GitHubPullRequestStatsEnrichmentService#IMMEDIATE_ENRICH_LIMIT} PENDING PRs are
* enriched synchronously (reviews + size stats) so dashboards reflect fresh data
* right away.
* - Phase C — background backfill: remaining PENDING PRs are handled by
@@ -34,10 +34,10 @@
@Service
@RequiredArgsConstructor
@Slf4j
-public class GitHubPrCollector {
+public class GitHubPullRequestCollector {
- private final GitHubPullRequestCollector ingestService;
- private final GitHubPrStatsEnrichmentService enrichmentService;
+ private final GitHubPullRequestIngestService ingestService;
+ private final GitHubPullRequestStatsEnrichmentService enrichmentService;
/**
* Runs the full two-phase collection for one repository.
@@ -46,7 +46,7 @@ public class GitHubPrCollector {
*/
public int collectForRepository(Long gitRepoId, SyncJobTracker.JobState jobState) {
// Phase A: fast ingest — saves all new/changed PRs as PENDING.
- GitHubPullRequestCollector.IngestResult ingest =
+ GitHubPullRequestIngestService.IngestResult ingest =
ingestService.collectPullRequests(gitRepoId, jobState);
List saved = ingest.savedEntities();
@@ -56,7 +56,7 @@ public int collectForRepository(Long gitRepoId, SyncJobTracker.JobState jobState
}
log.info("Ingested {} new/updated PRs for repo id={}, starting immediate enrichment of top {}",
- saved.size(), gitRepoId, GitHubPrStatsEnrichmentService.IMMEDIATE_ENRICH_LIMIT);
+ saved.size(), gitRepoId, GitHubPullRequestStatsEnrichmentService.IMMEDIATE_ENRICH_LIMIT);
// Phase B: immediate enrichment of the priority window — newest PRs first.
// Sort explicitly so the limit always picks the most recently created ones
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPullRequestCollector.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestIngestService.java
similarity index 94%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPullRequestCollector.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestIngestService.java
index 729c98f..a858215 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPullRequestCollector.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestIngestService.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.pullrequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -8,12 +8,11 @@
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.model.StatsStatus;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
import com.juliashtal.devanalytics.github.model.GitHubPullRequestEntity;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -34,12 +33,12 @@
import static com.juliashtal.devanalytics.helper.ParsingHelper.resolveApiBase;
/**
- * Queries stored pull requests and paginates the GitHub PR API.
+ * Paginates the GitHub PR API and stores the entries it returns.
*/
@Service
@RequiredArgsConstructor
@Slf4j
-public class GitHubPullRequestCollector {
+public class GitHubPullRequestIngestService {
private static final int BATCH_SIZE = 100;
private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
@@ -56,7 +55,7 @@ public class GitHubPullRequestCollector {
*
*
Pages through all PRs and saves new or changed ones with
* {@code statsStatus=PENDING}. No review fetches and no per-PR detail calls are
- * made here — that is the responsibility of {@link GitHubPrStatsEnrichmentService}.
+ * made here — that is the responsibility of {@link GitHubPullRequestStatsEnrichmentService}.
*
* Unchanged PRs (same {@code updated_at}) are skipped entirely, so incremental
* runs only write the rows that actually changed.
@@ -278,11 +277,4 @@ private int fetchTotalPrCount(String apiBase, String token, String repoFullName)
}
return -1;
}
-
- @Transactional(readOnly = true)
- public Page listPullRequests(Long repoId, Pageable pageable) {
- GitRepositoryEntity repo = repoRepository.findById(repoId)
- .orElseThrow(() -> new NoSuchElementException("Git repo not found: " + repoId));
- return prRepository.findByRepositoryOrderByCreatedAtDesc(repo, pageable);
- }
}
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestQueryService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestQueryService.java
new file mode 100644
index 0000000..4c40b12
--- /dev/null
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestQueryService.java
@@ -0,0 +1,32 @@
+package com.juliashtal.devanalytics.github.pullrequest;
+
+import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
+import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.model.GitHubPullRequestEntity;
+import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
+import lombok.RequiredArgsConstructor;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Read side for stored pull requests.
+ * Separate from ingestion so neither half carries the other's dependencies.
+ */
+@Service
+@RequiredArgsConstructor
+public class GitHubPullRequestQueryService {
+
+ private final GitRepositoryEntityRepository repoRepository;
+ private final GitHubPullRequestRepository prRepository;
+
+ @Transactional(readOnly = true)
+ public Page listPullRequests(Long repoId, Pageable pageable) {
+ GitRepositoryEntity repo = repoRepository.findById(repoId)
+ .orElseThrow(() -> new NoSuchElementException("Git repo not found: " + repoId));
+ return prRepository.findByRepositoryOrderByCreatedAtDesc(repo, pageable);
+ }
+}
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPrStatsEnrichmentService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestStatsEnrichmentService.java
similarity index 98%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPrStatsEnrichmentService.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestStatsEnrichmentService.java
index 9713647..06af0f3 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubPrStatsEnrichmentService.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestStatsEnrichmentService.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.pullrequest;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -59,7 +59,7 @@
@Service
@RequiredArgsConstructor
@Slf4j
-public class GitHubPrStatsEnrichmentService {
+public class GitHubPullRequestStatsEnrichmentService {
/** PRs enriched immediately after ingest (priority window — matches commit enricher). */
static final int IMMEDIATE_ENRICH_LIMIT = 150;
@@ -199,7 +199,7 @@ void enrichSingle(GitHubPullRequestEntity pr, String apiBase, String token, Stri
* Shared with {@link #enrichSingle}. Exposed so the attribution backfill can refresh
* reviews for a PR already {@code COMPLETE}, which enrichment never revisits.
*/
- void refreshReviews(GitHubPullRequestEntity pr, String apiBase, String token, String repoFullName)
+ public void refreshReviews(GitHubPullRequestEntity pr, String apiBase, String token, String repoFullName)
throws IOException, InterruptedException {
List reviews = fetchReviews(pr, apiBase, token, repoFullName);
reviewRepository.deleteAllByPullRequest(pr);
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubRepositoryService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/repo/GitHubRepositoryService.java
similarity index 98%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubRepositoryService.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/repo/GitHubRepositoryService.java
index 3aa0bc2..e7f0fad 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/GitHubRepositoryService.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/repo/GitHubRepositoryService.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.repo;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.datasource.model.DataSourceType;
@@ -12,6 +12,7 @@
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
import com.juliashtal.devanalytics.git.repository.UserRepoRegistrationRepository;
import com.juliashtal.devanalytics.datasource.repository.DataSourceConfigRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import com.juliashtal.devanalytics.github.model.dto.DiscoveredRepoDto;
import com.juliashtal.devanalytics.github.model.dto.DiscoveryResult;
import com.juliashtal.devanalytics.user.repository.UserRepository;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/StatsEnrichmentScheduler.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/scheduler/StatsEnrichmentScheduler.java
similarity index 90%
rename from dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/StatsEnrichmentScheduler.java
rename to dev-analytics/src/main/java/com/juliashtal/devanalytics/github/scheduler/StatsEnrichmentScheduler.java
index f9eb17e..6719579 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/service/StatsEnrichmentScheduler.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/github/scheduler/StatsEnrichmentScheduler.java
@@ -1,10 +1,13 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.scheduler;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.model.RepoType;
import com.juliashtal.devanalytics.git.model.StatsStatus;
import com.juliashtal.devanalytics.git.repository.GitCommitEntityRepository;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
+import com.juliashtal.devanalytics.github.commit.GitHubCommitStatsEnrichmentService;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestStatsEnrichmentService;
import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -40,7 +43,7 @@ public class StatsEnrichmentScheduler {
private final GitHubPullRequestRepository prRepository;
private final GitRepositoryEntityRepository repoRepository;
private final GitHubCommitStatsEnrichmentService commitEnrichmentService;
- private final GitHubPrStatsEnrichmentService prEnrichmentService;
+ private final GitHubPullRequestStatsEnrichmentService prEnrichmentService;
private final GitHubClientFactory clientFactory;
@Scheduled(fixedDelay = 120_000, initialDelay = 60_000)
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/issue/controller/IssuesController.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/issue/controller/IssuesController.java
index eee8749..026baaf 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/issue/controller/IssuesController.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/issue/controller/IssuesController.java
@@ -5,7 +5,7 @@
import com.juliashtal.devanalytics.datasource.service.DataSourceService;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.service.RepoService;
-import com.juliashtal.devanalytics.github.service.GitHubIssuesCollector;
+import com.juliashtal.devanalytics.github.issue.GitHubIssuesCollector;
import com.juliashtal.devanalytics.issue.model.IssueDto;
import com.juliashtal.devanalytics.issue.service.IssueService;
import com.juliashtal.devanalytics.jira.service.JiraCollector;
diff --git a/dev-analytics/src/main/java/com/juliashtal/devanalytics/user/service/AuthorIdentityService.java b/dev-analytics/src/main/java/com/juliashtal/devanalytics/user/service/AuthorIdentityService.java
index 8691818..818cb01 100644
--- a/dev-analytics/src/main/java/com/juliashtal/devanalytics/user/service/AuthorIdentityService.java
+++ b/dev-analytics/src/main/java/com/juliashtal/devanalytics/user/service/AuthorIdentityService.java
@@ -4,7 +4,7 @@
import com.juliashtal.devanalytics.exception.ConflictException;
import com.juliashtal.devanalytics.exception.NotFoundException;
import com.juliashtal.devanalytics.exception.UnprocessableEntityException;
-import com.juliashtal.devanalytics.github.service.GitHubAccountLookup;
+import com.juliashtal.devanalytics.github.identity.GitHubAccountLookup;
import com.juliashtal.devanalytics.user.model.AuthorIdentityChangedEvent;
import com.juliashtal.devanalytics.user.model.CommitEmailDto;
import com.juliashtal.devanalytics.user.model.User;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/attribution/AttributionMigrationTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/attribution/AttributionMigrationTest.java
index 06d627b..1da29eb 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/attribution/AttributionMigrationTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/attribution/AttributionMigrationTest.java
@@ -3,7 +3,7 @@
import com.juliashtal.devanalytics.exception.ConflictException;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
-import com.juliashtal.devanalytics.github.service.GitHubIdentityBackfill;
+import com.juliashtal.devanalytics.github.identity.GitHubIdentityBackfill;
import com.juliashtal.devanalytics.jira.service.JiraIdentityBackfill;
import com.juliashtal.devanalytics.metrics.service.MetricBackfillTrigger;
import com.juliashtal.devanalytics.user.model.User;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceAttachDetachTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceAttachDetachTest.java
index fa3d985..faac459 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceAttachDetachTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceAttachDetachTest.java
@@ -15,7 +15,7 @@
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
import com.juliashtal.devanalytics.git.repository.UserRepoRegistrationRepository;
import com.juliashtal.devanalytics.git.service.GitRepositoryService;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.jira.service.JiraProjectService;
import com.juliashtal.devanalytics.security.TokenEncryptor;
import com.juliashtal.devanalytics.user.model.User;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceCoverageTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceCoverageTest.java
index bdd1acd..547d81c 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceCoverageTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceCoverageTest.java
@@ -15,7 +15,7 @@
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
import com.juliashtal.devanalytics.git.repository.UserRepoRegistrationRepository;
import com.juliashtal.devanalytics.git.service.GitRepositoryService;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.jira.model.JiraProjectEntity;
import com.juliashtal.devanalytics.jira.service.JiraProjectService;
import com.juliashtal.devanalytics.security.SecurityUtils;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceTest.java
index e85da24..a8e25d0 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/DataSourceServiceTest.java
@@ -10,7 +10,7 @@
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
import com.juliashtal.devanalytics.git.repository.UserRepoRegistrationRepository;
import com.juliashtal.devanalytics.git.service.GitRepositoryService;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.jira.service.JiraProjectService;
import com.juliashtal.devanalytics.jira.model.JiraProjectEntity;
import com.juliashtal.devanalytics.security.TokenEncryptor;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/collect/GitHubSourceCollectorTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/collect/GitHubSourceCollectorTest.java
index 2612e1f..3ba337f 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/collect/GitHubSourceCollectorTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/datasource/collect/GitHubSourceCollectorTest.java
@@ -5,9 +5,9 @@
import com.juliashtal.devanalytics.datasource.service.SyncJobTracker;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
-import com.juliashtal.devanalytics.github.service.GitHubCollector;
-import com.juliashtal.devanalytics.github.service.GitHubIssuesCollector;
-import com.juliashtal.devanalytics.github.service.GitHubPrCollector;
+import com.juliashtal.devanalytics.github.commit.GitHubCommitCollector;
+import com.juliashtal.devanalytics.github.issue.GitHubIssuesCollector;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestCollector;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
@@ -27,8 +27,8 @@
class GitHubSourceCollectorTest {
@Mock GitRepositoryEntityRepository gitRepoRepository;
- @Mock GitHubCollector gitHubCollector;
- @Mock GitHubPrCollector prCollector;
+ @Mock GitHubCommitCollector commitCollector;
+ @Mock GitHubPullRequestCollector prCollector;
@Mock GitHubIssuesCollector issuesCollector;
@Mock SyncJobTracker tracker;
@@ -69,7 +69,7 @@ void collect_noIssues_collectsCommitsAndPrsOnly() {
DataSourceConfig cfg = new DataSourceConfig();
GitRepositoryEntity r = repo(10L, "owner/repo", false);
when(gitRepoRepository.findAllByDataSourceConfig(cfg)).thenReturn(List.of(r));
- when(gitHubCollector.collectForRepository(eq(10L), any())).thenReturn(3);
+ when(commitCollector.collectForRepository(eq(10L), any())).thenReturn(3);
when(prCollector.collectForRepository(eq(10L), any())).thenReturn(2);
SyncJobTracker.JobState js = new SyncJobTracker.JobState();
@@ -85,7 +85,7 @@ void collect_withIssues_collectsAllThree() {
DataSourceConfig cfg = new DataSourceConfig();
GitRepositoryEntity r = repo(11L, "owner/repo-issues", true);
when(gitRepoRepository.findAllByDataSourceConfig(cfg)).thenReturn(List.of(r));
- when(gitHubCollector.collectForRepository(eq(11L), any())).thenReturn(2);
+ when(commitCollector.collectForRepository(eq(11L), any())).thenReturn(2);
when(prCollector.collectForRepository(eq(11L), any())).thenReturn(1);
when(issuesCollector.collectIssuesForRepo(
any(DataSourceConfig.class), any(GitRepositoryEntity.class))).thenReturn(4);
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/git/RepoTypeDiscriminatorTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/git/RepoTypeDiscriminatorTest.java
index d68d412..eda4900 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/git/RepoTypeDiscriminatorTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/git/RepoTypeDiscriminatorTest.java
@@ -10,7 +10,7 @@
import com.juliashtal.devanalytics.git.repository.UserRepoRegistrationRepository;
import com.juliashtal.devanalytics.git.service.GitRepositoryService;
import com.juliashtal.devanalytics.git.model.dto.RegisterLocalRepoRequest;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.user.model.User;
import com.juliashtal.devanalytics.user.repository.UserRepository;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/git/UserRepoRegistrationTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/git/UserRepoRegistrationTest.java
index eac17ad..b7a3d18 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/git/UserRepoRegistrationTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/git/UserRepoRegistrationTest.java
@@ -33,7 +33,7 @@ class UserRepoRegistrationTest {
JiraProjectService jiraProjectService;
@Mock com.juliashtal.devanalytics.datasource.service.DataSourceValidator validator;
@Mock com.juliashtal.devanalytics.git.service.GitRepositoryService gitRepositoryService;
- @Mock com.juliashtal.devanalytics.github.service.GitHubRepositoryService gitHubRepositoryService;
+ @Mock com.juliashtal.devanalytics.github.repo.GitHubRepositoryService gitHubRepositoryService;
@Mock com.juliashtal.devanalytics.security.TokenEncryptor tokenEncryptor;
@InjectMocks DataSourceService dataSourceService;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubClientFactoryTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/client/GitHubClientFactoryTest.java
similarity index 98%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubClientFactoryTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/client/GitHubClientFactoryTest.java
index 7506ee7..917e5da 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubClientFactoryTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/client/GitHubClientFactoryTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.client;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.exception.GitHubException;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCollectorTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitCollectorTest.java
similarity index 97%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCollectorTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitCollectorTest.java
index 11aecd1..e33e082 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCollectorTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitCollectorTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.commit;
import com.juliashtal.devanalytics.git.model.GitCommitEntity;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
@@ -19,13 +19,13 @@
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
-class GitHubCollectorTest {
+class GitHubCommitCollectorTest {
@Mock GitHubCommitIngestService ingestService;
@Mock GitHubCommitStatsEnrichmentService enrichmentService;
@InjectMocks
- GitHubCollector collector;
+ GitHubCommitCollector collector;
private GitCommitEntity commit(Instant date, StatsStatus status, String repoFullName) {
GitRepositoryEntity repo = new GitRepositoryEntity();
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCommitIngestServiceTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitIngestServiceTest.java
similarity index 99%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCommitIngestServiceTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitIngestServiceTest.java
index 647d887..48db015 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCommitIngestServiceTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitIngestServiceTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.commit;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
@@ -11,6 +11,7 @@
import com.juliashtal.devanalytics.git.model.StatsStatus;
import com.juliashtal.devanalytics.git.repository.GitCommitEntityRepository;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCommitStatsEnrichmentServiceTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitStatsEnrichmentServiceTest.java
similarity index 99%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCommitStatsEnrichmentServiceTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitStatsEnrichmentServiceTest.java
index 5d03cf7..d1fe6ac 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubCommitStatsEnrichmentServiceTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/commit/GitHubCommitStatsEnrichmentServiceTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.commit;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookupImplTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookupImplTest.java
similarity index 98%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookupImplTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookupImplTest.java
index 6a81844..6f378ad 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubAccountLookupImplTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/GitHubAccountLookupImplTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.identity;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
@@ -7,6 +7,7 @@
import com.juliashtal.devanalytics.datasource.model.DataSourceType;
import com.juliashtal.devanalytics.datasource.repository.DataSourceConfigRepository;
import com.juliashtal.devanalytics.exception.GitHubException;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfillServiceTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfillServiceTest.java
similarity index 96%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfillServiceTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfillServiceTest.java
index b4c4663..7cb546c 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubIdentityBackfillServiceTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/GitHubIdentityBackfillServiceTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.identity;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
@@ -8,7 +8,10 @@
import com.juliashtal.devanalytics.git.model.GitCommitEntity;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitCommitEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
+import com.juliashtal.devanalytics.github.issue.GitHubIssuesCollector;
import com.juliashtal.devanalytics.github.model.GitHubPullRequestEntity;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestStatsEnrichmentService;
import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -43,7 +46,7 @@ class GitHubIdentityBackfillServiceTest {
@Mock GitCommitEntityRepository commitRepository;
@Mock GitHubPullRequestRepository prRepository;
- @Mock GitHubPrStatsEnrichmentService prEnrichmentService;
+ @Mock GitHubPullRequestStatsEnrichmentService prEnrichmentService;
@Mock GitHubIssuesCollector issuesCollector;
@Mock GitHubClientFactory clientFactory;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/IdentityIngestMappingTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/IdentityIngestMappingTest.java
similarity index 95%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/IdentityIngestMappingTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/IdentityIngestMappingTest.java
index 5b846db..57ede6d 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/IdentityIngestMappingTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/identity/IdentityIngestMappingTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.identity;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
@@ -8,7 +8,10 @@
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitCommitEntityRepository;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
+import com.juliashtal.devanalytics.github.commit.GitHubCommitIngestService;
import com.juliashtal.devanalytics.github.model.GitHubPullRequestEntity;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestIngestService;
import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -43,14 +46,14 @@ class IdentityIngestMappingTest {
@Mock GitHubClientFactory clientFactory;
GitHubCommitIngestService commitIngest;
- GitHubPullRequestCollector prCollector;
+ GitHubPullRequestIngestService prCollector;
String wmBaseUrl;
@BeforeEach
void setUp(WireMockRuntimeInfo wm) {
wmBaseUrl = wm.getHttpBaseUrl();
commitIngest = new GitHubCommitIngestService(repoRepository, commitRepository, clientFactory, new ObjectMapper());
- prCollector = new GitHubPullRequestCollector(repoRepository, prRepository, clientFactory, new ObjectMapper());
+ prCollector = new GitHubPullRequestIngestService(repoRepository, prRepository, clientFactory, new ObjectMapper());
}
private GitRepositoryEntity repo() {
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/AsyncIssuesCollectServiceTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/AsyncIssuesCollectorTest.java
similarity index 95%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/AsyncIssuesCollectServiceTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/AsyncIssuesCollectorTest.java
index 169534a..d190c25 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/AsyncIssuesCollectServiceTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/AsyncIssuesCollectorTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.issue;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
@@ -14,13 +14,13 @@
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
-class AsyncIssuesCollectServiceTest {
+class AsyncIssuesCollectorTest {
@Mock GitHubIssuesCollector issuesCollector;
@Mock GitRepositoryEntityRepository gitRepoRepository;
@InjectMocks
- AsyncIssuesCollectService service;
+ AsyncIssuesCollector service;
// ── repo not found → warns and returns without calling collector ─────────
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubIssuesCollectorTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/GitHubIssuesCollectorTest.java
similarity index 99%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubIssuesCollectorTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/GitHubIssuesCollectorTest.java
index da3560a..999a1a6 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubIssuesCollectorTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/GitHubIssuesCollectorTest.java
@@ -1,9 +1,10 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.issue;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.exception.GitHubException;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import com.juliashtal.devanalytics.issue.IssueRepository;
import com.juliashtal.devanalytics.issue.model.IssueEntity;
import com.juliashtal.devanalytics.issue.model.IssueSource;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/ReviewAndIssueIdentityMappingTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/ReviewAndIssueIdentityMappingTest.java
similarity index 95%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/ReviewAndIssueIdentityMappingTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/ReviewAndIssueIdentityMappingTest.java
index 457a985..9c6e4d7 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/ReviewAndIssueIdentityMappingTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/issue/ReviewAndIssueIdentityMappingTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.issue;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
@@ -6,8 +6,10 @@
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import com.juliashtal.devanalytics.github.model.GitHubPrReviewEntity;
import com.juliashtal.devanalytics.github.model.GitHubPullRequestEntity;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestStatsEnrichmentService;
import com.juliashtal.devanalytics.github.repository.GitHubPrReviewRepository;
import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
import com.juliashtal.devanalytics.issue.IssueRepository;
@@ -51,14 +53,14 @@ class ReviewAndIssueIdentityMappingTest {
@Mock IssueRepository issueRepository;
@Mock GitRepositoryEntityRepository gitRepositoryEntityRepository;
- GitHubPrStatsEnrichmentService enrichment;
+ GitHubPullRequestStatsEnrichmentService enrichment;
GitHubIssuesCollector issuesCollector;
String wmBaseUrl;
@BeforeEach
void setUp(WireMockRuntimeInfo wm) {
wmBaseUrl = wm.getHttpBaseUrl();
- enrichment = new GitHubPrStatsEnrichmentService(prRepository, reviewRepository, new ObjectMapper());
+ enrichment = new GitHubPullRequestStatsEnrichmentService(prRepository, reviewRepository, new ObjectMapper());
issuesCollector = new GitHubIssuesCollector(clientFactory, issueRepository, gitRepositoryEntityRepository);
}
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPrCollectorTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestCollectorTest.java
similarity index 87%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPrCollectorTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestCollectorTest.java
index a02f63b..99e1ab1 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPrCollectorTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestCollectorTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.pullrequest;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.model.StatsStatus;
@@ -19,13 +19,13 @@
import static org.mockito.Mockito.*;
@ExtendWith(MockitoExtension.class)
-class GitHubPrCollectorTest {
+class GitHubPullRequestCollectorTest {
- @Mock GitHubPullRequestCollector ingestService;
- @Mock GitHubPrStatsEnrichmentService enrichmentService;
+ @Mock GitHubPullRequestIngestService ingestService;
+ @Mock GitHubPullRequestStatsEnrichmentService enrichmentService;
@InjectMocks
- GitHubPrCollector collector;
+ GitHubPullRequestCollector collector;
private GitHubPullRequestEntity pr(Instant createdAt, StatsStatus status, String repoFullName) {
GitRepositoryEntity repo = new GitRepositoryEntity();
@@ -44,7 +44,7 @@ private GitHubPullRequestEntity pr(Instant createdAt, StatsStatus status, String
@Test
void collectForRepository_emptyIngestResult_returnsZero() {
when(ingestService.collectPullRequests(eq(1L), any()))
- .thenReturn(new GitHubPullRequestCollector.IngestResult(
+ .thenReturn(new GitHubPullRequestIngestService.IngestResult(
new ArrayList<>(), "https://api.github.com", "token"));
int result = collector.collectForRepository(1L, null);
@@ -63,7 +63,7 @@ void collectForRepository_withNewPrs_enrichesAndReturnsCount() {
StatsStatus.PENDING, "owner/repo");
when(ingestService.collectPullRequests(eq(1L), any()))
- .thenReturn(new GitHubPullRequestCollector.IngestResult(
+ .thenReturn(new GitHubPullRequestIngestService.IngestResult(
new ArrayList<>(List.of(p1, p2)), "https://api.github.com", "token"));
int result = collector.collectForRepository(1L, null);
@@ -84,7 +84,7 @@ void collectForRepository_pendingRemainsAfterEnrichment_returnsTotalCount() {
StatsStatus.PENDING, "owner/repo");
when(ingestService.collectPullRequests(eq(2L), any()))
- .thenReturn(new GitHubPullRequestCollector.IngestResult(
+ .thenReturn(new GitHubPullRequestIngestService.IngestResult(
new ArrayList<>(List.of(p)), "https://api.github.com", "token"));
int result = collector.collectForRepository(2L, null);
@@ -106,7 +106,7 @@ void collectForRepository_noRepoFullName_usesNameForEnrichment() {
p.setRepository(repo);
when(ingestService.collectPullRequests(eq(3L), any()))
- .thenReturn(new GitHubPullRequestCollector.IngestResult(
+ .thenReturn(new GitHubPullRequestIngestService.IngestResult(
new ArrayList<>(List.of(p)), "https://api.github.com", "token"));
collector.collectForRepository(3L, null);
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPullRequestCollectorTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestIngestServiceTest.java
similarity index 86%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPullRequestCollectorTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestIngestServiceTest.java
index f9ca512..a400d82 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPullRequestCollectorTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestIngestServiceTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.pullrequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
@@ -9,6 +9,7 @@
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
import com.juliashtal.devanalytics.git.model.StatsStatus;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
import com.juliashtal.devanalytics.github.model.GitHubPullRequestEntity;
import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
import org.junit.jupiter.api.BeforeEach;
@@ -16,9 +17,6 @@
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.PageImpl;
-import org.springframework.data.domain.PageRequest;
import java.time.Instant;
import java.util.List;
@@ -33,19 +31,19 @@
@ExtendWith(MockitoExtension.class)
@WireMockTest
-class GitHubPullRequestCollectorTest {
+class GitHubPullRequestIngestServiceTest {
@Mock GitRepositoryEntityRepository repoRepository;
@Mock GitHubPullRequestRepository prRepository;
@Mock GitHubClientFactory clientFactory;
- GitHubPullRequestCollector service;
+ GitHubPullRequestIngestService service;
String wmBaseUrl;
DataSourceConfig cfg;
@BeforeEach
void setUp(WireMockRuntimeInfo wm) {
- service = new GitHubPullRequestCollector(repoRepository, prRepository, clientFactory, new ObjectMapper());
+ service = new GitHubPullRequestIngestService(repoRepository, prRepository, clientFactory, new ObjectMapper());
wmBaseUrl = wm.getHttpBaseUrl();
cfg = new DataSourceConfig();
cfg.setId(1L);
@@ -85,7 +83,7 @@ void collectPullRequests_emptyList_returnsEmptyResult() {
.willReturn(aResponse().withStatus(200).withBody("[]")
.withHeader("Content-Type", "application/json")));
- GitHubPullRequestCollector.IngestResult result = service.collectPullRequests(10L, null);
+ GitHubPullRequestIngestService.IngestResult result = service.collectPullRequests(10L, null);
assertThat(result.savedEntities()).isEmpty();
verify(repoRepository).save(repo);
@@ -112,7 +110,7 @@ void collectPullRequests_newPr_savedAsPendingWithFields() {
.willReturn(aResponse().withStatus(200).withBody(body)
.withHeader("Content-Type", "application/json")));
- GitHubPullRequestCollector.IngestResult result = service.collectPullRequests(10L, null);
+ GitHubPullRequestIngestService.IngestResult result = service.collectPullRequests(10L, null);
assertThat(result.savedEntities()).hasSize(1);
GitHubPullRequestEntity pr = result.savedEntities().get(0);
@@ -146,7 +144,7 @@ void collectPullRequests_mergedPr_calculatesLeadTimeHours() {
.willReturn(aResponse().withStatus(200).withBody(body)
.withHeader("Content-Type", "application/json")));
- GitHubPullRequestCollector.IngestResult result = service.collectPullRequests(10L, null);
+ GitHubPullRequestIngestService.IngestResult result = service.collectPullRequests(10L, null);
GitHubPullRequestEntity pr = result.savedEntities().get(0);
assertThat(pr.getLeadTimeHours()).isEqualTo(48L);
@@ -178,7 +176,7 @@ void collectPullRequests_unchangedPr_skipsAndDoesNotSave() {
.willReturn(aResponse().withStatus(200).withBody(body)
.withHeader("Content-Type", "application/json")));
- GitHubPullRequestCollector.IngestResult result = service.collectPullRequests(10L, null);
+ GitHubPullRequestIngestService.IngestResult result = service.collectPullRequests(10L, null);
assertThat(result.savedEntities()).isEmpty();
verify(prRepository, never()).saveAll(any());
@@ -213,7 +211,7 @@ void collectPullRequests_updatedOpenPr_resetsStatsToPending() {
.willReturn(aResponse().withStatus(200).withBody(body)
.withHeader("Content-Type", "application/json")));
- GitHubPullRequestCollector.IngestResult result = service.collectPullRequests(10L, null);
+ GitHubPullRequestIngestService.IngestResult result = service.collectPullRequests(10L, null);
assertThat(result.savedEntities()).hasSize(1);
GitHubPullRequestEntity pr = result.savedEntities().get(0);
@@ -250,7 +248,7 @@ void collectPullRequests_updatedMergedCompletePr_preservesStats() {
.willReturn(aResponse().withStatus(200).withBody(body)
.withHeader("Content-Type", "application/json")));
- GitHubPullRequestCollector.IngestResult result = service.collectPullRequests(10L, null);
+ GitHubPullRequestIngestService.IngestResult result = service.collectPullRequests(10L, null);
assertThat(result.savedEntities()).hasSize(1);
GitHubPullRequestEntity pr = result.savedEntities().get(0);
@@ -332,39 +330,8 @@ void collectPullRequests_multiplePages_collectsAllPrs() {
.willReturn(aResponse().withStatus(200).withBody(page2)
.withHeader("Content-Type", "application/json")));
- GitHubPullRequestCollector.IngestResult result = service.collectPullRequests(10L, null);
+ GitHubPullRequestIngestService.IngestResult result = service.collectPullRequests(10L, null);
assertThat(result.savedEntities()).hasSize(2);
}
-
- // ── listPullRequests: delegates to repository ───────────────────────────
-
- @Test
- void listPullRequests_repoFound_returnsPage() {
- GitRepositoryEntity repo = repo();
- when(repoRepository.findById(10L)).thenReturn(Optional.of(repo));
-
- GitHubPullRequestEntity pr = new GitHubPullRequestEntity();
- pr.setNumber(1);
- Page page =
- new PageImpl<>(List.of(pr), PageRequest.of(0, 20), 1);
- when(prRepository.findByRepositoryOrderByCreatedAtDesc(repo, PageRequest.of(0, 20)))
- .thenReturn(page);
-
- Page result =
- service.listPullRequests(10L, PageRequest.of(0, 20));
-
- assertThat(result.getContent()).hasSize(1);
- assertThat(result.getContent().get(0).getNumber()).isEqualTo(1);
- }
-
- // ── listPullRequests: repo not found ────────────────────────────────────
-
- @Test
- void listPullRequests_repoNotFound_throwsNoSuchElement() {
- when(repoRepository.findById(99L)).thenReturn(Optional.empty());
-
- assertThatThrownBy(() -> service.listPullRequests(99L, PageRequest.of(0, 20)))
- .isInstanceOf(NoSuchElementException.class);
- }
}
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestQueryServiceTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestQueryServiceTest.java
new file mode 100644
index 0000000..211a241
--- /dev/null
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestQueryServiceTest.java
@@ -0,0 +1,74 @@
+package com.juliashtal.devanalytics.github.pullrequest;
+
+import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
+import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.model.GitHubPullRequestEntity;
+import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.PageRequest;
+
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Optional;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.when;
+
+/**
+ * Pins the read side: a known repository returns its stored pull requests newest-first,
+ * and an unknown one is rejected rather than returning an empty page.
+ */
+@ExtendWith(MockitoExtension.class)
+class GitHubPullRequestQueryServiceTest {
+
+ @Mock GitRepositoryEntityRepository repoRepository;
+ @Mock GitHubPullRequestRepository prRepository;
+
+ GitHubPullRequestQueryService service;
+
+ @BeforeEach
+ void setUp() {
+ service = new GitHubPullRequestQueryService(repoRepository, prRepository);
+ }
+
+ /** Only identity matters here — the query path reads no other field. */
+ private GitRepositoryEntity repo() {
+ GitRepositoryEntity r = new GitRepositoryEntity();
+ r.setId(10L);
+ return r;
+ }
+
+ @Test
+ void listPullRequests_repoFound_returnsPage() {
+ GitRepositoryEntity repo = repo();
+ when(repoRepository.findById(10L)).thenReturn(Optional.of(repo));
+
+ GitHubPullRequestEntity pr = new GitHubPullRequestEntity();
+ pr.setNumber(1);
+ Page page =
+ new PageImpl<>(List.of(pr), PageRequest.of(0, 20), 1);
+ when(prRepository.findByRepositoryOrderByCreatedAtDesc(repo, PageRequest.of(0, 20)))
+ .thenReturn(page);
+
+ Page result =
+ service.listPullRequests(10L, PageRequest.of(0, 20));
+
+ assertThat(result.getContent()).hasSize(1);
+ assertThat(result.getContent().get(0).getNumber()).isEqualTo(1);
+ }
+
+ @Test
+ void listPullRequests_repoNotFound_throwsNoSuchElement() {
+ when(repoRepository.findById(99L)).thenReturn(Optional.empty());
+
+ assertThatThrownBy(() -> service.listPullRequests(99L, PageRequest.of(0, 20)))
+ .isInstanceOf(NoSuchElementException.class);
+ }
+}
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPrStatsEnrichmentServiceTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestStatsEnrichmentServiceTest.java
similarity index 98%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPrStatsEnrichmentServiceTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestStatsEnrichmentServiceTest.java
index 45089ba..e26f2d9 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/GitHubPrStatsEnrichmentServiceTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/pullrequest/GitHubPullRequestStatsEnrichmentServiceTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.pullrequest;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.tomakehurst.wiremock.junit5.WireMockRuntimeInfo;
@@ -27,19 +27,19 @@
@ExtendWith(MockitoExtension.class)
@WireMockTest
-class GitHubPrStatsEnrichmentServiceTest {
+class GitHubPullRequestStatsEnrichmentServiceTest {
@Mock GitHubPullRequestRepository prRepository;
@Mock GitHubPrReviewRepository reviewRepository;
- GitHubPrStatsEnrichmentService service;
+ GitHubPullRequestStatsEnrichmentService service;
String wmBaseUrl;
private static final String REPO_NAME = "owner/test-repo";
@BeforeEach
void setUp(WireMockRuntimeInfo wm) {
- service = new GitHubPrStatsEnrichmentService(prRepository, reviewRepository, new ObjectMapper());
+ service = new GitHubPullRequestStatsEnrichmentService(prRepository, reviewRepository, new ObjectMapper());
wmBaseUrl = wm.getHttpBaseUrl();
}
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/GitHubRepoDiscoveryTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/repo/GitHubRepoDiscoveryTest.java
similarity index 97%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/GitHubRepoDiscoveryTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/repo/GitHubRepoDiscoveryTest.java
index 3ae0853..c9c8910 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/GitHubRepoDiscoveryTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/repo/GitHubRepoDiscoveryTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github;
+package com.juliashtal.devanalytics.github.repo;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.datasource.model.DataSourceType;
@@ -11,8 +11,8 @@
import com.juliashtal.devanalytics.git.repository.UserRepoRegistrationRepository;
import com.juliashtal.devanalytics.github.model.dto.DiscoveredRepoDto;
import com.juliashtal.devanalytics.github.model.dto.DiscoveryResult;
-import com.juliashtal.devanalytics.github.service.GitHubClientFactory;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.user.model.User;
import com.juliashtal.devanalytics.user.repository.UserRepository;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/GitHubRepositoryServiceRegisterTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/repo/GitHubRepositoryServiceRegisterTest.java
similarity index 97%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/GitHubRepositoryServiceRegisterTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/repo/GitHubRepositoryServiceRegisterTest.java
index 4fd43e1..62b9dd4 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/GitHubRepositoryServiceRegisterTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/repo/GitHubRepositoryServiceRegisterTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github;
+package com.juliashtal.devanalytics.github.repo;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.datasource.model.DataSourceType;
@@ -8,8 +8,8 @@
import com.juliashtal.devanalytics.git.model.UserRepoRegistration;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
import com.juliashtal.devanalytics.git.repository.UserRepoRegistrationRepository;
-import com.juliashtal.devanalytics.github.service.GitHubClientFactory;
-import com.juliashtal.devanalytics.github.service.GitHubRepositoryService;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
+import com.juliashtal.devanalytics.github.repo.GitHubRepositoryService;
import com.juliashtal.devanalytics.user.model.User;
import com.juliashtal.devanalytics.user.repository.UserRepository;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/StatsEnrichmentSchedulerTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/scheduler/StatsEnrichmentSchedulerTest.java
similarity index 95%
rename from dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/StatsEnrichmentSchedulerTest.java
rename to dev-analytics/src/test/java/com/juliashtal/devanalytics/github/scheduler/StatsEnrichmentSchedulerTest.java
index ad40897..9db4698 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/service/StatsEnrichmentSchedulerTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/github/scheduler/StatsEnrichmentSchedulerTest.java
@@ -1,4 +1,4 @@
-package com.juliashtal.devanalytics.github.service;
+package com.juliashtal.devanalytics.github.scheduler;
import com.juliashtal.devanalytics.datasource.model.DataSourceConfig;
import com.juliashtal.devanalytics.git.model.GitRepositoryEntity;
@@ -6,6 +6,9 @@
import com.juliashtal.devanalytics.git.model.StatsStatus;
import com.juliashtal.devanalytics.git.repository.GitCommitEntityRepository;
import com.juliashtal.devanalytics.git.repository.GitRepositoryEntityRepository;
+import com.juliashtal.devanalytics.github.client.GitHubClientFactory;
+import com.juliashtal.devanalytics.github.commit.GitHubCommitStatsEnrichmentService;
+import com.juliashtal.devanalytics.github.pullrequest.GitHubPullRequestStatsEnrichmentService;
import com.juliashtal.devanalytics.github.repository.GitHubPullRequestRepository;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -27,7 +30,7 @@ class StatsEnrichmentSchedulerTest {
@Mock GitHubPullRequestRepository prRepository;
@Mock GitRepositoryEntityRepository repoRepository;
@Mock GitHubCommitStatsEnrichmentService commitEnrichmentService;
- @Mock GitHubPrStatsEnrichmentService prEnrichmentService;
+ @Mock GitHubPullRequestStatsEnrichmentService prEnrichmentService;
@Mock GitHubClientFactory clientFactory;
@InjectMocks
diff --git a/dev-analytics/src/test/java/com/juliashtal/devanalytics/user/AuthorIdentityServiceTest.java b/dev-analytics/src/test/java/com/juliashtal/devanalytics/user/AuthorIdentityServiceTest.java
index 79a0afc..a617381 100644
--- a/dev-analytics/src/test/java/com/juliashtal/devanalytics/user/AuthorIdentityServiceTest.java
+++ b/dev-analytics/src/test/java/com/juliashtal/devanalytics/user/AuthorIdentityServiceTest.java
@@ -3,7 +3,7 @@
import com.juliashtal.devanalytics.exception.BadRequestException;
import com.juliashtal.devanalytics.exception.ConflictException;
import com.juliashtal.devanalytics.exception.UnprocessableEntityException;
-import com.juliashtal.devanalytics.github.service.GitHubAccountLookup;
+import com.juliashtal.devanalytics.github.identity.GitHubAccountLookup;
import com.juliashtal.devanalytics.user.model.AuthorIdentityChangedEvent;
import com.juliashtal.devanalytics.user.model.User;
import com.juliashtal.devanalytics.user.model.UserCommitEmail;