3.6.6 - Application size discrepancy after an application import

Workaround for the inflated application size (Lines of code) reported in CAST Imaging 3.6.6-funcrel after importing an application

Overview

This page describes a workaround for an issue specific to CAST Imaging 3.6.6-funcrel (see IMAGKSL-5754), in which the application size (Lines of code) displayed in CAST Imaging is significantly larger than the real size of the application. The issue is fixed in 3.6.7-funcrel.

Symptoms

After importing an application (for example an application exported from one CAST Imaging instance and imported into another, including across platforms such as Windows to Linux), the application size reported in the Viewer and on the Console onboarding page can be several times larger than the size reported for the same application onboarded from scratch.

The import creates duplicate Language nodes in the Neo4j database. Because the size of an application is derived from its active HAS_LANGUAGE relationships, the duplicated nodes cause the size to be counted multiple times.

Workaround

Two options are available:

  • Update to 3.6.7-funcrel, in which the issue is fixed. This is the recommended option.
  • Run the Cypher queries below to correct the data in place, as described in Correct the data in 3.6.6-funcrel.

Correct the data in 3.6.6-funcrel

Run the following queries in order, against the Neo4j database of the tenant on which the discrepancy is visible, for example using the Neo4j Browser. Steps 2, 3 and 4 use the APOC procedures that are bundled with CAST Imaging.

Step 1 - Detect the affected applications

This query is read-only and lists the applications and languages that are affected:

MATCH (a:Application|Repository)-[r:HAS_LANGUAGE]->(l:Language)
WHERE r.EndDate IS NULL
WITH a, l.Name AS langName, count(DISTINCT l) AS nodeCount
WHERE nodeCount > 1
RETURN a.Name AS app, langName, nodeCount
ORDER BY app, nodeCount DESC

Step 2 - Retire the redundant active relationships

This query corrects the reported size immediately:

CALL apoc.periodic.iterate(
  "MATCH (a:Application|Repository)-[r:HAS_LANGUAGE]->(l:Language)
   WHERE r.EndDate IS NULL
   WITH a, l.Name AS langName, l, r
   ORDER BY elementId(a), langName, l.StartDate ASC, elementId(l) ASC
   WITH a, langName, collect(l) AS nodes, collect(r) AS rels
   WHERE size(nodes) > 1
   RETURN rels[1..] AS relsToRetire",
  "UNWIND relsToRetire AS rel
   SET rel.EndDate = datetime(), rel.Status = 'deleted'",
  { batchSize: 1000, parallel: false, retries: 3 }
) YIELD batch, operations, timeTaken, errorMessages, retries
RETURN batch, operations, timeTaken, errorMessages, retries

Step 3 - Merge the duplicate nodes

This query closes the gap that allows subsequent onboarding and import operations to duplicate the nodes again:

CALL apoc.periodic.iterate(
  "MATCH (l:Language)
   WITH l.Name AS langName, l
   ORDER BY langName, l.StartDate ASC, elementId(l) ASC
   WITH langName, collect(l) AS nodes
   WHERE size(nodes) > 1
   RETURN nodes",
  "CALL apoc.refactor.mergeNodes(nodes, {mergeRels:false, properties:'discard'}) YIELD node RETURN node",
  { batchSize: 1000, parallel: false, retries: 3 }
) YIELD batch, operations, timeTaken, errorMessages, retries
RETURN batch, operations, timeTaken, errorMessages, retries

Step 4 - Recompute the application size

This query updates the stored Lines of code value for every application whose value is now stale:

CALL apoc.periodic.iterate(
  "MATCH (a:Application|Repository)-[r:HAS_LANGUAGE]->(l:Language) WHERE r.EndDate IS NULL
   WITH a, SUM(r.NbLocs) AS totalLoc
   MATCH (a)-[:Property]->(p:Property) WHERE p.Label = 'Lines of code' AND p.Value <> toString(totalLoc)
   RETURN a, p, totalLoc",
  "SET p.Value = toString(totalLoc)",
  { batchSize: 1000, parallel: false, retries: 3 }
) YIELD batch, operations, timeTaken, errorMessages, retries
RETURN batch, operations, timeTaken, errorMessages, retries

Step 5 - Check the result

Run the detection query in Step 1 again. It should return no rows. The corrected application size is displayed in the Viewer and on the Console onboarding page.