@backstage/plugin-catalog-backend-module-incremental-ingestion 0.7.12-next.0 → 0.7.12-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/database/IncrementalIngestionDatabaseManager.cjs.js +7 -7
- package/dist/database/IncrementalIngestionDatabaseManager.cjs.js.map +1 -1
- package/dist/engine/IncrementalIngestionEngine.cjs.js +2 -2
- package/dist/engine/IncrementalIngestionEngine.cjs.js.map +1 -1
- package/package.json +8 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# @backstage/plugin-catalog-backend-module-incremental-ingestion
|
|
2
2
|
|
|
3
|
+
## 0.7.12-next.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e9b78e9: Removed the `uuid` dependency and replaced usage with the built-in `crypto.randomUUID()`.
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @backstage/catalog-model@1.8.1-next.1
|
|
10
|
+
- @backstage/plugin-catalog-node@2.2.1-next.1
|
|
11
|
+
- @backstage/backend-defaults@0.17.1-next.1
|
|
12
|
+
- @backstage/plugin-catalog-backend@3.6.2-next.1
|
|
13
|
+
|
|
3
14
|
## 0.7.12-next.0
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var catalogModel = require('@backstage/catalog-model');
|
|
4
|
-
var
|
|
4
|
+
var node_crypto = require('node:crypto');
|
|
5
5
|
|
|
6
6
|
class IncrementalIngestionDatabaseManager {
|
|
7
7
|
client;
|
|
@@ -152,7 +152,7 @@ class IncrementalIngestionDatabaseManager {
|
|
|
152
152
|
const next_action_at = /* @__PURE__ */ new Date();
|
|
153
153
|
next_action_at.setTime(next_action_at.getTime() + 24 * 60 * 60 * 1e3);
|
|
154
154
|
await this.insertIngestionRecord({
|
|
155
|
-
id:
|
|
155
|
+
id: node_crypto.randomUUID(),
|
|
156
156
|
next_action: "rest",
|
|
157
157
|
provider_name: provider,
|
|
158
158
|
next_action_at,
|
|
@@ -179,7 +179,7 @@ class IncrementalIngestionDatabaseManager {
|
|
|
179
179
|
* @returns A new ingestion record
|
|
180
180
|
*/
|
|
181
181
|
async createProviderIngestionRecord(provider) {
|
|
182
|
-
const ingestionId =
|
|
182
|
+
const ingestionId = node_crypto.randomUUID();
|
|
183
183
|
const nextAction = "ingest";
|
|
184
184
|
try {
|
|
185
185
|
await this.insertIngestionRecord({
|
|
@@ -260,7 +260,7 @@ class IncrementalIngestionDatabaseManager {
|
|
|
260
260
|
next_action_at.setTime(next_action_at.getTime() + 24 * 60 * 60 * 1e3);
|
|
261
261
|
for (const provider of providers) {
|
|
262
262
|
await this.insertIngestionRecord({
|
|
263
|
-
id:
|
|
263
|
+
id: node_crypto.randomUUID(),
|
|
264
264
|
next_action: "rest",
|
|
265
265
|
provider_name: provider,
|
|
266
266
|
next_action_at,
|
|
@@ -306,7 +306,7 @@ class IncrementalIngestionDatabaseManager {
|
|
|
306
306
|
next_action: "nothing (done)",
|
|
307
307
|
rest_completed_at: /* @__PURE__ */ new Date(),
|
|
308
308
|
status: "complete",
|
|
309
|
-
completion_ticket:
|
|
309
|
+
completion_ticket: node_crypto.randomUUID()
|
|
310
310
|
}
|
|
311
311
|
});
|
|
312
312
|
}
|
|
@@ -361,7 +361,7 @@ class IncrementalIngestionDatabaseManager {
|
|
|
361
361
|
next_action: "nothing (canceled)",
|
|
362
362
|
rest_completed_at: /* @__PURE__ */ new Date(),
|
|
363
363
|
status: "complete",
|
|
364
|
-
completion_ticket:
|
|
364
|
+
completion_ticket: node_crypto.randomUUID()
|
|
365
365
|
}
|
|
366
366
|
});
|
|
367
367
|
}
|
|
@@ -448,7 +448,7 @@ class IncrementalIngestionDatabaseManager {
|
|
|
448
448
|
if (newRefs.length > 0) {
|
|
449
449
|
await tx("ingestion_mark_entities").insert(
|
|
450
450
|
newRefs.map((ref) => ({
|
|
451
|
-
id:
|
|
451
|
+
id: node_crypto.randomUUID(),
|
|
452
452
|
ingestion_mark_id: markId,
|
|
453
453
|
ref
|
|
454
454
|
}))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncrementalIngestionDatabaseManager.cjs.js","sources":["../../src/database/IncrementalIngestionDatabaseManager.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Knex } from 'knex';\nimport type { DeferredEntity } from '@backstage/plugin-catalog-node';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { Duration } from 'luxon';\nimport { v4 } from 'uuid';\nimport {\n IngestionRecord,\n IngestionRecordUpdate,\n IngestionUpsert,\n MarkRecord,\n MarkRecordInsert,\n} from './tables';\n\nexport class IncrementalIngestionDatabaseManager {\n private client: Knex;\n\n constructor(options: { client: Knex }) {\n this.client = options.client;\n }\n\n /**\n * Performs an update to the ingestion record with matching `id`.\n * @param options - IngestionRecordUpdate\n */\n async updateIngestionRecordById(options: IngestionRecordUpdate) {\n await this.client.transaction(async tx => {\n const { ingestionId, update } = options;\n await tx('ingestions').where('id', ingestionId).update(update);\n });\n }\n\n /**\n * Performs an update to the ingestion record with matching provider name. Will only update active records.\n * @param provider - string\n * @param update - Partial<IngestionUpsertIFace>\n */\n async updateIngestionRecordByProvider(\n provider: string,\n update: Partial<IngestionUpsert>,\n ) {\n await this.client.transaction(async tx => {\n await tx('ingestions')\n .where('provider_name', provider)\n .andWhere('completion_ticket', 'open')\n .update(update);\n });\n }\n\n /**\n * Performs an insert into the `ingestions` table with the supplied values.\n * @param record - IngestionUpsertIFace\n */\n async insertIngestionRecord(record: IngestionUpsert) {\n await this.client.transaction(async tx => {\n await tx('ingestions').insert(record);\n });\n }\n\n private async deleteMarkEntities(\n tx: Knex.Transaction,\n ids: { id: string }[],\n ) {\n const chunks: { id: string }[][] = [];\n for (let i = 0; i < ids.length; i += 100) {\n const chunk = ids.slice(i, i + 100);\n chunks.push(chunk);\n }\n\n let deleted = 0;\n\n for (const chunk of chunks) {\n const chunkDeleted = await tx('ingestion_mark_entities')\n .delete()\n .whereIn(\n 'id',\n chunk.map(entry => entry.id),\n );\n deleted += chunkDeleted;\n }\n\n return deleted;\n }\n\n /**\n * Finds the current ingestion record for the named provider.\n * @param provider - string\n * @returns IngestionRecord | undefined\n */\n async getCurrentIngestionRecord(provider: string) {\n return await this.client.transaction(async tx => {\n const record = await tx<IngestionRecord>('ingestions')\n .where('provider_name', provider)\n .andWhere('completion_ticket', 'open')\n .first();\n return record;\n });\n }\n\n /**\n * Finds the last ingestion record for the named provider.\n * @param provider - string\n * @returns IngestionRecord | undefined\n */\n async getPreviousIngestionRecord(provider: string) {\n return await this.client.transaction(async tx => {\n return await tx<IngestionRecord>('ingestions')\n .where('provider_name', provider)\n .andWhereNot('completion_ticket', 'open')\n .first();\n });\n }\n\n /**\n * Removes all entries from `ingestion_marks_entities`, `ingestion_marks`, and `ingestions`\n * for prior ingestions that completed (i.e., have a `completion_ticket` value other than 'open').\n * @param provider - string\n * @returns A count of deletions for each record type.\n */\n async clearFinishedIngestions(provider: string) {\n return await this.client.transaction(async tx => {\n const markEntitiesDeleted = await tx('ingestion_mark_entities')\n .delete()\n .whereIn(\n 'ingestion_mark_id',\n tx('ingestion_marks')\n .select('id')\n .whereIn(\n 'ingestion_id',\n tx('ingestions')\n .select('id')\n .where('provider_name', provider)\n .andWhereNot('completion_ticket', 'open'),\n ),\n );\n\n const marksDeleted = await tx('ingestion_marks')\n .delete()\n .whereIn(\n 'ingestion_id',\n tx('ingestions')\n .select('id')\n .where('provider_name', provider)\n .andWhereNot('completion_ticket', 'open'),\n );\n\n const ingestionsDeleted = await tx('ingestions')\n .delete()\n .where('provider_name', provider)\n .andWhereNot('completion_ticket', 'open');\n\n return {\n deletions: {\n markEntitiesDeleted,\n marksDeleted,\n ingestionsDeleted,\n },\n };\n });\n }\n\n /**\n * Automatically cleans up duplicate ingestion records if they were accidentally created.\n * Any ingestion record where the `rest_completed_at` is null (meaning it is active) AND\n * the ingestionId is incorrect is a duplicate ingestion record.\n * @param ingestionId - string\n * @param provider - string\n */\n async clearDuplicateIngestions(ingestionId: string, provider: string) {\n await this.client.transaction(async tx => {\n const invalid = await tx<IngestionRecord>('ingestions')\n .where('provider_name', provider)\n .andWhere('rest_completed_at', null)\n .andWhereNot('id', ingestionId);\n\n if (invalid.length > 0) {\n await tx('ingestions').delete().whereIn('id', invalid);\n await tx('ingestion_mark_entities')\n .delete()\n .whereIn(\n 'ingestion_mark_id',\n tx('ingestion_marks').select('id').whereIn('ingestion_id', invalid),\n );\n await tx('ingestion_marks').delete().whereIn('ingestion_id', invalid);\n }\n });\n }\n\n /**\n * This method fully purges and resets all ingestion records for the named provider, and\n * leaves it in a paused state.\n * @param provider - string\n * @returns Counts of all deleted ingestion records\n */\n async purgeAndResetProvider(provider: string) {\n return await this.client.transaction(async tx => {\n const ingestionIDs: { id: string }[] = await tx('ingestions')\n .select('id')\n .where('provider_name', provider);\n\n const markIDs: { id: string }[] =\n ingestionIDs.length > 0\n ? await tx('ingestion_marks')\n .select('id')\n .whereIn(\n 'ingestion_id',\n ingestionIDs.map(entry => entry.id),\n )\n : [];\n\n const markEntityIDs: { id: string }[] =\n markIDs.length > 0\n ? await tx('ingestion_mark_entities')\n .select('id')\n .whereIn(\n 'ingestion_mark_id',\n markIDs.map(entry => entry.id),\n )\n : [];\n\n const markEntitiesDeleted = await this.deleteMarkEntities(\n tx,\n markEntityIDs,\n );\n\n const marksDeleted =\n markIDs.length > 0\n ? await tx('ingestion_marks')\n .delete()\n .whereIn(\n 'ingestion_id',\n ingestionIDs.map(entry => entry.id),\n )\n : 0;\n\n const ingestionsDeleted = await tx('ingestions')\n .delete()\n .where('provider_name', provider);\n\n const next_action_at = new Date();\n next_action_at.setTime(next_action_at.getTime() + 24 * 60 * 60 * 1000);\n\n await this.insertIngestionRecord({\n id: v4(),\n next_action: 'rest',\n provider_name: provider,\n next_action_at,\n ingestion_completed_at: new Date(),\n status: 'resting',\n completion_ticket: 'open',\n });\n\n return { provider, ingestionsDeleted, marksDeleted, markEntitiesDeleted };\n });\n }\n\n /**\n * This method is used to remove entity records from the ingestion_mark_entities\n * table by their entity reference.\n */\n async deleteEntityRecordsByRef(entities: { entityRef: string }[]) {\n const refs = entities.map(e => e.entityRef);\n await this.client.transaction(async tx => {\n await tx('ingestion_mark_entities').delete().whereIn('ref', refs);\n });\n }\n\n /**\n * Creates a new ingestion record.\n * @param provider - string\n * @returns A new ingestion record\n */\n async createProviderIngestionRecord(provider: string) {\n const ingestionId = v4();\n const nextAction = 'ingest';\n try {\n await this.insertIngestionRecord({\n id: ingestionId,\n next_action: nextAction,\n provider_name: provider,\n status: 'bursting',\n completion_ticket: 'open',\n });\n return { ingestionId, nextAction, attempts: 0, nextActionAt: Date.now() };\n } catch (_e) {\n // Creating the ingestion record failed. Return undefined.\n return undefined;\n }\n }\n\n /**\n * Computes which entities to remove, if any, at the end of a burst.\n * @param provider - string\n * @param ingestionId - string\n * @returns All entities to remove for this burst.\n */\n async computeRemoved(provider: string, ingestionId: string) {\n const previousIngestion = await this.getPreviousIngestionRecord(provider);\n return await this.client.transaction(async tx => {\n const count = await tx('ingestion_mark_entities')\n .count({ total: 'ingestion_mark_entities.ref' })\n .join(\n 'ingestion_marks',\n 'ingestion_marks.id',\n 'ingestion_mark_entities.ingestion_mark_id',\n )\n .join('ingestions', 'ingestions.id', 'ingestion_marks.ingestion_id')\n .where('ingestions.id', ingestionId);\n\n const total = count.reduce((acc, cur) => acc + Number(cur.total), 0);\n\n const removed: { entityRef: string }[] = [];\n if (previousIngestion) {\n const stale: { ref: string }[] = await tx('ingestion_mark_entities')\n .select('ingestion_mark_entities.ref')\n .join(\n 'ingestion_marks',\n 'ingestion_marks.id',\n 'ingestion_mark_entities.ingestion_mark_id',\n )\n .join('ingestions', 'ingestions.id', 'ingestion_marks.ingestion_id')\n .where('ingestions.id', previousIngestion.id);\n\n for (const entityRef of stale) {\n removed.push({ entityRef: entityRef.ref });\n }\n }\n\n return { total, removed };\n });\n }\n\n /**\n * Performs a lookup of all providers that have duplicate active ingestion records.\n * @returns An array of all duplicate active ingestions\n */\n async healthcheck() {\n return await this.client.transaction(async tx => {\n const records = await tx<{ id: string; provider_name: string }>(\n 'ingestions',\n )\n .distinct('id', 'provider_name')\n .where('rest_completed_at', null);\n return records;\n });\n }\n\n /**\n * Skips any wait time for the next action to run.\n * @param provider - string\n */\n async triggerNextProviderAction(provider: string) {\n await this.updateIngestionRecordByProvider(provider, {\n next_action_at: new Date(),\n });\n }\n\n /**\n * Purges the following tables:\n * * `ingestions`\n * * `ingestion_marks`\n * * `ingestion_mark_entities`\n *\n * This function leaves the ingestions table with all providers in a paused state.\n * @returns Results from cleaning up all ingestion tables.\n */\n async cleanupProviders() {\n const providers = await this.listProviders();\n\n const ingestionsDeleted = await this.purgeTable('ingestions');\n\n const next_action_at = new Date();\n next_action_at.setTime(next_action_at.getTime() + 24 * 60 * 60 * 1000);\n\n for (const provider of providers) {\n await this.insertIngestionRecord({\n id: v4(),\n next_action: 'rest',\n provider_name: provider,\n next_action_at,\n ingestion_completed_at: new Date(),\n status: 'resting',\n completion_ticket: 'open',\n });\n }\n\n const ingestionMarksDeleted = await this.purgeTable('ingestion_marks');\n const markEntitiesDeleted = await this.purgeTable(\n 'ingestion_mark_entities',\n );\n\n return { ingestionsDeleted, ingestionMarksDeleted, markEntitiesDeleted };\n }\n\n /**\n * Configures the current ingestion record to ingest a burst.\n * @param ingestionId - string\n */\n async setProviderIngesting(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: { next_action: 'ingest' },\n });\n }\n\n /**\n * Indicates the provider is currently ingesting a burst.\n * @param ingestionId - string\n */\n async setProviderBursting(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: { status: 'bursting' },\n });\n }\n\n /**\n * Finalizes the current ingestion record to indicate that the post-ingestion rest period is complete.\n * @param ingestionId - string\n */\n async setProviderComplete(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: {\n next_action: 'nothing (done)',\n rest_completed_at: new Date(),\n status: 'complete',\n completion_ticket: v4(),\n },\n });\n }\n\n /**\n * Marks ingestion as complete and starts the post-ingestion rest cycle.\n * @param ingestionId - string\n * @param restLength - Duration\n */\n async setProviderResting(ingestionId: string, restLength: Duration) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: {\n next_action: 'rest',\n next_action_at: new Date(Date.now() + restLength.as('milliseconds')),\n ingestion_completed_at: new Date(),\n status: 'resting',\n },\n });\n }\n\n /**\n * Marks ingestion as paused after a burst completes.\n * @param ingestionId - string\n */\n async setProviderInterstitial(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: { attempts: 0, status: 'interstitial' },\n });\n }\n\n /**\n * Starts the cancel process for the current ingestion.\n * @param ingestionId - string\n * @param message - string (optional)\n */\n async setProviderCanceling(ingestionId: string, message?: string) {\n const update: Partial<IngestionUpsert> = {\n next_action: 'cancel',\n last_error: message ? message : undefined,\n next_action_at: new Date(),\n status: 'canceling',\n };\n await this.updateIngestionRecordById({ ingestionId, update });\n }\n\n /**\n * Completes the cancel process and triggers a new ingestion.\n * @param ingestionId - string\n */\n async setProviderCanceled(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: {\n next_action: 'nothing (canceled)',\n rest_completed_at: new Date(),\n status: 'complete',\n completion_ticket: v4(),\n },\n });\n }\n\n /**\n * Configures the current ingestion to wait and retry, due to a data source error.\n * @param ingestionId - string\n * @param attempts - number\n * @param error - Error\n * @param backoffLength - number\n */\n async setProviderBackoff(\n ingestionId: string,\n attempts: number,\n error: Error,\n backoffLength: number,\n ) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: {\n next_action: 'backoff',\n attempts: attempts + 1,\n last_error: String(error),\n next_action_at: new Date(Date.now() + backoffLength),\n status: 'backing off',\n },\n });\n }\n\n /**\n * Returns the last record from `ingestion_marks` for the supplied ingestionId.\n * @param ingestionId - string\n * @returns MarkRecord | undefined\n */\n async getLastMark(ingestionId: string) {\n return await this.client.transaction(async tx => {\n const mark = await tx<MarkRecord>('ingestion_marks')\n .where('ingestion_id', ingestionId)\n .orderBy('sequence', 'desc')\n .first();\n return this.#decodeMark(this.client, mark);\n });\n }\n\n /**\n * Returns the first record from `ingestion_marks` for the supplied ingestionId.\n * @param ingestionId - string\n * @returns MarkRecord | undefined\n */\n async getFirstMark(ingestionId: string) {\n return await this.client.transaction(async tx => {\n const mark = await tx<MarkRecord>('ingestion_marks')\n .where('ingestion_id', ingestionId)\n .orderBy('sequence', 'asc')\n .first();\n return this.#decodeMark(this.client, mark);\n });\n }\n\n async getAllMarks(ingestionId: string) {\n return await this.client.transaction(async tx => {\n const marks = await tx<MarkRecord>('ingestion_marks')\n .where('ingestion_id', ingestionId)\n .orderBy('sequence', 'desc');\n return marks.map(m => this.#decodeMark(this.client, m));\n });\n }\n\n /**\n * Performs an insert into the `ingestion_marks` table with the supplied values.\n * @param options - MarkRecordInsert\n */\n async createMark(options: MarkRecordInsert) {\n const { record } = options;\n await this.client.transaction(async tx => {\n await tx('ingestion_marks').insert(record);\n });\n }\n\n // Handles the fact that sqlite does not support json columns; they just\n // persist the stringified data instead\n #decodeMark<T extends MarkRecord | undefined>(knex: Knex, record: T): T {\n if (record && knex.client.config.client.includes('sqlite3')) {\n return {\n ...record,\n cursor: JSON.parse(record.cursor as string),\n };\n }\n return record;\n }\n\n /**\n * Performs an upsert to the `ingestion_mark_entities` table for all deferred entities.\n * @param markId - string\n * @param entities - DeferredEntity[]\n */\n async createMarkEntities(markId: string, entities: DeferredEntity[]) {\n const refs = entities.map(e => stringifyEntityRef(e.entity));\n\n await this.client.transaction(async tx => {\n const existingRefsArray = (\n await tx<{ ref: string }>('ingestion_mark_entities')\n .select('ref')\n .whereIn('ref', refs)\n ).map(e => e.ref);\n\n const existingRefsSet = new Set(existingRefsArray);\n\n const newRefs = refs.filter(e => !existingRefsSet.has(e));\n\n await tx('ingestion_mark_entities')\n .update('ingestion_mark_id', markId)\n .whereIn('ref', existingRefsArray);\n\n if (newRefs.length > 0) {\n await tx('ingestion_mark_entities').insert(\n newRefs.map(ref => ({\n id: v4(),\n ingestion_mark_id: markId,\n ref,\n })),\n );\n }\n });\n }\n\n /**\n * Deletes the entire content of a table, and returns the number of records deleted.\n * @param table - string\n * @returns number\n */\n async purgeTable(table: string) {\n return await this.client.transaction(async tx => {\n return await tx(table).delete();\n });\n }\n\n /**\n * Returns a list of all providers.\n * @returns string[]\n */\n async listProviders() {\n return await this.client.transaction(async tx => {\n const providers = await tx<{ provider_name: string }>(\n 'ingestions',\n ).distinct('provider_name');\n return providers.map(entry => entry.provider_name);\n });\n }\n\n async updateByName(provider: string, update: Partial<IngestionUpsert>) {\n await this.updateIngestionRecordByProvider(provider, update);\n }\n}\n"],"names":["v4","stringifyEntityRef"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"IncrementalIngestionDatabaseManager.cjs.js","sources":["../../src/database/IncrementalIngestionDatabaseManager.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Knex } from 'knex';\nimport type { DeferredEntity } from '@backstage/plugin-catalog-node';\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { Duration } from 'luxon';\nimport { randomUUID as v4 } from 'node:crypto';\nimport {\n IngestionRecord,\n IngestionRecordUpdate,\n IngestionUpsert,\n MarkRecord,\n MarkRecordInsert,\n} from './tables';\n\nexport class IncrementalIngestionDatabaseManager {\n private client: Knex;\n\n constructor(options: { client: Knex }) {\n this.client = options.client;\n }\n\n /**\n * Performs an update to the ingestion record with matching `id`.\n * @param options - IngestionRecordUpdate\n */\n async updateIngestionRecordById(options: IngestionRecordUpdate) {\n await this.client.transaction(async tx => {\n const { ingestionId, update } = options;\n await tx('ingestions').where('id', ingestionId).update(update);\n });\n }\n\n /**\n * Performs an update to the ingestion record with matching provider name. Will only update active records.\n * @param provider - string\n * @param update - Partial<IngestionUpsertIFace>\n */\n async updateIngestionRecordByProvider(\n provider: string,\n update: Partial<IngestionUpsert>,\n ) {\n await this.client.transaction(async tx => {\n await tx('ingestions')\n .where('provider_name', provider)\n .andWhere('completion_ticket', 'open')\n .update(update);\n });\n }\n\n /**\n * Performs an insert into the `ingestions` table with the supplied values.\n * @param record - IngestionUpsertIFace\n */\n async insertIngestionRecord(record: IngestionUpsert) {\n await this.client.transaction(async tx => {\n await tx('ingestions').insert(record);\n });\n }\n\n private async deleteMarkEntities(\n tx: Knex.Transaction,\n ids: { id: string }[],\n ) {\n const chunks: { id: string }[][] = [];\n for (let i = 0; i < ids.length; i += 100) {\n const chunk = ids.slice(i, i + 100);\n chunks.push(chunk);\n }\n\n let deleted = 0;\n\n for (const chunk of chunks) {\n const chunkDeleted = await tx('ingestion_mark_entities')\n .delete()\n .whereIn(\n 'id',\n chunk.map(entry => entry.id),\n );\n deleted += chunkDeleted;\n }\n\n return deleted;\n }\n\n /**\n * Finds the current ingestion record for the named provider.\n * @param provider - string\n * @returns IngestionRecord | undefined\n */\n async getCurrentIngestionRecord(provider: string) {\n return await this.client.transaction(async tx => {\n const record = await tx<IngestionRecord>('ingestions')\n .where('provider_name', provider)\n .andWhere('completion_ticket', 'open')\n .first();\n return record;\n });\n }\n\n /**\n * Finds the last ingestion record for the named provider.\n * @param provider - string\n * @returns IngestionRecord | undefined\n */\n async getPreviousIngestionRecord(provider: string) {\n return await this.client.transaction(async tx => {\n return await tx<IngestionRecord>('ingestions')\n .where('provider_name', provider)\n .andWhereNot('completion_ticket', 'open')\n .first();\n });\n }\n\n /**\n * Removes all entries from `ingestion_marks_entities`, `ingestion_marks`, and `ingestions`\n * for prior ingestions that completed (i.e., have a `completion_ticket` value other than 'open').\n * @param provider - string\n * @returns A count of deletions for each record type.\n */\n async clearFinishedIngestions(provider: string) {\n return await this.client.transaction(async tx => {\n const markEntitiesDeleted = await tx('ingestion_mark_entities')\n .delete()\n .whereIn(\n 'ingestion_mark_id',\n tx('ingestion_marks')\n .select('id')\n .whereIn(\n 'ingestion_id',\n tx('ingestions')\n .select('id')\n .where('provider_name', provider)\n .andWhereNot('completion_ticket', 'open'),\n ),\n );\n\n const marksDeleted = await tx('ingestion_marks')\n .delete()\n .whereIn(\n 'ingestion_id',\n tx('ingestions')\n .select('id')\n .where('provider_name', provider)\n .andWhereNot('completion_ticket', 'open'),\n );\n\n const ingestionsDeleted = await tx('ingestions')\n .delete()\n .where('provider_name', provider)\n .andWhereNot('completion_ticket', 'open');\n\n return {\n deletions: {\n markEntitiesDeleted,\n marksDeleted,\n ingestionsDeleted,\n },\n };\n });\n }\n\n /**\n * Automatically cleans up duplicate ingestion records if they were accidentally created.\n * Any ingestion record where the `rest_completed_at` is null (meaning it is active) AND\n * the ingestionId is incorrect is a duplicate ingestion record.\n * @param ingestionId - string\n * @param provider - string\n */\n async clearDuplicateIngestions(ingestionId: string, provider: string) {\n await this.client.transaction(async tx => {\n const invalid = await tx<IngestionRecord>('ingestions')\n .where('provider_name', provider)\n .andWhere('rest_completed_at', null)\n .andWhereNot('id', ingestionId);\n\n if (invalid.length > 0) {\n await tx('ingestions').delete().whereIn('id', invalid);\n await tx('ingestion_mark_entities')\n .delete()\n .whereIn(\n 'ingestion_mark_id',\n tx('ingestion_marks').select('id').whereIn('ingestion_id', invalid),\n );\n await tx('ingestion_marks').delete().whereIn('ingestion_id', invalid);\n }\n });\n }\n\n /**\n * This method fully purges and resets all ingestion records for the named provider, and\n * leaves it in a paused state.\n * @param provider - string\n * @returns Counts of all deleted ingestion records\n */\n async purgeAndResetProvider(provider: string) {\n return await this.client.transaction(async tx => {\n const ingestionIDs: { id: string }[] = await tx('ingestions')\n .select('id')\n .where('provider_name', provider);\n\n const markIDs: { id: string }[] =\n ingestionIDs.length > 0\n ? await tx('ingestion_marks')\n .select('id')\n .whereIn(\n 'ingestion_id',\n ingestionIDs.map(entry => entry.id),\n )\n : [];\n\n const markEntityIDs: { id: string }[] =\n markIDs.length > 0\n ? await tx('ingestion_mark_entities')\n .select('id')\n .whereIn(\n 'ingestion_mark_id',\n markIDs.map(entry => entry.id),\n )\n : [];\n\n const markEntitiesDeleted = await this.deleteMarkEntities(\n tx,\n markEntityIDs,\n );\n\n const marksDeleted =\n markIDs.length > 0\n ? await tx('ingestion_marks')\n .delete()\n .whereIn(\n 'ingestion_id',\n ingestionIDs.map(entry => entry.id),\n )\n : 0;\n\n const ingestionsDeleted = await tx('ingestions')\n .delete()\n .where('provider_name', provider);\n\n const next_action_at = new Date();\n next_action_at.setTime(next_action_at.getTime() + 24 * 60 * 60 * 1000);\n\n await this.insertIngestionRecord({\n id: v4(),\n next_action: 'rest',\n provider_name: provider,\n next_action_at,\n ingestion_completed_at: new Date(),\n status: 'resting',\n completion_ticket: 'open',\n });\n\n return { provider, ingestionsDeleted, marksDeleted, markEntitiesDeleted };\n });\n }\n\n /**\n * This method is used to remove entity records from the ingestion_mark_entities\n * table by their entity reference.\n */\n async deleteEntityRecordsByRef(entities: { entityRef: string }[]) {\n const refs = entities.map(e => e.entityRef);\n await this.client.transaction(async tx => {\n await tx('ingestion_mark_entities').delete().whereIn('ref', refs);\n });\n }\n\n /**\n * Creates a new ingestion record.\n * @param provider - string\n * @returns A new ingestion record\n */\n async createProviderIngestionRecord(provider: string) {\n const ingestionId = v4();\n const nextAction = 'ingest';\n try {\n await this.insertIngestionRecord({\n id: ingestionId,\n next_action: nextAction,\n provider_name: provider,\n status: 'bursting',\n completion_ticket: 'open',\n });\n return { ingestionId, nextAction, attempts: 0, nextActionAt: Date.now() };\n } catch (_e) {\n // Creating the ingestion record failed. Return undefined.\n return undefined;\n }\n }\n\n /**\n * Computes which entities to remove, if any, at the end of a burst.\n * @param provider - string\n * @param ingestionId - string\n * @returns All entities to remove for this burst.\n */\n async computeRemoved(provider: string, ingestionId: string) {\n const previousIngestion = await this.getPreviousIngestionRecord(provider);\n return await this.client.transaction(async tx => {\n const count = await tx('ingestion_mark_entities')\n .count({ total: 'ingestion_mark_entities.ref' })\n .join(\n 'ingestion_marks',\n 'ingestion_marks.id',\n 'ingestion_mark_entities.ingestion_mark_id',\n )\n .join('ingestions', 'ingestions.id', 'ingestion_marks.ingestion_id')\n .where('ingestions.id', ingestionId);\n\n const total = count.reduce((acc, cur) => acc + Number(cur.total), 0);\n\n const removed: { entityRef: string }[] = [];\n if (previousIngestion) {\n const stale: { ref: string }[] = await tx('ingestion_mark_entities')\n .select('ingestion_mark_entities.ref')\n .join(\n 'ingestion_marks',\n 'ingestion_marks.id',\n 'ingestion_mark_entities.ingestion_mark_id',\n )\n .join('ingestions', 'ingestions.id', 'ingestion_marks.ingestion_id')\n .where('ingestions.id', previousIngestion.id);\n\n for (const entityRef of stale) {\n removed.push({ entityRef: entityRef.ref });\n }\n }\n\n return { total, removed };\n });\n }\n\n /**\n * Performs a lookup of all providers that have duplicate active ingestion records.\n * @returns An array of all duplicate active ingestions\n */\n async healthcheck() {\n return await this.client.transaction(async tx => {\n const records = await tx<{ id: string; provider_name: string }>(\n 'ingestions',\n )\n .distinct('id', 'provider_name')\n .where('rest_completed_at', null);\n return records;\n });\n }\n\n /**\n * Skips any wait time for the next action to run.\n * @param provider - string\n */\n async triggerNextProviderAction(provider: string) {\n await this.updateIngestionRecordByProvider(provider, {\n next_action_at: new Date(),\n });\n }\n\n /**\n * Purges the following tables:\n * * `ingestions`\n * * `ingestion_marks`\n * * `ingestion_mark_entities`\n *\n * This function leaves the ingestions table with all providers in a paused state.\n * @returns Results from cleaning up all ingestion tables.\n */\n async cleanupProviders() {\n const providers = await this.listProviders();\n\n const ingestionsDeleted = await this.purgeTable('ingestions');\n\n const next_action_at = new Date();\n next_action_at.setTime(next_action_at.getTime() + 24 * 60 * 60 * 1000);\n\n for (const provider of providers) {\n await this.insertIngestionRecord({\n id: v4(),\n next_action: 'rest',\n provider_name: provider,\n next_action_at,\n ingestion_completed_at: new Date(),\n status: 'resting',\n completion_ticket: 'open',\n });\n }\n\n const ingestionMarksDeleted = await this.purgeTable('ingestion_marks');\n const markEntitiesDeleted = await this.purgeTable(\n 'ingestion_mark_entities',\n );\n\n return { ingestionsDeleted, ingestionMarksDeleted, markEntitiesDeleted };\n }\n\n /**\n * Configures the current ingestion record to ingest a burst.\n * @param ingestionId - string\n */\n async setProviderIngesting(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: { next_action: 'ingest' },\n });\n }\n\n /**\n * Indicates the provider is currently ingesting a burst.\n * @param ingestionId - string\n */\n async setProviderBursting(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: { status: 'bursting' },\n });\n }\n\n /**\n * Finalizes the current ingestion record to indicate that the post-ingestion rest period is complete.\n * @param ingestionId - string\n */\n async setProviderComplete(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: {\n next_action: 'nothing (done)',\n rest_completed_at: new Date(),\n status: 'complete',\n completion_ticket: v4(),\n },\n });\n }\n\n /**\n * Marks ingestion as complete and starts the post-ingestion rest cycle.\n * @param ingestionId - string\n * @param restLength - Duration\n */\n async setProviderResting(ingestionId: string, restLength: Duration) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: {\n next_action: 'rest',\n next_action_at: new Date(Date.now() + restLength.as('milliseconds')),\n ingestion_completed_at: new Date(),\n status: 'resting',\n },\n });\n }\n\n /**\n * Marks ingestion as paused after a burst completes.\n * @param ingestionId - string\n */\n async setProviderInterstitial(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: { attempts: 0, status: 'interstitial' },\n });\n }\n\n /**\n * Starts the cancel process for the current ingestion.\n * @param ingestionId - string\n * @param message - string (optional)\n */\n async setProviderCanceling(ingestionId: string, message?: string) {\n const update: Partial<IngestionUpsert> = {\n next_action: 'cancel',\n last_error: message ? message : undefined,\n next_action_at: new Date(),\n status: 'canceling',\n };\n await this.updateIngestionRecordById({ ingestionId, update });\n }\n\n /**\n * Completes the cancel process and triggers a new ingestion.\n * @param ingestionId - string\n */\n async setProviderCanceled(ingestionId: string) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: {\n next_action: 'nothing (canceled)',\n rest_completed_at: new Date(),\n status: 'complete',\n completion_ticket: v4(),\n },\n });\n }\n\n /**\n * Configures the current ingestion to wait and retry, due to a data source error.\n * @param ingestionId - string\n * @param attempts - number\n * @param error - Error\n * @param backoffLength - number\n */\n async setProviderBackoff(\n ingestionId: string,\n attempts: number,\n error: Error,\n backoffLength: number,\n ) {\n await this.updateIngestionRecordById({\n ingestionId,\n update: {\n next_action: 'backoff',\n attempts: attempts + 1,\n last_error: String(error),\n next_action_at: new Date(Date.now() + backoffLength),\n status: 'backing off',\n },\n });\n }\n\n /**\n * Returns the last record from `ingestion_marks` for the supplied ingestionId.\n * @param ingestionId - string\n * @returns MarkRecord | undefined\n */\n async getLastMark(ingestionId: string) {\n return await this.client.transaction(async tx => {\n const mark = await tx<MarkRecord>('ingestion_marks')\n .where('ingestion_id', ingestionId)\n .orderBy('sequence', 'desc')\n .first();\n return this.#decodeMark(this.client, mark);\n });\n }\n\n /**\n * Returns the first record from `ingestion_marks` for the supplied ingestionId.\n * @param ingestionId - string\n * @returns MarkRecord | undefined\n */\n async getFirstMark(ingestionId: string) {\n return await this.client.transaction(async tx => {\n const mark = await tx<MarkRecord>('ingestion_marks')\n .where('ingestion_id', ingestionId)\n .orderBy('sequence', 'asc')\n .first();\n return this.#decodeMark(this.client, mark);\n });\n }\n\n async getAllMarks(ingestionId: string) {\n return await this.client.transaction(async tx => {\n const marks = await tx<MarkRecord>('ingestion_marks')\n .where('ingestion_id', ingestionId)\n .orderBy('sequence', 'desc');\n return marks.map(m => this.#decodeMark(this.client, m));\n });\n }\n\n /**\n * Performs an insert into the `ingestion_marks` table with the supplied values.\n * @param options - MarkRecordInsert\n */\n async createMark(options: MarkRecordInsert) {\n const { record } = options;\n await this.client.transaction(async tx => {\n await tx('ingestion_marks').insert(record);\n });\n }\n\n // Handles the fact that sqlite does not support json columns; they just\n // persist the stringified data instead\n #decodeMark<T extends MarkRecord | undefined>(knex: Knex, record: T): T {\n if (record && knex.client.config.client.includes('sqlite3')) {\n return {\n ...record,\n cursor: JSON.parse(record.cursor as string),\n };\n }\n return record;\n }\n\n /**\n * Performs an upsert to the `ingestion_mark_entities` table for all deferred entities.\n * @param markId - string\n * @param entities - DeferredEntity[]\n */\n async createMarkEntities(markId: string, entities: DeferredEntity[]) {\n const refs = entities.map(e => stringifyEntityRef(e.entity));\n\n await this.client.transaction(async tx => {\n const existingRefsArray = (\n await tx<{ ref: string }>('ingestion_mark_entities')\n .select('ref')\n .whereIn('ref', refs)\n ).map(e => e.ref);\n\n const existingRefsSet = new Set(existingRefsArray);\n\n const newRefs = refs.filter(e => !existingRefsSet.has(e));\n\n await tx('ingestion_mark_entities')\n .update('ingestion_mark_id', markId)\n .whereIn('ref', existingRefsArray);\n\n if (newRefs.length > 0) {\n await tx('ingestion_mark_entities').insert(\n newRefs.map(ref => ({\n id: v4(),\n ingestion_mark_id: markId,\n ref,\n })),\n );\n }\n });\n }\n\n /**\n * Deletes the entire content of a table, and returns the number of records deleted.\n * @param table - string\n * @returns number\n */\n async purgeTable(table: string) {\n return await this.client.transaction(async tx => {\n return await tx(table).delete();\n });\n }\n\n /**\n * Returns a list of all providers.\n * @returns string[]\n */\n async listProviders() {\n return await this.client.transaction(async tx => {\n const providers = await tx<{ provider_name: string }>(\n 'ingestions',\n ).distinct('provider_name');\n return providers.map(entry => entry.provider_name);\n });\n }\n\n async updateByName(provider: string, update: Partial<IngestionUpsert>) {\n await this.updateIngestionRecordByProvider(provider, update);\n }\n}\n"],"names":["v4","stringifyEntityRef"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var node_perf_hooks = require('node:perf_hooks');
|
|
4
4
|
var luxon = require('luxon');
|
|
5
|
-
var
|
|
5
|
+
var node_crypto = require('node:crypto');
|
|
6
6
|
var errors = require('@backstage/errors');
|
|
7
7
|
|
|
8
8
|
class IncrementalIngestionEngine {
|
|
@@ -229,7 +229,7 @@ class IncrementalIngestionEngine {
|
|
|
229
229
|
this.options.logger.debug(
|
|
230
230
|
`incremental-engine: Ingestion '${id}': MARK ${entities ? entities.length : 0} entities, cursor: ${cursor ? JSON.stringify(cursor) : "none"}, done: ${done}`
|
|
231
231
|
);
|
|
232
|
-
const markId =
|
|
232
|
+
const markId = node_crypto.randomUUID();
|
|
233
233
|
await this.manager.createMark({
|
|
234
234
|
record: {
|
|
235
235
|
id: markId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncrementalIngestionEngine.cjs.js","sources":["../../src/engine/IncrementalIngestionEngine.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { DeferredEntity } from '@backstage/plugin-catalog-node';\nimport { MetricsServiceGauge } from '@backstage/backend-plugin-api/alpha';\nimport { IterationEngine, IterationEngineOptions } from '../types';\nimport { IncrementalIngestionDatabaseManager } from '../database/IncrementalIngestionDatabaseManager';\nimport { performance } from 'node:perf_hooks';\nimport { Duration } from 'luxon';\nimport { v4 } from 'uuid';\nimport { stringifyError, toError } from '@backstage/errors';\nimport { EventParams } from '@backstage/plugin-events-node';\nimport { HumanDuration } from '@backstage/types';\n\nexport class IncrementalIngestionEngine implements IterationEngine {\n private readonly restLength: Duration;\n private readonly burstLength: Duration;\n private readonly backoff: HumanDuration[];\n private readonly lastStarted: MetricsServiceGauge;\n private readonly lastCompleted: MetricsServiceGauge;\n\n private manager: IncrementalIngestionDatabaseManager;\n\n constructor(private options: IterationEngineOptions) {\n this.manager = options.manager;\n this.restLength = Duration.fromObject(options.restLength);\n this.burstLength = Duration.fromObject(options.burstLength);\n this.backoff = options.backoff ?? [\n { minutes: 1 },\n { minutes: 5 },\n { minutes: 30 },\n { hours: 3 },\n ];\n\n this.lastStarted = options.metrics.createGauge(\n 'catalog_incremental.ingestions.started',\n {\n description: 'Epoch timestamp when the ingestion was last started',\n unit: 's',\n },\n );\n this.lastCompleted = options.metrics.createGauge(\n 'catalog_incremental.ingestions.completed',\n {\n description: 'Epoch timestamp when the ingestion was last completed',\n unit: 's',\n },\n );\n }\n\n async taskFn(signal: AbortSignal) {\n try {\n this.options.logger.debug('Begin tick');\n await this.handleNextAction(signal);\n } catch (error) {\n this.options.logger.error(`${error}`);\n throw error;\n } finally {\n this.options.logger.debug('End tick');\n }\n }\n\n async handleNextAction(signal: AbortSignal) {\n await this.options.ready;\n\n const result = await this.getCurrentAction();\n if (result) {\n const { ingestionId, nextActionAt, nextAction, attempts } = result;\n\n switch (nextAction) {\n case 'rest':\n if (Date.now() > nextActionAt) {\n await this.manager.clearFinishedIngestions(\n this.options.provider.getProviderName(),\n );\n this.options.logger.debug(\n `incremental-engine: Ingestion ${ingestionId} rest period complete. Ingestion will start again`,\n );\n\n this.lastStarted.record(Date.now() / 1000, {\n providerName: this.options.provider.getProviderName(),\n });\n await this.manager.setProviderComplete(ingestionId);\n } else {\n this.options.logger.debug(\n `incremental-engine: Ingestion '${ingestionId}' rest period continuing`,\n );\n }\n break;\n case 'ingest':\n try {\n await this.manager.setProviderBursting(ingestionId);\n const done = await this.ingestOneBurst(ingestionId, signal);\n if (done) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${ingestionId}' complete, transitioning to rest period of ${this.restLength.toHuman()}`,\n );\n this.lastCompleted.record(Date.now() / 1000, {\n providerName: this.options.provider.getProviderName(),\n status: 'completed',\n });\n await this.manager.setProviderResting(\n ingestionId,\n this.restLength,\n );\n } else {\n await this.manager.setProviderInterstitial(ingestionId);\n this.options.logger.debug(\n `incremental-engine: Ingestion '${ingestionId}' continuing`,\n );\n }\n } catch (error) {\n const err = toError(error);\n if (err.message === 'CANCEL') {\n this.options.logger.info(\n `incremental-engine: Ingestion '${ingestionId}' canceled`,\n );\n await this.manager.setProviderCanceling(ingestionId, err.message);\n } else {\n const currentBackoff = Duration.fromObject(\n this.backoff[Math.min(this.backoff.length - 1, attempts)],\n );\n\n const backoffLength = currentBackoff.as('milliseconds');\n this.options.logger.error(\n `incremental-engine: Ingestion '${ingestionId}' failed`,\n error,\n );\n\n const truncatedError = stringifyError(error).substring(0, 700);\n this.options.logger.error(\n `incremental-engine: Ingestion '${ingestionId}' threw an error during ingestion burst. Ingestion will backoff for ${currentBackoff.toHuman()} (${truncatedError})`,\n );\n this.lastCompleted.record(Date.now() / 1000, {\n providerName: this.options.provider.getProviderName(),\n status: 'failed',\n });\n\n await this.manager.setProviderBackoff(\n ingestionId,\n attempts,\n error as Error,\n backoffLength,\n );\n }\n }\n break;\n case 'backoff':\n if (Date.now() > nextActionAt) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${ingestionId}' backoff complete, will attempt to resume`,\n );\n await this.manager.setProviderIngesting(ingestionId);\n } else {\n this.options.logger.debug(\n `incremental-engine: Ingestion '${ingestionId}' backoff continuing`,\n );\n }\n break;\n case 'cancel':\n this.options.logger.info(\n `incremental-engine: Ingestion '${ingestionId}' canceling, will restart`,\n );\n await this.manager.setProviderCanceled(ingestionId);\n break;\n default:\n this.options.logger.error(\n `incremental-engine: Ingestion '${ingestionId}' received unknown action '${nextAction}'`,\n );\n }\n } else {\n this.options.logger.error(\n `incremental-engine: Engine tried to create duplicate ingestion record for provider '${this.options.provider.getProviderName()}'.`,\n );\n }\n }\n\n async getCurrentAction() {\n const providerName = this.options.provider.getProviderName();\n const record = await this.manager.getCurrentIngestionRecord(providerName);\n if (record) {\n this.options.logger.debug(\n `incremental-engine: Ingestion record found: '${record.id}'`,\n );\n return {\n ingestionId: record.id,\n nextAction: record.next_action as 'rest' | 'ingest' | 'backoff',\n attempts: record.attempts as number,\n nextActionAt: record.next_action_at.valueOf() as number,\n };\n }\n const result = await this.manager.createProviderIngestionRecord(\n providerName,\n );\n if (result) {\n this.options.logger.info(\n `incremental-engine: Ingestion record created: '${result.ingestionId}'`,\n );\n }\n return result;\n }\n\n async ingestOneBurst(id: string, signal: AbortSignal) {\n const lastMark = await this.manager.getLastMark(id);\n\n const cursor = lastMark ? lastMark.cursor : undefined;\n let sequence = lastMark ? lastMark.sequence + 1 : 0;\n\n const start = performance.now();\n let count = 0;\n let done = false;\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}' burst initiated`,\n );\n\n await this.options.provider.around(async (context: unknown) => {\n let next = await this.options.provider.next(context, cursor);\n count++;\n for (;;) {\n done = next.done;\n await this.mark({\n id,\n sequence,\n entities: next?.entities,\n done: next.done,\n cursor: next?.cursor,\n });\n if (signal.aborted || next.done) {\n break;\n } else if (\n performance.now() - start >\n this.burstLength.as('milliseconds')\n ) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}' burst ending after ${this.burstLength.toHuman()}.`,\n );\n break;\n } else {\n next = await this.options.provider.next(context, next.cursor);\n count++;\n sequence++;\n }\n }\n });\n\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}' burst complete. (${count} batches in ${Math.round(\n performance.now() - start,\n )}ms).`,\n );\n return done;\n }\n\n async mark(options: {\n id: string;\n sequence: number;\n entities?: DeferredEntity[];\n done: boolean;\n cursor?: unknown;\n }) {\n const { id, sequence, entities, done, cursor } = options;\n this.options.logger.debug(\n `incremental-engine: Ingestion '${id}': MARK ${\n entities ? entities.length : 0\n } entities, cursor: ${\n cursor ? JSON.stringify(cursor) : 'none'\n }, done: ${done}`,\n );\n const markId = v4();\n\n await this.manager.createMark({\n record: {\n id: markId,\n ingestion_id: id,\n cursor,\n sequence,\n },\n });\n\n if (entities && entities.length > 0) {\n await this.manager.createMarkEntities(markId, entities);\n }\n\n const added =\n entities?.map(deferred => ({\n ...deferred,\n entity: {\n ...deferred.entity,\n metadata: {\n ...deferred.entity.metadata,\n annotations: {\n ...deferred.entity.metadata.annotations,\n },\n },\n },\n })) ?? [];\n\n const removed: { entityRef: string }[] = [];\n\n if (done) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}': Final page reached, calculating removed entities`,\n );\n const result = await this.manager.computeRemoved(\n this.options.provider.getProviderName(),\n id,\n );\n\n const { total } = result;\n\n let doRemoval = true;\n if (this.options.rejectEmptySourceCollections) {\n if (total === 0) {\n this.options.logger.error(\n `incremental-engine: Ingestion '${id}': Rejecting empty entity collection!`,\n );\n doRemoval = false;\n }\n }\n\n if (this.options.rejectRemovalsAbovePercentage) {\n // If the total entities upserted in this ingestion is 0, then\n // 100% of entities are stale and marked for removal.\n const percentRemoved =\n total > 0 ? (result.removed.length / total) * 100 : 100;\n if (percentRemoved <= this.options.rejectRemovalsAbovePercentage) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}': Removing ${result.removed.length} entities that have no matching assets`,\n );\n } else {\n const notice = `Attempted to remove ${percentRemoved}% of matching entities!`;\n this.options.logger.error(\n `incremental-engine: Ingestion '${id}': ${notice}`,\n );\n await this.manager.updateIngestionRecordById({\n ingestionId: id,\n update: {\n last_error: `REMOVAL_THRESHOLD exceeded on ingestion mark ${markId}: ${notice}`,\n },\n });\n doRemoval = false;\n }\n }\n if (doRemoval) {\n for (const entityRef of result.removed) {\n removed.push(entityRef);\n }\n }\n }\n\n await this.options.connection.applyMutation({\n type: 'delta',\n added,\n removed,\n });\n }\n\n async onEvent(params: EventParams): Promise<void> {\n const { topic } = params;\n if (!this.supportsEventTopics().includes(topic)) {\n return;\n }\n\n const { logger, provider, connection } = this.options;\n const providerName = provider.getProviderName();\n logger.debug(`incremental-engine: ${providerName} received ${topic} event`);\n\n if (!provider.eventHandler) {\n return;\n }\n\n const result = await provider.eventHandler.onEvent(params);\n\n if (result.type === 'delta') {\n if (result.added.length > 0) {\n const ingestionRecord = await this.manager.getCurrentIngestionRecord(\n providerName,\n );\n\n if (!ingestionRecord) {\n logger.debug(\n `incremental-engine: ${providerName} skipping delta addition because incremental ingestion is restarting.`,\n );\n } else {\n const mark =\n ingestionRecord.status === 'resting'\n ? await this.manager.getLastMark(ingestionRecord.id)\n : await this.manager.getFirstMark(ingestionRecord.id);\n\n if (!mark) {\n throw new Error(\n `Cannot apply delta, page records are missing! Please re-run incremental ingestion for ${providerName}.`,\n );\n }\n await this.manager.createMarkEntities(mark.id, result.added);\n }\n }\n\n if (result.removed.length > 0) {\n await this.manager.deleteEntityRecordsByRef(result.removed);\n }\n\n await connection.applyMutation(result);\n logger.debug(\n `incremental-engine: ${providerName} processed delta from '${topic}' event`,\n );\n } else {\n logger.debug(\n `incremental-engine: ${providerName} ignored event from topic '${topic}'`,\n );\n }\n }\n\n supportsEventTopics(): string[] {\n const { provider } = this.options;\n const topics = provider.eventHandler\n ? provider.eventHandler.supportsEventTopics()\n : [];\n return topics;\n }\n}\n"],"names":["Duration","toError","stringifyError","performance","v4"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"IncrementalIngestionEngine.cjs.js","sources":["../../src/engine/IncrementalIngestionEngine.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { DeferredEntity } from '@backstage/plugin-catalog-node';\nimport { MetricsServiceGauge } from '@backstage/backend-plugin-api/alpha';\nimport { IterationEngine, IterationEngineOptions } from '../types';\nimport { IncrementalIngestionDatabaseManager } from '../database/IncrementalIngestionDatabaseManager';\nimport { performance } from 'node:perf_hooks';\nimport { Duration } from 'luxon';\nimport { randomUUID as v4 } from 'node:crypto';\nimport { stringifyError, toError } from '@backstage/errors';\nimport { EventParams } from '@backstage/plugin-events-node';\nimport { HumanDuration } from '@backstage/types';\n\nexport class IncrementalIngestionEngine implements IterationEngine {\n private readonly restLength: Duration;\n private readonly burstLength: Duration;\n private readonly backoff: HumanDuration[];\n private readonly lastStarted: MetricsServiceGauge;\n private readonly lastCompleted: MetricsServiceGauge;\n\n private manager: IncrementalIngestionDatabaseManager;\n\n constructor(private options: IterationEngineOptions) {\n this.manager = options.manager;\n this.restLength = Duration.fromObject(options.restLength);\n this.burstLength = Duration.fromObject(options.burstLength);\n this.backoff = options.backoff ?? [\n { minutes: 1 },\n { minutes: 5 },\n { minutes: 30 },\n { hours: 3 },\n ];\n\n this.lastStarted = options.metrics.createGauge(\n 'catalog_incremental.ingestions.started',\n {\n description: 'Epoch timestamp when the ingestion was last started',\n unit: 's',\n },\n );\n this.lastCompleted = options.metrics.createGauge(\n 'catalog_incremental.ingestions.completed',\n {\n description: 'Epoch timestamp when the ingestion was last completed',\n unit: 's',\n },\n );\n }\n\n async taskFn(signal: AbortSignal) {\n try {\n this.options.logger.debug('Begin tick');\n await this.handleNextAction(signal);\n } catch (error) {\n this.options.logger.error(`${error}`);\n throw error;\n } finally {\n this.options.logger.debug('End tick');\n }\n }\n\n async handleNextAction(signal: AbortSignal) {\n await this.options.ready;\n\n const result = await this.getCurrentAction();\n if (result) {\n const { ingestionId, nextActionAt, nextAction, attempts } = result;\n\n switch (nextAction) {\n case 'rest':\n if (Date.now() > nextActionAt) {\n await this.manager.clearFinishedIngestions(\n this.options.provider.getProviderName(),\n );\n this.options.logger.debug(\n `incremental-engine: Ingestion ${ingestionId} rest period complete. Ingestion will start again`,\n );\n\n this.lastStarted.record(Date.now() / 1000, {\n providerName: this.options.provider.getProviderName(),\n });\n await this.manager.setProviderComplete(ingestionId);\n } else {\n this.options.logger.debug(\n `incremental-engine: Ingestion '${ingestionId}' rest period continuing`,\n );\n }\n break;\n case 'ingest':\n try {\n await this.manager.setProviderBursting(ingestionId);\n const done = await this.ingestOneBurst(ingestionId, signal);\n if (done) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${ingestionId}' complete, transitioning to rest period of ${this.restLength.toHuman()}`,\n );\n this.lastCompleted.record(Date.now() / 1000, {\n providerName: this.options.provider.getProviderName(),\n status: 'completed',\n });\n await this.manager.setProviderResting(\n ingestionId,\n this.restLength,\n );\n } else {\n await this.manager.setProviderInterstitial(ingestionId);\n this.options.logger.debug(\n `incremental-engine: Ingestion '${ingestionId}' continuing`,\n );\n }\n } catch (error) {\n const err = toError(error);\n if (err.message === 'CANCEL') {\n this.options.logger.info(\n `incremental-engine: Ingestion '${ingestionId}' canceled`,\n );\n await this.manager.setProviderCanceling(ingestionId, err.message);\n } else {\n const currentBackoff = Duration.fromObject(\n this.backoff[Math.min(this.backoff.length - 1, attempts)],\n );\n\n const backoffLength = currentBackoff.as('milliseconds');\n this.options.logger.error(\n `incremental-engine: Ingestion '${ingestionId}' failed`,\n error,\n );\n\n const truncatedError = stringifyError(error).substring(0, 700);\n this.options.logger.error(\n `incremental-engine: Ingestion '${ingestionId}' threw an error during ingestion burst. Ingestion will backoff for ${currentBackoff.toHuman()} (${truncatedError})`,\n );\n this.lastCompleted.record(Date.now() / 1000, {\n providerName: this.options.provider.getProviderName(),\n status: 'failed',\n });\n\n await this.manager.setProviderBackoff(\n ingestionId,\n attempts,\n error as Error,\n backoffLength,\n );\n }\n }\n break;\n case 'backoff':\n if (Date.now() > nextActionAt) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${ingestionId}' backoff complete, will attempt to resume`,\n );\n await this.manager.setProviderIngesting(ingestionId);\n } else {\n this.options.logger.debug(\n `incremental-engine: Ingestion '${ingestionId}' backoff continuing`,\n );\n }\n break;\n case 'cancel':\n this.options.logger.info(\n `incremental-engine: Ingestion '${ingestionId}' canceling, will restart`,\n );\n await this.manager.setProviderCanceled(ingestionId);\n break;\n default:\n this.options.logger.error(\n `incremental-engine: Ingestion '${ingestionId}' received unknown action '${nextAction}'`,\n );\n }\n } else {\n this.options.logger.error(\n `incremental-engine: Engine tried to create duplicate ingestion record for provider '${this.options.provider.getProviderName()}'.`,\n );\n }\n }\n\n async getCurrentAction() {\n const providerName = this.options.provider.getProviderName();\n const record = await this.manager.getCurrentIngestionRecord(providerName);\n if (record) {\n this.options.logger.debug(\n `incremental-engine: Ingestion record found: '${record.id}'`,\n );\n return {\n ingestionId: record.id,\n nextAction: record.next_action as 'rest' | 'ingest' | 'backoff',\n attempts: record.attempts as number,\n nextActionAt: record.next_action_at.valueOf() as number,\n };\n }\n const result = await this.manager.createProviderIngestionRecord(\n providerName,\n );\n if (result) {\n this.options.logger.info(\n `incremental-engine: Ingestion record created: '${result.ingestionId}'`,\n );\n }\n return result;\n }\n\n async ingestOneBurst(id: string, signal: AbortSignal) {\n const lastMark = await this.manager.getLastMark(id);\n\n const cursor = lastMark ? lastMark.cursor : undefined;\n let sequence = lastMark ? lastMark.sequence + 1 : 0;\n\n const start = performance.now();\n let count = 0;\n let done = false;\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}' burst initiated`,\n );\n\n await this.options.provider.around(async (context: unknown) => {\n let next = await this.options.provider.next(context, cursor);\n count++;\n for (;;) {\n done = next.done;\n await this.mark({\n id,\n sequence,\n entities: next?.entities,\n done: next.done,\n cursor: next?.cursor,\n });\n if (signal.aborted || next.done) {\n break;\n } else if (\n performance.now() - start >\n this.burstLength.as('milliseconds')\n ) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}' burst ending after ${this.burstLength.toHuman()}.`,\n );\n break;\n } else {\n next = await this.options.provider.next(context, next.cursor);\n count++;\n sequence++;\n }\n }\n });\n\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}' burst complete. (${count} batches in ${Math.round(\n performance.now() - start,\n )}ms).`,\n );\n return done;\n }\n\n async mark(options: {\n id: string;\n sequence: number;\n entities?: DeferredEntity[];\n done: boolean;\n cursor?: unknown;\n }) {\n const { id, sequence, entities, done, cursor } = options;\n this.options.logger.debug(\n `incremental-engine: Ingestion '${id}': MARK ${\n entities ? entities.length : 0\n } entities, cursor: ${\n cursor ? JSON.stringify(cursor) : 'none'\n }, done: ${done}`,\n );\n const markId = v4();\n\n await this.manager.createMark({\n record: {\n id: markId,\n ingestion_id: id,\n cursor,\n sequence,\n },\n });\n\n if (entities && entities.length > 0) {\n await this.manager.createMarkEntities(markId, entities);\n }\n\n const added =\n entities?.map(deferred => ({\n ...deferred,\n entity: {\n ...deferred.entity,\n metadata: {\n ...deferred.entity.metadata,\n annotations: {\n ...deferred.entity.metadata.annotations,\n },\n },\n },\n })) ?? [];\n\n const removed: { entityRef: string }[] = [];\n\n if (done) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}': Final page reached, calculating removed entities`,\n );\n const result = await this.manager.computeRemoved(\n this.options.provider.getProviderName(),\n id,\n );\n\n const { total } = result;\n\n let doRemoval = true;\n if (this.options.rejectEmptySourceCollections) {\n if (total === 0) {\n this.options.logger.error(\n `incremental-engine: Ingestion '${id}': Rejecting empty entity collection!`,\n );\n doRemoval = false;\n }\n }\n\n if (this.options.rejectRemovalsAbovePercentage) {\n // If the total entities upserted in this ingestion is 0, then\n // 100% of entities are stale and marked for removal.\n const percentRemoved =\n total > 0 ? (result.removed.length / total) * 100 : 100;\n if (percentRemoved <= this.options.rejectRemovalsAbovePercentage) {\n this.options.logger.info(\n `incremental-engine: Ingestion '${id}': Removing ${result.removed.length} entities that have no matching assets`,\n );\n } else {\n const notice = `Attempted to remove ${percentRemoved}% of matching entities!`;\n this.options.logger.error(\n `incremental-engine: Ingestion '${id}': ${notice}`,\n );\n await this.manager.updateIngestionRecordById({\n ingestionId: id,\n update: {\n last_error: `REMOVAL_THRESHOLD exceeded on ingestion mark ${markId}: ${notice}`,\n },\n });\n doRemoval = false;\n }\n }\n if (doRemoval) {\n for (const entityRef of result.removed) {\n removed.push(entityRef);\n }\n }\n }\n\n await this.options.connection.applyMutation({\n type: 'delta',\n added,\n removed,\n });\n }\n\n async onEvent(params: EventParams): Promise<void> {\n const { topic } = params;\n if (!this.supportsEventTopics().includes(topic)) {\n return;\n }\n\n const { logger, provider, connection } = this.options;\n const providerName = provider.getProviderName();\n logger.debug(`incremental-engine: ${providerName} received ${topic} event`);\n\n if (!provider.eventHandler) {\n return;\n }\n\n const result = await provider.eventHandler.onEvent(params);\n\n if (result.type === 'delta') {\n if (result.added.length > 0) {\n const ingestionRecord = await this.manager.getCurrentIngestionRecord(\n providerName,\n );\n\n if (!ingestionRecord) {\n logger.debug(\n `incremental-engine: ${providerName} skipping delta addition because incremental ingestion is restarting.`,\n );\n } else {\n const mark =\n ingestionRecord.status === 'resting'\n ? await this.manager.getLastMark(ingestionRecord.id)\n : await this.manager.getFirstMark(ingestionRecord.id);\n\n if (!mark) {\n throw new Error(\n `Cannot apply delta, page records are missing! Please re-run incremental ingestion for ${providerName}.`,\n );\n }\n await this.manager.createMarkEntities(mark.id, result.added);\n }\n }\n\n if (result.removed.length > 0) {\n await this.manager.deleteEntityRecordsByRef(result.removed);\n }\n\n await connection.applyMutation(result);\n logger.debug(\n `incremental-engine: ${providerName} processed delta from '${topic}' event`,\n );\n } else {\n logger.debug(\n `incremental-engine: ${providerName} ignored event from topic '${topic}'`,\n );\n }\n }\n\n supportsEventTopics(): string[] {\n const { provider } = this.options;\n const topics = provider.eventHandler\n ? provider.eventHandler.supportsEventTopics()\n : [];\n return topics;\n }\n}\n"],"names":["Duration","toError","stringifyError","performance","v4"],"mappings":";;;;;;;AA2BO,MAAM,0BAAA,CAAsD;AAAA,EASjE,YAAoB,OAAA,EAAiC;AAAjC,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAClB,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA;AACvB,IAAA,IAAA,CAAK,UAAA,GAAaA,cAAA,CAAS,UAAA,CAAW,OAAA,CAAQ,UAAU,CAAA;AACxD,IAAA,IAAA,CAAK,WAAA,GAAcA,cAAA,CAAS,UAAA,CAAW,OAAA,CAAQ,WAAW,CAAA;AAC1D,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW;AAAA,MAChC,EAAE,SAAS,CAAA,EAAE;AAAA,MACb,EAAE,SAAS,CAAA,EAAE;AAAA,MACb,EAAE,SAAS,EAAA,EAAG;AAAA,MACd,EAAE,OAAO,CAAA;AAAE,KACb;AAEA,IAAA,IAAA,CAAK,WAAA,GAAc,QAAQ,OAAA,CAAQ,WAAA;AAAA,MACjC,wCAAA;AAAA,MACA;AAAA,QACE,WAAA,EAAa,qDAAA;AAAA,QACb,IAAA,EAAM;AAAA;AACR,KACF;AACA,IAAA,IAAA,CAAK,aAAA,GAAgB,QAAQ,OAAA,CAAQ,WAAA;AAAA,MACnC,0CAAA;AAAA,MACA;AAAA,QACE,WAAA,EAAa,uDAAA;AAAA,QACb,IAAA,EAAM;AAAA;AACR,KACF;AAAA,EACF;AAAA,EAjCiB,UAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,aAAA;AAAA,EAET,OAAA;AAAA,EA6BR,MAAM,OAAO,MAAA,EAAqB;AAChC,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,YAAY,CAAA;AACtC,MAAA,MAAM,IAAA,CAAK,iBAAiB,MAAM,CAAA;AAAA,IACpC,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,CAAE,CAAA;AACpC,MAAA,MAAM,KAAA;AAAA,IACR,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,OAAA,CAAQ,MAAA,CAAO,KAAA,CAAM,UAAU,CAAA;AAAA,IACtC;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,MAAA,EAAqB;AAC1C,IAAA,MAAM,KAAK,OAAA,CAAQ,KAAA;AAEnB,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,gBAAA,EAAiB;AAC3C,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,MAAM,EAAE,WAAA,EAAa,YAAA,EAAc,UAAA,EAAY,UAAS,GAAI,MAAA;AAE5D,MAAA,QAAQ,UAAA;AAAY,QAClB,KAAK,MAAA;AACH,UAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,YAAA,EAAc;AAC7B,YAAA,MAAM,KAAK,OAAA,CAAQ,uBAAA;AAAA,cACjB,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,eAAA;AAAgB,aACxC;AACA,YAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,cAClB,iCAAiC,WAAW,CAAA,iDAAA;AAAA,aAC9C;AAEA,YAAA,IAAA,CAAK,WAAA,CAAY,MAAA,CAAO,IAAA,CAAK,GAAA,KAAQ,GAAA,EAAM;AAAA,cACzC,YAAA,EAAc,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,eAAA;AAAgB,aACrD,CAAA;AACD,YAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,mBAAA,CAAoB,WAAW,CAAA;AAAA,UACpD,CAAA,MAAO;AACL,YAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,cAClB,kCAAkC,WAAW,CAAA,wBAAA;AAAA,aAC/C;AAAA,UACF;AACA,UAAA;AAAA,QACF,KAAK,QAAA;AACH,UAAA,IAAI;AACF,YAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,mBAAA,CAAoB,WAAW,CAAA;AAClD,YAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,cAAA,CAAe,aAAa,MAAM,CAAA;AAC1D,YAAA,IAAI,IAAA,EAAM;AACR,cAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,gBAClB,kCAAkC,WAAW,CAAA,4CAAA,EAA+C,IAAA,CAAK,UAAA,CAAW,SAAS,CAAA;AAAA,eACvH;AACA,cAAA,IAAA,CAAK,aAAA,CAAc,MAAA,CAAO,IAAA,CAAK,GAAA,KAAQ,GAAA,EAAM;AAAA,gBAC3C,YAAA,EAAc,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,eAAA,EAAgB;AAAA,gBACpD,MAAA,EAAQ;AAAA,eACT,CAAA;AACD,cAAA,MAAM,KAAK,OAAA,CAAQ,kBAAA;AAAA,gBACjB,WAAA;AAAA,gBACA,IAAA,CAAK;AAAA,eACP;AAAA,YACF,CAAA,MAAO;AACL,cAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,uBAAA,CAAwB,WAAW,CAAA;AACtD,cAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,gBAClB,kCAAkC,WAAW,CAAA,YAAA;AAAA,eAC/C;AAAA,YACF;AAAA,UACF,SAAS,KAAA,EAAO;AACd,YAAA,MAAM,GAAA,GAAMC,eAAQ,KAAK,CAAA;AACzB,YAAA,IAAI,GAAA,CAAI,YAAY,QAAA,EAAU;AAC5B,cAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,gBAClB,kCAAkC,WAAW,CAAA,UAAA;AAAA,eAC/C;AACA,cAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,oBAAA,CAAqB,WAAA,EAAa,IAAI,OAAO,CAAA;AAAA,YAClE,CAAA,MAAO;AACL,cAAA,MAAM,iBAAiBD,cAAA,CAAS,UAAA;AAAA,gBAC9B,IAAA,CAAK,QAAQ,IAAA,CAAK,GAAA,CAAI,KAAK,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG,QAAQ,CAAC;AAAA,eAC1D;AAEA,cAAA,MAAM,aAAA,GAAgB,cAAA,CAAe,EAAA,CAAG,cAAc,CAAA;AACtD,cAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,gBAClB,kCAAkC,WAAW,CAAA,QAAA,CAAA;AAAA,gBAC7C;AAAA,eACF;AAEA,cAAA,MAAM,iBAAiBE,qBAAA,CAAe,KAAK,CAAA,CAAE,SAAA,CAAU,GAAG,GAAG,CAAA;AAC7D,cAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,gBAClB,kCAAkC,WAAW,CAAA,oEAAA,EAAuE,eAAe,OAAA,EAAS,KAAK,cAAc,CAAA,CAAA;AAAA,eACjK;AACA,cAAA,IAAA,CAAK,aAAA,CAAc,MAAA,CAAO,IAAA,CAAK,GAAA,KAAQ,GAAA,EAAM;AAAA,gBAC3C,YAAA,EAAc,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,eAAA,EAAgB;AAAA,gBACpD,MAAA,EAAQ;AAAA,eACT,CAAA;AAED,cAAA,MAAM,KAAK,OAAA,CAAQ,kBAAA;AAAA,gBACjB,WAAA;AAAA,gBACA,QAAA;AAAA,gBACA,KAAA;AAAA,gBACA;AAAA,eACF;AAAA,YACF;AAAA,UACF;AACA,UAAA;AAAA,QACF,KAAK,SAAA;AACH,UAAA,IAAI,IAAA,CAAK,GAAA,EAAI,GAAI,YAAA,EAAc;AAC7B,YAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,cAClB,kCAAkC,WAAW,CAAA,0CAAA;AAAA,aAC/C;AACA,YAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,oBAAA,CAAqB,WAAW,CAAA;AAAA,UACrD,CAAA,MAAO;AACL,YAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,cAClB,kCAAkC,WAAW,CAAA,oBAAA;AAAA,aAC/C;AAAA,UACF;AACA,UAAA;AAAA,QACF,KAAK,QAAA;AACH,UAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,YAClB,kCAAkC,WAAW,CAAA,yBAAA;AAAA,WAC/C;AACA,UAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,mBAAA,CAAoB,WAAW,CAAA;AAClD,UAAA;AAAA,QACF;AACE,UAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,YAClB,CAAA,+BAAA,EAAkC,WAAW,CAAA,2BAAA,EAA8B,UAAU,CAAA,CAAA;AAAA,WACvF;AAAA;AACJ,IACF,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,QAClB,CAAA,oFAAA,EAAuF,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,iBAAiB,CAAA,EAAA;AAAA,OAChI;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,gBAAA,GAAmB;AACvB,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,eAAA,EAAgB;AAC3D,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,0BAA0B,YAAY,CAAA;AACxE,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,QAClB,CAAA,6CAAA,EAAgD,OAAO,EAAE,CAAA,CAAA;AAAA,OAC3D;AACA,MAAA,OAAO;AAAA,QACL,aAAa,MAAA,CAAO,EAAA;AAAA,QACpB,YAAY,MAAA,CAAO,WAAA;AAAA,QACnB,UAAU,MAAA,CAAO,QAAA;AAAA,QACjB,YAAA,EAAc,MAAA,CAAO,cAAA,CAAe,OAAA;AAAQ,OAC9C;AAAA,IACF;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,6BAAA;AAAA,MAChC;AAAA,KACF;AACA,IAAA,IAAI,MAAA,EAAQ;AACV,MAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,QAClB,CAAA,+CAAA,EAAkD,OAAO,WAAW,CAAA,CAAA;AAAA,OACtE;AAAA,IACF;AACA,IAAA,OAAO,MAAA;AAAA,EACT;AAAA,EAEA,MAAM,cAAA,CAAe,EAAA,EAAY,MAAA,EAAqB;AACpD,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,YAAY,EAAE,CAAA;AAElD,IAAA,MAAM,MAAA,GAAS,QAAA,GAAW,QAAA,CAAS,MAAA,GAAS,MAAA;AAC5C,IAAA,IAAI,QAAA,GAAW,QAAA,GAAW,QAAA,CAAS,QAAA,GAAW,CAAA,GAAI,CAAA;AAElD,IAAA,MAAM,KAAA,GAAQC,4BAAY,GAAA,EAAI;AAC9B,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,IAAI,IAAA,GAAO,KAAA;AACX,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,MAClB,kCAAkC,EAAE,CAAA,iBAAA;AAAA,KACtC;AAEA,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,MAAA,CAAO,OAAO,OAAA,KAAqB;AAC7D,MAAA,IAAI,OAAO,MAAM,IAAA,CAAK,QAAQ,QAAA,CAAS,IAAA,CAAK,SAAS,MAAM,CAAA;AAC3D,MAAA,KAAA,EAAA;AACA,MAAA,WAAS;AACP,QAAA,IAAA,GAAO,IAAA,CAAK,IAAA;AACZ,QAAA,MAAM,KAAK,IAAA,CAAK;AAAA,UACd,EAAA;AAAA,UACA,QAAA;AAAA,UACA,UAAU,IAAA,EAAM,QAAA;AAAA,UAChB,MAAM,IAAA,CAAK,IAAA;AAAA,UACX,QAAQ,IAAA,EAAM;AAAA,SACf,CAAA;AACD,QAAA,IAAI,MAAA,CAAO,OAAA,IAAW,IAAA,CAAK,IAAA,EAAM;AAC/B,UAAA;AAAA,QACF,CAAA,MAAA,IACEA,4BAAY,GAAA,EAAI,GAAI,QACpB,IAAA,CAAK,WAAA,CAAY,EAAA,CAAG,cAAc,CAAA,EAClC;AACA,UAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,YAClB,kCAAkC,EAAE,CAAA,qBAAA,EAAwB,IAAA,CAAK,WAAA,CAAY,SAAS,CAAA,CAAA;AAAA,WACxF;AACA,UAAA;AAAA,QACF,CAAA,MAAO;AACL,UAAA,IAAA,GAAO,MAAM,IAAA,CAAK,OAAA,CAAQ,SAAS,IAAA,CAAK,OAAA,EAAS,KAAK,MAAM,CAAA;AAC5D,UAAA,KAAA,EAAA;AACA,UAAA,QAAA,EAAA;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC,CAAA;AAED,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,MAClB,CAAA,+BAAA,EAAkC,EAAE,CAAA,mBAAA,EAAsB,KAAK,eAAe,IAAA,CAAK,KAAA;AAAA,QACjFA,2BAAA,CAAY,KAAI,GAAI;AAAA,OACrB,CAAA,IAAA;AAAA,KACH;AACA,IAAA,OAAO,IAAA;AAAA,EACT;AAAA,EAEA,MAAM,KAAK,OAAA,EAMR;AACD,IAAA,MAAM,EAAE,EAAA,EAAI,QAAA,EAAU,QAAA,EAAU,IAAA,EAAM,QAAO,GAAI,OAAA;AACjD,IAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,MAClB,CAAA,+BAAA,EAAkC,EAAE,CAAA,QAAA,EAClC,QAAA,GAAW,SAAS,MAAA,GAAS,CAC/B,CAAA,mBAAA,EACE,MAAA,GAAS,KAAK,SAAA,CAAU,MAAM,CAAA,GAAI,MACpC,WAAW,IAAI,CAAA;AAAA,KACjB;AACA,IAAA,MAAM,SAASC,sBAAA,EAAG;AAElB,IAAA,MAAM,IAAA,CAAK,QAAQ,UAAA,CAAW;AAAA,MAC5B,MAAA,EAAQ;AAAA,QACN,EAAA,EAAI,MAAA;AAAA,QACJ,YAAA,EAAc,EAAA;AAAA,QACd,MAAA;AAAA,QACA;AAAA;AACF,KACD,CAAA;AAED,IAAA,IAAI,QAAA,IAAY,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AACnC,MAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,kBAAA,CAAmB,MAAA,EAAQ,QAAQ,CAAA;AAAA,IACxD;AAEA,IAAA,MAAM,KAAA,GACJ,QAAA,EAAU,GAAA,CAAI,CAAA,QAAA,MAAa;AAAA,MACzB,GAAG,QAAA;AAAA,MACH,MAAA,EAAQ;AAAA,QACN,GAAG,QAAA,CAAS,MAAA;AAAA,QACZ,QAAA,EAAU;AAAA,UACR,GAAG,SAAS,MAAA,CAAO,QAAA;AAAA,UACnB,WAAA,EAAa;AAAA,YACX,GAAG,QAAA,CAAS,MAAA,CAAO,QAAA,CAAS;AAAA;AAC9B;AACF;AACF,KACF,CAAE,KAAK,EAAC;AAEV,IAAA,MAAM,UAAmC,EAAC;AAE1C,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,QAClB,kCAAkC,EAAE,CAAA,mDAAA;AAAA,OACtC;AACA,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,OAAA,CAAQ,cAAA;AAAA,QAChC,IAAA,CAAK,OAAA,CAAQ,QAAA,CAAS,eAAA,EAAgB;AAAA,QACtC;AAAA,OACF;AAEA,MAAA,MAAM,EAAE,OAAM,GAAI,MAAA;AAElB,MAAA,IAAI,SAAA,GAAY,IAAA;AAChB,MAAA,IAAI,IAAA,CAAK,QAAQ,4BAAA,EAA8B;AAC7C,QAAA,IAAI,UAAU,CAAA,EAAG;AACf,UAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,YAClB,kCAAkC,EAAE,CAAA,qCAAA;AAAA,WACtC;AACA,UAAA,SAAA,GAAY,KAAA;AAAA,QACd;AAAA,MACF;AAEA,MAAA,IAAI,IAAA,CAAK,QAAQ,6BAAA,EAA+B;AAG9C,QAAA,MAAM,iBACJ,KAAA,GAAQ,CAAA,GAAK,OAAO,OAAA,CAAQ,MAAA,GAAS,QAAS,GAAA,GAAM,GAAA;AACtD,QAAA,IAAI,cAAA,IAAkB,IAAA,CAAK,OAAA,CAAQ,6BAAA,EAA+B;AAChE,UAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,IAAA;AAAA,YAClB,CAAA,+BAAA,EAAkC,EAAE,CAAA,YAAA,EAAe,MAAA,CAAO,QAAQ,MAAM,CAAA,sCAAA;AAAA,WAC1E;AAAA,QACF,CAAA,MAAO;AACL,UAAA,MAAM,MAAA,GAAS,uBAAuB,cAAc,CAAA,uBAAA,CAAA;AACpD,UAAA,IAAA,CAAK,QAAQ,MAAA,CAAO,KAAA;AAAA,YAClB,CAAA,+BAAA,EAAkC,EAAE,CAAA,GAAA,EAAM,MAAM,CAAA;AAAA,WAClD;AACA,UAAA,MAAM,IAAA,CAAK,QAAQ,yBAAA,CAA0B;AAAA,YAC3C,WAAA,EAAa,EAAA;AAAA,YACb,MAAA,EAAQ;AAAA,cACN,UAAA,EAAY,CAAA,6CAAA,EAAgD,MAAM,CAAA,EAAA,EAAK,MAAM,CAAA;AAAA;AAC/E,WACD,CAAA;AACD,UAAA,SAAA,GAAY,KAAA;AAAA,QACd;AAAA,MACF;AACA,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,KAAA,MAAW,SAAA,IAAa,OAAO,OAAA,EAAS;AACtC,UAAA,OAAA,CAAQ,KAAK,SAAS,CAAA;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,UAAA,CAAW,aAAA,CAAc;AAAA,MAC1C,IAAA,EAAM,OAAA;AAAA,MACN,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AAAA,EAEA,MAAM,QAAQ,MAAA,EAAoC;AAChD,IAAA,MAAM,EAAE,OAAM,GAAI,MAAA;AAClB,IAAA,IAAI,CAAC,IAAA,CAAK,mBAAA,EAAoB,CAAE,QAAA,CAAS,KAAK,CAAA,EAAG;AAC/C,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,MAAA,EAAQ,QAAA,EAAU,UAAA,KAAe,IAAA,CAAK,OAAA;AAC9C,IAAA,MAAM,YAAA,GAAe,SAAS,eAAA,EAAgB;AAC9C,IAAA,MAAA,CAAO,KAAA,CAAM,CAAA,oBAAA,EAAuB,YAAY,CAAA,UAAA,EAAa,KAAK,CAAA,MAAA,CAAQ,CAAA;AAE1E,IAAA,IAAI,CAAC,SAAS,YAAA,EAAc;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,MAAA,GAAS,MAAM,QAAA,CAAS,YAAA,CAAa,QAAQ,MAAM,CAAA;AAEzD,IAAA,IAAI,MAAA,CAAO,SAAS,OAAA,EAAS;AAC3B,MAAA,IAAI,MAAA,CAAO,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG;AAC3B,QAAA,MAAM,eAAA,GAAkB,MAAM,IAAA,CAAK,OAAA,CAAQ,yBAAA;AAAA,UACzC;AAAA,SACF;AAEA,QAAA,IAAI,CAAC,eAAA,EAAiB;AACpB,UAAA,MAAA,CAAO,KAAA;AAAA,YACL,uBAAuB,YAAY,CAAA,qEAAA;AAAA,WACrC;AAAA,QACF,CAAA,MAAO;AACL,UAAA,MAAM,OACJ,eAAA,CAAgB,MAAA,KAAW,SAAA,GACvB,MAAM,KAAK,OAAA,CAAQ,WAAA,CAAY,eAAA,CAAgB,EAAE,IACjD,MAAM,IAAA,CAAK,OAAA,CAAQ,YAAA,CAAa,gBAAgB,EAAE,CAAA;AAExD,UAAA,IAAI,CAAC,IAAA,EAAM;AACT,YAAA,MAAM,IAAI,KAAA;AAAA,cACR,yFAAyF,YAAY,CAAA,CAAA;AAAA,aACvG;AAAA,UACF;AACA,UAAA,MAAM,KAAK,OAAA,CAAQ,kBAAA,CAAmB,IAAA,CAAK,EAAA,EAAI,OAAO,KAAK,CAAA;AAAA,QAC7D;AAAA,MACF;AAEA,MAAA,IAAI,MAAA,CAAO,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG;AAC7B,QAAA,MAAM,IAAA,CAAK,OAAA,CAAQ,wBAAA,CAAyB,MAAA,CAAO,OAAO,CAAA;AAAA,MAC5D;AAEA,MAAA,MAAM,UAAA,CAAW,cAAc,MAAM,CAAA;AACrC,MAAA,MAAA,CAAO,KAAA;AAAA,QACL,CAAA,oBAAA,EAAuB,YAAY,CAAA,uBAAA,EAA0B,KAAK,CAAA,OAAA;AAAA,OACpE;AAAA,IACF,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,KAAA;AAAA,QACL,CAAA,oBAAA,EAAuB,YAAY,CAAA,2BAAA,EAA8B,KAAK,CAAA,CAAA;AAAA,OACxE;AAAA,IACF;AAAA,EACF;AAAA,EAEA,mBAAA,GAAgC;AAC9B,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,IAAA,CAAK,OAAA;AAC1B,IAAA,MAAM,SAAS,QAAA,CAAS,YAAA,GACpB,SAAS,YAAA,CAAa,mBAAA,KACtB,EAAC;AACL,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-catalog-backend-module-incremental-ingestion",
|
|
3
|
-
"version": "0.7.12-next.
|
|
3
|
+
"version": "0.7.12-next.1",
|
|
4
4
|
"description": "An entity provider for streaming large asset sources into the catalog",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "backend-plugin-module",
|
|
@@ -55,24 +55,23 @@
|
|
|
55
55
|
"test": "backstage-cli package test"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@backstage/backend-defaults": "0.17.1-next.
|
|
58
|
+
"@backstage/backend-defaults": "0.17.1-next.1",
|
|
59
59
|
"@backstage/backend-plugin-api": "1.9.1-next.0",
|
|
60
|
-
"@backstage/catalog-model": "1.8.1-next.
|
|
60
|
+
"@backstage/catalog-model": "1.8.1-next.1",
|
|
61
61
|
"@backstage/config": "1.3.8-next.0",
|
|
62
62
|
"@backstage/errors": "1.3.1-next.0",
|
|
63
|
-
"@backstage/plugin-catalog-backend": "3.6.
|
|
64
|
-
"@backstage/plugin-catalog-node": "2.2.1-next.
|
|
63
|
+
"@backstage/plugin-catalog-backend": "3.6.2-next.1",
|
|
64
|
+
"@backstage/plugin-catalog-node": "2.2.1-next.1",
|
|
65
65
|
"@backstage/plugin-events-node": "0.4.22-next.0",
|
|
66
66
|
"@backstage/types": "1.2.2",
|
|
67
67
|
"express": "^4.22.0",
|
|
68
68
|
"express-promise-router": "^4.1.0",
|
|
69
69
|
"knex": "^3.0.0",
|
|
70
|
-
"luxon": "^3.0.0"
|
|
71
|
-
"uuid": "^11.0.0"
|
|
70
|
+
"luxon": "^3.0.0"
|
|
72
71
|
},
|
|
73
72
|
"devDependencies": {
|
|
74
|
-
"@backstage/backend-test-utils": "1.11.3-next.
|
|
75
|
-
"@backstage/cli": "0.36.2-next.
|
|
73
|
+
"@backstage/backend-test-utils": "1.11.3-next.1",
|
|
74
|
+
"@backstage/cli": "0.36.2-next.1",
|
|
76
75
|
"@types/express": "^4.17.6"
|
|
77
76
|
}
|
|
78
77
|
}
|