Use direct DB update for onConflict refresh instead of RefreshService
Simplify by updating refresh_state directly (next_update_at=now, result_hash='') to force reprocessing, removing the need for RefreshService wiring in the location store. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Fredrik Adelöw <freben@spotify.com>
This commit is contained in:
@@ -29,14 +29,13 @@ import {
|
||||
EntityProviderConnection,
|
||||
} from '@backstage/plugin-catalog-node';
|
||||
import { locationSpecToLocationEntity } from '../util/conversion';
|
||||
import { LocationInput, LocationStore, RefreshService } from '../service/types';
|
||||
import { LocationInput, LocationStore } from '../service/types';
|
||||
import {
|
||||
ANNOTATION_ORIGIN_LOCATION,
|
||||
CompoundEntityRef,
|
||||
parseLocationRef,
|
||||
stringifyEntityRef,
|
||||
} from '@backstage/catalog-model';
|
||||
import { BackstageCredentials } from '@backstage/backend-plugin-api';
|
||||
import {
|
||||
CatalogScmEvent,
|
||||
CatalogScmEventsService,
|
||||
@@ -54,7 +53,6 @@ export class DefaultLocationStore implements LocationStore, EntityProvider {
|
||||
private readonly db: Knex;
|
||||
private readonly scmEvents: CatalogScmEventsService;
|
||||
private readonly scmEventHandlingConfig: ScmEventHandlingConfig;
|
||||
private refreshService?: RefreshService;
|
||||
|
||||
constructor(
|
||||
db: Knex,
|
||||
@@ -66,10 +64,6 @@ export class DefaultLocationStore implements LocationStore, EntityProvider {
|
||||
this.scmEventHandlingConfig = scmEventHandlingConfig;
|
||||
}
|
||||
|
||||
setRefreshService(refreshService: RefreshService): void {
|
||||
this.refreshService = refreshService;
|
||||
}
|
||||
|
||||
getProviderName(): string {
|
||||
return 'DefaultLocationStore';
|
||||
}
|
||||
@@ -78,7 +72,6 @@ export class DefaultLocationStore implements LocationStore, EntityProvider {
|
||||
input: LocationInput,
|
||||
options?: {
|
||||
onConflict?: 'refresh' | 'reject';
|
||||
credentials?: BackstageCredentials;
|
||||
},
|
||||
): Promise<Location> {
|
||||
let existed = false;
|
||||
@@ -113,23 +106,15 @@ export class DefaultLocationStore implements LocationStore, EntityProvider {
|
||||
});
|
||||
|
||||
if (existed) {
|
||||
if (!this.refreshService) {
|
||||
throw new InputError(
|
||||
'onConflict refresh is not supported: no refresh service available',
|
||||
);
|
||||
}
|
||||
if (!options?.credentials) {
|
||||
throw new InputError(
|
||||
'onConflict refresh requires credentials to be provided',
|
||||
);
|
||||
}
|
||||
const entityRef = stringifyEntityRef(
|
||||
locationSpecToLocationEntity({ location }),
|
||||
);
|
||||
await this.refreshService.refresh({
|
||||
entityRef,
|
||||
credentials: options.credentials,
|
||||
});
|
||||
await this.db<DbRefreshStateRow>('refresh_state')
|
||||
.where({ entity_ref: entityRef })
|
||||
.update({
|
||||
next_update_at: this.db.fn.now(),
|
||||
result_hash: '',
|
||||
});
|
||||
} else {
|
||||
const entity = locationSpecToLocationEntity({ location });
|
||||
await this.connection.applyMutation({
|
||||
|
||||
@@ -591,10 +591,6 @@ export class CatalogBuilder {
|
||||
new RepoLocationAnalyzer(logger, integrations, this.locationAnalyzers),
|
||||
permissionsService,
|
||||
);
|
||||
const innerRefreshService = new DefaultRefreshService({
|
||||
database: catalogDatabase,
|
||||
});
|
||||
locationStore.setRefreshService(innerRefreshService);
|
||||
const locationService = new AuthorizedLocationService(
|
||||
new DefaultLocationService(locationStore, orchestrator, {
|
||||
allowedLocationTypes: this.allowedLocationType,
|
||||
@@ -602,7 +598,7 @@ export class CatalogBuilder {
|
||||
permissionsService,
|
||||
);
|
||||
const refreshService = new AuthorizedRefreshService(
|
||||
innerRefreshService,
|
||||
new DefaultRefreshService({ database: catalogDatabase }),
|
||||
permissionsService,
|
||||
);
|
||||
|
||||
|
||||
@@ -315,7 +315,7 @@ describe('DefaultLocationServiceTest', () => {
|
||||
).rejects.toThrow(InputError);
|
||||
});
|
||||
|
||||
it('should pass onConflict and credentials through to store', async () => {
|
||||
it('should pass onConflict through to store', async () => {
|
||||
const locationSpec = {
|
||||
type: 'url',
|
||||
target: 'https://backstage.io/catalog-info.yaml',
|
||||
@@ -326,10 +326,9 @@ describe('DefaultLocationServiceTest', () => {
|
||||
...locationSpec,
|
||||
});
|
||||
|
||||
const credentials = {} as any;
|
||||
const result = await locationService.createLocation(locationSpec, false, {
|
||||
onConflict: 'refresh',
|
||||
credentials,
|
||||
credentials: {} as any,
|
||||
});
|
||||
|
||||
expect(result).toEqual({
|
||||
@@ -338,7 +337,6 @@ describe('DefaultLocationServiceTest', () => {
|
||||
});
|
||||
expect(store.createLocation).toHaveBeenCalledWith(locationSpec, {
|
||||
onConflict: 'refresh',
|
||||
credentials,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -72,7 +72,6 @@ export class DefaultLocationService implements LocationService {
|
||||
}
|
||||
const location = await this.store.createLocation(input, {
|
||||
onConflict: options?.onConflict,
|
||||
credentials: options?.credentials,
|
||||
});
|
||||
return { location, entities: [] };
|
||||
}
|
||||
|
||||
@@ -89,7 +89,6 @@ export interface LocationStore {
|
||||
location: LocationInput,
|
||||
options?: {
|
||||
onConflict?: 'refresh' | 'reject';
|
||||
credentials?: BackstageCredentials;
|
||||
},
|
||||
): Promise<Location>;
|
||||
listLocations(): Promise<Location[]>;
|
||||
|
||||
Reference in New Issue
Block a user