Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,12 @@ class CSVReader
csv.writeHeader(outputHeaders ?: header)
preproc.stream().skip(1).forEach { r: CsvRecord ->
val transformed = csvPreprocessor.preprocessRow(r.fields, header, typeIdx, qualifiedNameIdx)
csv.writeRecord(transformed)
// Skip entirely-blank rows (e.g. a trailing ",,,,," line): writing these to the
// preprocessed/.processed output produces an asset with empty typeName and qualifiedName,
// which later fails delta calculation with "Invalid asset identity: ::". (CSA-467)
if (transformed.any { it.isNotBlank() }) {
csv.writeRecord(transformed)
}
}
preproc.close()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,19 @@ class FileBasedDelta(
reader.stream().skip(1).forEach { r: CsvRecord ->
val values = r.fields
val assetIdentity = resolveAsset(values, header)
if (assetIdentity != null) {
// Guard against rows that resolve to a blank typeName and/or qualifiedName (e.g. a trailing
// ",,,,," line that slipped into a previously-written .processed file). Caching such an identity
// serializes its key as "::", which later fails deserialization with
// "Invalid asset identity: ::" while iterating the checksum cache. (CSA-467)
if (assetIdentity != null &&
assetIdentity.typeName.isNotBlank() &&
assetIdentity.qualifiedName.isNotBlank()
) {
val singleLine = r.fields.joinToString("§")
val checksum = Hashing.murmur3_128().hashString(singleLine, Charsets.UTF_8).toString()
cache.put(assetIdentity, checksum)
} else {
logger.warn { "Skipping row with blank typeName/qualifiedName in $filename: $values" }
}
}
}
Expand Down
Loading