@backstage/plugin-catalog-backend 1.13.0 → 1.13.2

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 CHANGED
@@ -1,5 +1,25 @@
1
1
  # @backstage/plugin-catalog-backend
2
2
 
3
+ ## 1.13.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/plugin-auth-node@0.3.1
9
+ - @backstage/backend-plugin-api@0.6.4
10
+ - @backstage/plugin-permission-node@0.7.15
11
+ - @backstage/backend-common@0.19.6
12
+ - @backstage/plugin-catalog-node@1.4.5
13
+ - @backstage/plugin-events-node@0.2.13
14
+ - @backstage/plugin-search-backend-module-catalog@0.1.8
15
+ - @backstage/backend-tasks@0.5.9
16
+
17
+ ## 1.13.1
18
+
19
+ ### Patch Changes
20
+
21
+ - e77bbde41b99: Fixes a bug where eagerly deleted entities did not properly trigger re-stitching of entities that they had relations to.
22
+
3
23
  ## 1.13.0
4
24
 
5
25
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-backend",
3
- "version": "1.13.0",
3
+ "version": "1.13.2",
4
4
  "main": "../dist/alpha.cjs.js",
5
5
  "types": "../dist/alpha.d.ts"
6
6
  }
package/dist/alpha.cjs.js CHANGED
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var alpha = require('@backstage/plugin-catalog-common/alpha');
6
6
  var pluginPermissionNode = require('@backstage/plugin-permission-node');
7
- var CatalogBuilder = require('./cjs/CatalogBuilder-c40214f8.cjs.js');
7
+ var CatalogBuilder = require('./cjs/CatalogBuilder-60d67596.cjs.js');
8
8
  var backendPluginApi = require('@backstage/backend-plugin-api');
9
9
  var alpha$1 = require('@backstage/plugin-catalog-node/alpha');
10
10
  var backendCommon = require('@backstage/backend-common');
@@ -5891,57 +5891,113 @@ async function deleteWithEagerPruningOfChildren(options) {
5891
5891
  const { knex, entityRefs, sourceKey } = options;
5892
5892
  let removedCount = 0;
5893
5893
  for (const refs of lodash__default["default"].chunk(entityRefs, 1e3)) {
5894
- removedCount += await knex.delete().from("refresh_state").whereIn(
5895
- "entity_ref",
5896
- (orphans) => orphans.withRecursive(
5897
- "descendants",
5898
- ["entity_ref"],
5899
- (initial) => initial.select("target_entity_ref").from("refresh_state_references").where("source_key", "=", sourceKey).whereIn("target_entity_ref", refs).union(
5900
- (recursive) => recursive.select("refresh_state_references.target_entity_ref").from("descendants").join(
5901
- "refresh_state_references",
5902
- "descendants.entity_ref",
5903
- "refresh_state_references.source_entity_ref"
5904
- )
5894
+ const { orphanEntityRefs } = await findDescendantsThatWouldHaveBeenOrphanedByDeletion({
5895
+ knex: options.knex,
5896
+ refs,
5897
+ sourceKey
5898
+ });
5899
+ for (const refsToDelete of lodash__default["default"].chunk(orphanEntityRefs, 1e3)) {
5900
+ await markEntitiesAffectedByDeletionForStitching({
5901
+ knex: options.knex,
5902
+ entityRefs: refsToDelete
5903
+ });
5904
+ await knex.delete().from("refresh_state").whereIn("entity_ref", refsToDelete);
5905
+ }
5906
+ await knex("refresh_state_references").where("source_key", "=", sourceKey).whereIn("target_entity_ref", refs).delete();
5907
+ removedCount += orphanEntityRefs.length;
5908
+ }
5909
+ return removedCount;
5910
+ }
5911
+ async function findDescendantsThatWouldHaveBeenOrphanedByDeletion(options) {
5912
+ const { knex, refs, sourceKey } = options;
5913
+ const orphans = (
5914
+ // First find all nodes that can be reached downwards from the roots
5915
+ // (deletion targets), including the roots themselves, by traversing
5916
+ // down the refresh_state_references table. Note that this query
5917
+ // starts with a condition that source_key = our source key, and
5918
+ // target_entity_ref is one of the deletion targets. This has two
5919
+ // effects: it won't match attempts at deleting something that didn't
5920
+ // originate from us in the first place, and also won't match non-root
5921
+ // entities (source_key would be null for those).
5922
+ //
5923
+ // KeyA - R1 - R2 Legend:
5924
+ // \ -----------------------------------------
5925
+ // R3 Key* Source key
5926
+ // / R* Entity ref
5927
+ // KeyA - R4 - R5 lines Individual references; sources to
5928
+ // / the left and targets to the right
5929
+ // KeyB --- R6
5930
+ //
5931
+ // The scenario is that KeyA wants to delete R1.
5932
+ //
5933
+ // The query starts with the KeyA-R1 reference, and then traverses
5934
+ // down to also find R2 and R3. It uses union instead of union all,
5935
+ // because it wants to find the set of unique descendants even if
5936
+ // the tree has unexpected loops etc.
5937
+ await knex.withRecursive(
5938
+ "descendants",
5939
+ ["entity_ref"],
5940
+ (initial) => initial.select("target_entity_ref").from("refresh_state_references").where("source_key", "=", sourceKey).whereIn("target_entity_ref", refs).union(
5941
+ (recursive) => recursive.select("refresh_state_references.target_entity_ref").from("descendants").join(
5942
+ "refresh_state_references",
5943
+ "descendants.entity_ref",
5944
+ "refresh_state_references.source_entity_ref"
5905
5945
  )
5906
- ).withRecursive(
5907
- "ancestors",
5908
- ["source_key", "source_entity_ref", "target_entity_ref", "subject"],
5909
- (initial) => initial.select(
5946
+ )
5947
+ ).withRecursive(
5948
+ "ancestors",
5949
+ ["source_key", "source_entity_ref", "target_entity_ref", "subject"],
5950
+ (initial) => initial.select(
5951
+ "refresh_state_references.source_key",
5952
+ "refresh_state_references.source_entity_ref",
5953
+ "refresh_state_references.target_entity_ref",
5954
+ "descendants.entity_ref"
5955
+ ).from("descendants").join(
5956
+ "refresh_state_references",
5957
+ "refresh_state_references.target_entity_ref",
5958
+ "descendants.entity_ref"
5959
+ ).union(
5960
+ (recursive) => recursive.select(
5910
5961
  "refresh_state_references.source_key",
5911
5962
  "refresh_state_references.source_entity_ref",
5912
5963
  "refresh_state_references.target_entity_ref",
5913
- "descendants.entity_ref"
5914
- ).from("descendants").join(
5964
+ "ancestors.subject"
5965
+ ).from("ancestors").join(
5915
5966
  "refresh_state_references",
5916
5967
  "refresh_state_references.target_entity_ref",
5917
- "descendants.entity_ref"
5918
- ).union(
5919
- (recursive) => recursive.select(
5920
- "refresh_state_references.source_key",
5921
- "refresh_state_references.source_entity_ref",
5922
- "refresh_state_references.target_entity_ref",
5923
- "ancestors.subject"
5924
- ).from("ancestors").join(
5925
- "refresh_state_references",
5926
- "refresh_state_references.target_entity_ref",
5927
- "ancestors.source_entity_ref"
5928
- )
5929
- )
5930
- ).with(
5931
- "retained",
5932
- ["entity_ref"],
5933
- (notPartOfDeletion) => notPartOfDeletion.select("subject").from("ancestors").whereNotNull("ancestors.source_key").where(
5934
- (foreignKeyOrRef) => foreignKeyOrRef.where("ancestors.source_key", "!=", sourceKey).orWhereNotIn("ancestors.target_entity_ref", refs)
5968
+ "ancestors.source_entity_ref"
5935
5969
  )
5936
- ).select("descendants.entity_ref").from("descendants").leftOuterJoin(
5937
- "retained",
5938
- "retained.entity_ref",
5939
- "descendants.entity_ref"
5940
- ).whereNull("retained.entity_ref")
5941
- );
5942
- await knex("refresh_state_references").where("source_key", "=", sourceKey).whereIn("target_entity_ref", refs).delete();
5970
+ )
5971
+ ).with(
5972
+ "retained",
5973
+ ["entity_ref"],
5974
+ (notPartOfDeletion) => notPartOfDeletion.select("subject").from("ancestors").whereNotNull("ancestors.source_key").where(
5975
+ (foreignKeyOrRef) => foreignKeyOrRef.where("ancestors.source_key", "!=", sourceKey).orWhereNotIn("ancestors.target_entity_ref", refs)
5976
+ )
5977
+ ).select("descendants.entity_ref AS entity_ref").from("descendants").leftOuterJoin(
5978
+ "retained",
5979
+ "retained.entity_ref",
5980
+ "descendants.entity_ref"
5981
+ ).whereNull("retained.entity_ref").then((rows) => rows.map((row) => row.entity_ref))
5982
+ );
5983
+ return { orphanEntityRefs: orphans };
5984
+ }
5985
+ async function markEntitiesAffectedByDeletionForStitching(options) {
5986
+ const { knex, entityRefs } = options;
5987
+ const affectedIds = await knex.select("refresh_state.entity_id AS entity_id").from("relations").join(
5988
+ "refresh_state",
5989
+ "relations.source_entity_ref",
5990
+ "refresh_state.entity_ref"
5991
+ ).whereIn("relations.target_entity_ref", entityRefs).then((rows) => rows.map((row) => row.entity_id));
5992
+ for (const ids of lodash__default["default"].chunk(affectedIds, 1e3)) {
5993
+ await knex.table("final_entities").update({
5994
+ hash: "force-stitching"
5995
+ }).whereIn("entity_id", ids);
5996
+ await knex.table("refresh_state").update({
5997
+ result_hash: "force-stitching",
5998
+ next_update_at: knex.fn.now()
5999
+ }).whereIn("entity_id", ids);
5943
6000
  }
5944
- return removedCount;
5945
6001
  }
5946
6002
 
5947
6003
  async function refreshByRefreshKeys(options) {
@@ -6750,4 +6806,4 @@ exports.createCatalogPermissionRule = createCatalogPermissionRule;
6750
6806
  exports.createRandomProcessingInterval = createRandomProcessingInterval;
6751
6807
  exports.parseEntityYaml = parseEntityYaml;
6752
6808
  exports.permissionRules = permissionRules;
6753
- //# sourceMappingURL=CatalogBuilder-c40214f8.cjs.js.map
6809
+ //# sourceMappingURL=CatalogBuilder-60d67596.cjs.js.map