Skip to content

Commit a127942

Browse files
committed
refactor(scorecard): scorecard metric loading logic
Signed-off-by: Ihor Mykhno <imykhno@redhat.com>
1 parent 2964f31 commit a127942

File tree

8 files changed

+99
-76
lines changed

8 files changed

+99
-76
lines changed

workspaces/scorecard/.changeset/free-rice-pick.md renamed to workspaces/scorecard/.changeset/olive-months-cross.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,8 @@
66
'@red-hat-developer-hub/backstage-plugin-scorecard': minor
77
---
88

9-
Adds database persistence and scheduled metric collection.
9+
Adds database persistence and scheduled metric collection
10+
11+
- **BREAKING**: The supportsEntity function renamed to getCatalogFilter. The getCatalogFilter function not have parameters are not passed
12+
- Implement scheduler to load metrics by provider
13+
- Implement scheduler to cleanup saved metrics

workspaces/scorecard/plugins/scorecard-backend/src/scheduler/index.ts

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,9 @@ import type { Config } from '@backstage/config';
2525
import { CLEANUP_EXPIRED_METRICS_ID } from './constants';
2626
import { CleanupExpiredMetricsTask } from './tasks/CleanupExpiredMetricsTask';
2727
import { PullMetricsByProviderTask } from './tasks/PullMetricsByProviderTask';
28-
import { SchedulerTask } from './types';
28+
import { SchedulerOptions, SchedulerTask } from './types';
2929
import { DatabaseMetricValues } from '../database/DatabaseMetricValues';
3030

31-
export interface SchedulerOptions {
32-
auth: AuthService;
33-
catalog: CatalogService;
34-
config: Config;
35-
logger: LoggerService;
36-
scheduler: SchedulerService;
37-
database: DatabaseMetricValues;
38-
metricProvidersRegistry: MetricProvidersRegistry;
39-
}
40-
4131
export class Scheduler {
4232
private readonly auth: AuthService;
4333
private readonly catalog: CatalogService;
@@ -91,12 +81,12 @@ export class Scheduler {
9181
this.tasks = [
9282
{
9383
name: CLEANUP_EXPIRED_METRICS_ID,
94-
task: new CleanupExpiredMetricsTask(
95-
this.scheduler,
96-
this.logger,
97-
this.database,
98-
this.config,
99-
),
84+
task: new CleanupExpiredMetricsTask({
85+
scheduler: this.scheduler,
86+
logger: this.logger,
87+
database: this.database,
88+
config: this.config,
89+
}),
10090
},
10191
];
10292
}
@@ -108,12 +98,14 @@ export class Scheduler {
10898
this.tasks.push({
10999
name: provider.getProviderId(),
110100
task: new PullMetricsByProviderTask(
111-
this.scheduler,
112-
this.logger,
113-
this.database,
114-
this.config,
115-
this.catalog,
116-
this.auth,
101+
{
102+
scheduler: this.scheduler,
103+
logger: this.logger,
104+
database: this.database,
105+
config: this.config,
106+
catalog: this.catalog,
107+
auth: this.auth,
108+
},
117109
provider,
118110
),
119111
});

workspaces/scorecard/plugins/scorecard-backend/src/scheduler/tasks/CleanupExpiredMetricsTask.test.ts

Lines changed: 6 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ describe('CleanupExpiredMetricsTask', () => {
5353
mockTaskRunner as any,
5454
);
5555

56-
task = new CleanupExpiredMetricsTask(
57-
mockScheduler,
58-
mockLogger,
59-
mockDatabase,
60-
mockConfig,
61-
);
56+
task = new CleanupExpiredMetricsTask({
57+
scheduler: mockScheduler,
58+
logger: mockLogger,
59+
database: mockDatabase,
60+
config: mockConfig,
61+
});
6262
});
6363

6464
afterEach(() => {
@@ -132,20 +132,6 @@ describe('CleanupExpiredMetricsTask', () => {
132132
'Deleted 12 expired metrics older than 2 days',
133133
);
134134
});
135-
136-
it('should log error message when cleanup expired metrics fails', async () => {
137-
const error = new Error('DB is not responding');
138-
139-
mockDatabase.cleanupExpiredMetrics.mockRejectedValue(error);
140-
await expect(
141-
(task as any).cleanupExpiredMetrics(mockLogger),
142-
).rejects.toThrow(error.message);
143-
144-
expect(mockLogger.error).toHaveBeenCalledWith(
145-
'Failed to cleanup expired metrics:',
146-
error,
147-
);
148-
});
149135
});
150136

151137
describe('getDataRetentionDays', () => {

workspaces/scorecard/plugins/scorecard-backend/src/scheduler/tasks/CleanupExpiredMetricsTask.ts

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,34 @@ import { daysToMilliseconds } from './utils';
2525
import type { Config } from '@backstage/config';
2626
import { SchedulerTask } from '../types';
2727
import { DatabaseMetricValues } from '../../database/DatabaseMetricValues';
28+
import { SchedulerOptions } from '../types';
29+
30+
type Options = Pick<
31+
SchedulerOptions,
32+
'scheduler' | 'logger' | 'database' | 'config'
33+
>;
2834

2935
export class CleanupExpiredMetricsTask implements SchedulerTask {
36+
private readonly config: Config;
37+
private readonly logger: LoggerService;
38+
private readonly scheduler: SchedulerService;
39+
private readonly database: DatabaseMetricValues;
40+
3041
private static readonly CLEANUP_SCHEDULE: SchedulerServiceTaskScheduleDefinition =
3142
{
3243
frequency: { days: 1 },
3344
timeout: { minutes: 2 },
3445
initialDelay: { seconds: 3 },
3546
};
47+
3648
private static readonly DEFAULT_DATA_RETENTION_DAYS = 365;
3749

38-
constructor(
39-
private readonly scheduler: SchedulerService,
40-
private readonly logger: LoggerService,
41-
private readonly database: DatabaseMetricValues,
42-
private readonly config: Config,
43-
) {}
50+
constructor(options: Options) {
51+
this.config = options.config;
52+
this.logger = options.logger;
53+
this.scheduler = options.scheduler;
54+
this.database = options.database;
55+
}
4456

4557
async start(): Promise<void> {
4658
const taskRunner = this.scheduler.createScheduledTaskRunner(
@@ -71,15 +83,10 @@ export class CleanupExpiredMetricsTask implements SchedulerTask {
7183
Date.now() - daysToMilliseconds(dataRetentionDays),
7284
);
7385

74-
try {
75-
const deletedCount = await this.database.cleanupExpiredMetrics(olderThan);
76-
logger.info(
77-
`Deleted ${deletedCount} expired metrics older than ${dataRetentionDays} days`,
78-
);
79-
} catch (error) {
80-
logger.error(`Failed to cleanup expired metrics:`, error);
81-
throw error;
82-
}
86+
const deletedCount = await this.database.cleanupExpiredMetrics(olderThan);
87+
logger.info(
88+
`Deleted ${deletedCount} expired metrics older than ${dataRetentionDays} days`,
89+
);
8390
}
8491

8592
private getDataRetentionDays(): number {

workspaces/scorecard/plugins/scorecard-backend/src/scheduler/tasks/PullMetricsByProviderTask.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,14 @@ describe('PullMetricsByProviderTask', () => {
6868
);
6969

7070
task = new PullMetricsByProviderTask(
71-
mockScheduler,
72-
mockLogger,
73-
mockDatabase,
74-
mockConfig,
75-
mockCatalog,
76-
mockAuth,
71+
{
72+
scheduler: mockScheduler,
73+
logger: mockLogger,
74+
database: mockDatabase,
75+
config: mockConfig,
76+
catalog: mockCatalog,
77+
auth: mockAuth,
78+
},
7779
mockProvider,
7880
);
7981
});

workspaces/scorecard/plugins/scorecard-backend/src/scheduler/tasks/PullMetricsByProviderTask.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,29 +28,41 @@ import { MetricProvider } from '@red-hat-developer-hub/backstage-plugin-scorecar
2828
import { v4 as uuid } from 'uuid';
2929
import { stringifyEntityRef } from '@backstage/catalog-model';
3030
import { DbMetricValue } from '../../database/types';
31-
import { SchedulerTask } from '../types';
31+
import { SchedulerOptions, SchedulerTask } from '../types';
32+
33+
type Options = Pick<
34+
SchedulerOptions,
35+
'scheduler' | 'logger' | 'database' | 'config' | 'catalog' | 'auth'
36+
>;
3237

3338
export class PullMetricsByProviderTask implements SchedulerTask {
39+
private readonly config: Config;
40+
private readonly auth: AuthService;
3441
private readonly providerId: string;
42+
private readonly logger: LoggerService;
43+
private readonly catalog: CatalogService;
44+
private readonly provider: MetricProvider;
45+
private readonly scheduler: SchedulerService;
46+
private readonly database: DatabaseMetricValues;
3547

3648
private static readonly CATALOG_BATCH_SIZE = 50;
49+
3750
private static readonly DEFAULT_SCHEDULE: SchedulerServiceTaskScheduleDefinition =
3851
{
3952
frequency: { hours: 1 },
4053
timeout: { minutes: 15 },
4154
initialDelay: { seconds: 3 },
4255
};
4356

44-
constructor(
45-
private readonly scheduler: SchedulerService,
46-
private readonly logger: LoggerService,
47-
private readonly database: DatabaseMetricValues,
48-
private readonly config: Config,
49-
private readonly catalog: CatalogService,
50-
private readonly auth: AuthService,
51-
private readonly provider: MetricProvider,
52-
) {
53-
this.providerId = this.provider.getProviderId();
57+
constructor(options: Options, provider: MetricProvider) {
58+
this.config = options.config;
59+
this.auth = options.auth;
60+
this.providerId = provider.getProviderId();
61+
this.logger = options.logger;
62+
this.catalog = options.catalog;
63+
this.provider = provider;
64+
this.scheduler = options.scheduler;
65+
this.database = options.database;
5466
}
5567

5668
async start(): Promise<void> {

workspaces/scorecard/plugins/scorecard-backend/src/scheduler/types.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,26 @@
1414
* limitations under the License.
1515
*/
1616

17+
import type { Config } from '@backstage/config';
18+
import { CatalogService } from '@backstage/plugin-catalog-node';
19+
import { DatabaseMetricValues } from '../database/DatabaseMetricValues';
20+
import { MetricProvidersRegistry } from '../providers/MetricProvidersRegistry';
21+
import {
22+
AuthService,
23+
LoggerService,
24+
SchedulerService,
25+
} from '@backstage/backend-plugin-api';
26+
1727
export interface SchedulerTask {
1828
start(): Promise<void>;
1929
}
30+
31+
export interface SchedulerOptions {
32+
auth: AuthService;
33+
catalog: CatalogService;
34+
config: Config;
35+
logger: LoggerService;
36+
scheduler: SchedulerService;
37+
database: DatabaseMetricValues;
38+
metricProvidersRegistry: MetricProvidersRegistry;
39+
}

0 commit comments

Comments
 (0)