|
| 1 | +import dataclasses |
1 | 2 | from dataclasses import dataclass |
| 3 | +from datetime import datetime, timezone |
2 | 4 |
|
| 5 | +from sqlalchemy import insert |
| 6 | + |
| 7 | +from athenian.api.db import DatabaseLike |
3 | 8 | from athenian.api.internal.features.entries import MinePullRequestMetrics |
4 | 9 | from athenian.api.internal.miners.github.branches import BranchMinerMetrics |
5 | 10 | from athenian.api.internal.miners.github.deployment import MineDeploymentsMetrics |
6 | 11 | from athenian.api.internal.miners.github.release_load import MineReleaseMetrics |
7 | 12 | from athenian.api.internal.reposet import RepositorySetMetrics |
| 13 | +from athenian.api.models.persistentdata.models import HealthMetric |
8 | 14 |
|
9 | 15 |
|
10 | 16 | @dataclass(frozen=True, slots=True) |
11 | 17 | class DataHealthMetrics: |
12 | 18 | """Collection of data error statistics to report.""" |
13 | 19 |
|
14 | | - branches: BranchMinerMetrics |
15 | | - deployments: MineDeploymentsMetrics |
16 | | - prs: MinePullRequestMetrics |
17 | | - releases: MineReleaseMetrics |
18 | | - reposet: RepositorySetMetrics |
| 20 | + branches: BranchMinerMetrics | None |
| 21 | + deployments: MineDeploymentsMetrics | None |
| 22 | + prs: MinePullRequestMetrics | None |
| 23 | + releases: MineReleaseMetrics | None |
| 24 | + reposet: RepositorySetMetrics | None |
19 | 25 |
|
20 | 26 | @classmethod |
21 | 27 | def empty(cls) -> "DataHealthMetrics": |
22 | 28 | """Initialize a new DataHealthMetrics instance filled with zeros.""" |
23 | | - return DataHealthMetrics(**{k: v.empty() for k, v in cls.__annotations__.items()}) |
| 29 | + return DataHealthMetrics( |
| 30 | + **{f.name: f.type.__args__[0].empty() for f in dataclasses.fields(cls)}, |
| 31 | + ) |
| 32 | + |
| 33 | + @classmethod |
| 34 | + def skip(cls) -> "DataHealthMetrics": |
| 35 | + """Initialize a new DataHealthMetrics instance filled with None-s, effectively disabling \ |
| 36 | + the feature.""" |
| 37 | + return DataHealthMetrics(**{f.name: None for f in dataclasses.fields(cls)}) |
| 38 | + |
| 39 | + async def persist(self, account: int, rdb: DatabaseLike) -> None: |
| 40 | + """Insert all the measured metrics to the database.""" |
| 41 | + now = datetime.now(timezone.utc) |
| 42 | + values = [] |
| 43 | + for f in dataclasses.fields(self): |
| 44 | + v = getattr(self, f.name) |
| 45 | + for m in v.as_db(): |
| 46 | + m.account_id = account |
| 47 | + m.created_at = now |
| 48 | + values.append(m.explode(with_primary_keys=True)) |
| 49 | + await rdb.execute_many(insert(HealthMetric), values) |
0 commit comments