feat: complete catalog fleet management workflow
This commit is contained in:
@@ -13,13 +13,13 @@ import {
|
||||
import { MetadataGenerationModelUnavailableError } from "../catalog/metadata-generation-models.js";
|
||||
import { ModelCompletionProviderError } from "../catalog/model-completer.js";
|
||||
import {
|
||||
SensitiveDataSuggester,
|
||||
SensitiveDataSuggestionDuplicateTargetIdsError,
|
||||
SensitiveDataSuggestionInvalidResponseError,
|
||||
SensitiveDataSuggestionNoEligibleColumnsError,
|
||||
SensitiveDataSuggestionPayloadTooLargeError,
|
||||
SensitiveDataSuggestionTargetNotFoundError,
|
||||
} from "../catalog/sensitive-data-suggester.js";
|
||||
import type { SensitiveDataSuggestionRunner } from "../catalog/sensitive-data-suggestion-runner.js";
|
||||
import {
|
||||
CatalogOperationInProgressError,
|
||||
CatalogUnavailableError,
|
||||
@@ -27,6 +27,8 @@ import {
|
||||
type CatalogRepository,
|
||||
type DescriptionGenerationEvent,
|
||||
type DescriptionGenerationRun,
|
||||
type SensitiveDataSuggestionEvent,
|
||||
type SensitiveDataSuggestionRun,
|
||||
} from "../catalog/types.js";
|
||||
|
||||
const idSchema = z.uuid();
|
||||
@@ -107,6 +109,34 @@ function publicRun(run: DescriptionGenerationRun) {
|
||||
};
|
||||
}
|
||||
|
||||
function publicSensitiveDataSuggestionEvent(event: SensitiveDataSuggestionEvent) {
|
||||
return {
|
||||
runId: event.runId,
|
||||
sequence: event.sequence,
|
||||
level: event.level,
|
||||
message: event.message,
|
||||
createdAt: event.createdAt,
|
||||
};
|
||||
}
|
||||
|
||||
function publicSensitiveDataSuggestionRun(run: SensitiveDataSuggestionRun) {
|
||||
return {
|
||||
id: run.id,
|
||||
databaseId: run.databaseId,
|
||||
scope: run.scope,
|
||||
modelId: run.modelId,
|
||||
status: run.status,
|
||||
total: run.total,
|
||||
suggestedSensitive: run.suggestedSensitive,
|
||||
suggestedNonSensitive: run.suggestedNonSensitive,
|
||||
createdAt: run.createdAt,
|
||||
startedAt: run.startedAt,
|
||||
updatedAt: run.updatedAt,
|
||||
finishedAt: run.finishedAt,
|
||||
errorSummary: run.errorSummary,
|
||||
};
|
||||
}
|
||||
|
||||
function safeError(reply: FastifyReply, error: unknown) {
|
||||
if (error instanceof CatalogUnavailableError) {
|
||||
return reply.code(503).send({
|
||||
@@ -260,12 +290,31 @@ function safeSuggestionError(reply: FastifyReply, error: unknown) {
|
||||
});
|
||||
}
|
||||
|
||||
function safeSuggestionHistoryError(reply: FastifyReply, error: unknown) {
|
||||
if (error instanceof CatalogUnavailableError) {
|
||||
return reply.code(503).send({
|
||||
code: "catalog_unavailable",
|
||||
message: "Sensitive Data Suggestion history is unavailable because the database catalog is unavailable.",
|
||||
});
|
||||
}
|
||||
if (error instanceof z.ZodError) {
|
||||
return reply.code(400).send({
|
||||
code: "sensitive_data_suggestion_history_request_invalid",
|
||||
message: "Sensitive Data Suggestion history parameters are invalid.",
|
||||
});
|
||||
}
|
||||
return reply.code(500).send({
|
||||
code: "sensitive_data_suggestion_history_failed",
|
||||
message: "Sensitive Data Suggestion history could not be loaded.",
|
||||
});
|
||||
}
|
||||
|
||||
export function catalogDescriptionGenerationRoutes(
|
||||
app: FastifyInstance,
|
||||
deps: {
|
||||
repository: CatalogRepository;
|
||||
worker: DescriptionGenerationWorker;
|
||||
sensitiveDataSuggester: SensitiveDataSuggester;
|
||||
sensitiveDataSuggestionRunner: SensitiveDataSuggestionRunner;
|
||||
},
|
||||
): void {
|
||||
app.post("/catalog/databases/:databaseId/sensitive-data-suggestions", async (request, reply) => {
|
||||
@@ -273,19 +322,66 @@ export function catalogDescriptionGenerationRoutes(
|
||||
try {
|
||||
const databaseId = idSchema.parse((request.params as { databaseId?: unknown }).databaseId);
|
||||
const input = suggestionSchema.parse(request.body);
|
||||
const suggestions = await deps.sensitiveDataSuggester.suggest(
|
||||
const result = await deps.sensitiveDataSuggestionRunner.run(
|
||||
databaseId,
|
||||
input.modelId,
|
||||
input.scope,
|
||||
"targetIds" in input ? input.targetIds : [],
|
||||
new AbortController().signal,
|
||||
);
|
||||
return { suggestions };
|
||||
return {
|
||||
suggestions: result.suggestions,
|
||||
run: publicSensitiveDataSuggestionRun(result.run),
|
||||
};
|
||||
} catch (error) {
|
||||
return safeSuggestionError(reply, error);
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/catalog/sensitive-data-suggestion-runs", async (request, reply) => {
|
||||
if (!manage(request, reply)) return reply;
|
||||
try {
|
||||
const { limit } = historyQuerySchema.parse(request.query);
|
||||
return (await deps.repository.listSensitiveDataSuggestionRuns(limit))
|
||||
.map(publicSensitiveDataSuggestionRun);
|
||||
} catch (error) {
|
||||
return safeSuggestionHistoryError(reply, error);
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/catalog/sensitive-data-suggestion-runs/:runId", async (request, reply) => {
|
||||
if (!manage(request, reply)) return reply;
|
||||
try {
|
||||
const runId = idSchema.parse((request.params as { runId?: unknown }).runId);
|
||||
const run = await deps.repository.getSensitiveDataSuggestionRun(runId);
|
||||
if (!run) return reply.code(404).send({
|
||||
code: "sensitive_data_suggestion_run_not_found",
|
||||
message: "Sensitive Data Suggestion Run was not found.",
|
||||
});
|
||||
return publicSensitiveDataSuggestionRun(run);
|
||||
} catch (error) {
|
||||
return safeSuggestionHistoryError(reply, error);
|
||||
}
|
||||
});
|
||||
|
||||
app.get("/catalog/sensitive-data-suggestion-runs/:runId/events-list", async (request, reply) => {
|
||||
if (!manage(request, reply)) return reply;
|
||||
try {
|
||||
const runId = idSchema.parse((request.params as { runId?: unknown }).runId);
|
||||
const { after } = eventQuerySchema.parse(request.query);
|
||||
if (!(await deps.repository.getSensitiveDataSuggestionRun(runId))) {
|
||||
return reply.code(404).send({
|
||||
code: "sensitive_data_suggestion_run_not_found",
|
||||
message: "Sensitive Data Suggestion Run was not found.",
|
||||
});
|
||||
}
|
||||
return (await deps.repository.listSensitiveDataSuggestionEvents(runId, after))
|
||||
.map(publicSensitiveDataSuggestionEvent);
|
||||
} catch (error) {
|
||||
return safeSuggestionHistoryError(reply, error);
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/catalog/databases/:databaseId/description-generation-runs", async (request, reply) => {
|
||||
if (!manage(request, reply)) return reply;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user