feat: move import database metadata to metadata field#1804
feat: move import database metadata to metadata field#1804sabrikaragonen wants to merge 2 commits into
Conversation
The `bruin import database` command previously embedded operational metadata (row count, size, timestamps, owner) into the asset Description field. This caused metadata to become stale on re-import since existing descriptions were never updated. Now this data lives in the Metadata field where it gets refreshed on every re-import, while Description holds only the actual DB table comment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prompt To Fix All With AIThis is a comment left during a code review.
Path: cmd/import.go
Line: 312-321
Comment:
**Stale import-generated metadata keys after re-import**
The merge loop only adds or overwrites keys that exist in `createdAsset.Metadata`; it never removes keys that were previously written by an import but are no longer returned by the DB. This directly contradicts the PR's stated goal: "On re-import, metadata is now always refreshed."
Concrete scenario:
1. First import: `RowCount` is available → `existingAsset.Metadata["row_count"] = "1 000 000"`.
2. Second import: DB no longer reports `RowCount` (stats dropped, permissions change, etc.) → `createdAsset.Metadata` has no `row_count` key.
3. After the merge loop the existing `row_count: "1 000 000"` stays untouched — permanently stale.
The same applies to `created_at`, `last_modified`, and `size`.
One way to fix this is to explicitly delete the known import-generated keys from `existingAsset.Metadata` before applying the merge, so absent metrics are cleared rather than left behind:
```go
// Always refresh metadata so it stays current on re-import.
// We merge key-by-key to preserve any user-added custom metadata keys.
if createdAsset.Metadata != nil {
if existingAsset.Metadata == nil {
existingAsset.Metadata = make(pipeline.EmptyStringMap)
}
// Clear import-generated keys first so absent metrics don't linger.
for _, k := range []string{"extracted_at", "created_at", "last_modified", "row_count", "size"} {
delete(existingAsset.Metadata, k)
}
for k, v := range createdAsset.Metadata {
existingAsset.Metadata[k] = v
}
}
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: cmd/import_test.go
Line: 341-352
Comment:
**Test duplicates production logic instead of exercising it**
`TestReimportUpdatesMetadata` manually copies the exact merge loop from `runImport()` rather than calling `runImport()` (or a helper extracted from it). This means if the merge logic in production changes, this test will continue to pass even though the behaviour is now wrong — it's testing a stale copy of the code, not the code itself.
Consider either:
- Extracting the merge logic into a package-level helper (e.g. `mergeAssetMetadata`) that both `runImport` and the test call, or
- Exercising the real `runImport()` path with a filesystem-backed test (even an in-memory `afero.MemMapFs`).
As written, the test provides false confidence that the re-import path works correctly.
How can I resolve this? If you propose a fix, please make it concise.Last reviewed commit: f262243 |
| // Always refresh metadata so it stays current on re-import. | ||
| // We merge key-by-key to preserve any user-added custom metadata keys. | ||
| if createdAsset.Metadata != nil { | ||
| if existingAsset.Metadata == nil { | ||
| existingAsset.Metadata = make(pipeline.EmptyStringMap) | ||
| } | ||
| for k, v := range createdAsset.Metadata { | ||
| existingAsset.Metadata[k] = v | ||
| } | ||
| } |
There was a problem hiding this comment.
Stale import-generated metadata keys after re-import
The merge loop only adds or overwrites keys that exist in createdAsset.Metadata; it never removes keys that were previously written by an import but are no longer returned by the DB. This directly contradicts the PR's stated goal: "On re-import, metadata is now always refreshed."
Concrete scenario:
- First import:
RowCountis available →existingAsset.Metadata["row_count"] = "1 000 000". - Second import: DB no longer reports
RowCount(stats dropped, permissions change, etc.) →createdAsset.Metadatahas norow_countkey. - After the merge loop the existing
row_count: "1 000 000"stays untouched — permanently stale.
The same applies to created_at, last_modified, and size.
One way to fix this is to explicitly delete the known import-generated keys from existingAsset.Metadata before applying the merge, so absent metrics are cleared rather than left behind:
// Always refresh metadata so it stays current on re-import.
// We merge key-by-key to preserve any user-added custom metadata keys.
if createdAsset.Metadata != nil {
if existingAsset.Metadata == nil {
existingAsset.Metadata = make(pipeline.EmptyStringMap)
}
// Clear import-generated keys first so absent metrics don't linger.
for _, k := range []string{"extracted_at", "created_at", "last_modified", "row_count", "size"} {
delete(existingAsset.Metadata, k)
}
for k, v := range createdAsset.Metadata {
existingAsset.Metadata[k] = v
}
}Prompt To Fix With AI
This is a comment left during a code review.
Path: cmd/import.go
Line: 312-321
Comment:
**Stale import-generated metadata keys after re-import**
The merge loop only adds or overwrites keys that exist in `createdAsset.Metadata`; it never removes keys that were previously written by an import but are no longer returned by the DB. This directly contradicts the PR's stated goal: "On re-import, metadata is now always refreshed."
Concrete scenario:
1. First import: `RowCount` is available → `existingAsset.Metadata["row_count"] = "1 000 000"`.
2. Second import: DB no longer reports `RowCount` (stats dropped, permissions change, etc.) → `createdAsset.Metadata` has no `row_count` key.
3. After the merge loop the existing `row_count: "1 000 000"` stays untouched — permanently stale.
The same applies to `created_at`, `last_modified`, and `size`.
One way to fix this is to explicitly delete the known import-generated keys from `existingAsset.Metadata` before applying the merge, so absent metrics are cleared rather than left behind:
```go
// Always refresh metadata so it stays current on re-import.
// We merge key-by-key to preserve any user-added custom metadata keys.
if createdAsset.Metadata != nil {
if existingAsset.Metadata == nil {
existingAsset.Metadata = make(pipeline.EmptyStringMap)
}
// Clear import-generated keys first so absent metrics don't linger.
for _, k := range []string{"extracted_at", "created_at", "last_modified", "row_count", "size"} {
delete(existingAsset.Metadata, k)
}
for k, v := range createdAsset.Metadata {
existingAsset.Metadata[k] = v
}
}
```
How can I resolve this? If you propose a fix, please make it concise.| // Apply the same merge logic used in the re-import branch | ||
| if createdAsset.Metadata != nil { | ||
| if existingAsset.Metadata == nil { | ||
| existingAsset.Metadata = make(pipeline.EmptyStringMap) | ||
| } | ||
| for k, v := range createdAsset.Metadata { | ||
| existingAsset.Metadata[k] = v | ||
| } | ||
| } | ||
| if createdAsset.Owner != "" { | ||
| existingAsset.Owner = createdAsset.Owner | ||
| } |
There was a problem hiding this comment.
Test duplicates production logic instead of exercising it
TestReimportUpdatesMetadata manually copies the exact merge loop from runImport() rather than calling runImport() (or a helper extracted from it). This means if the merge logic in production changes, this test will continue to pass even though the behaviour is now wrong — it's testing a stale copy of the code, not the code itself.
Consider either:
- Extracting the merge logic into a package-level helper (e.g.
mergeAssetMetadata) that bothrunImportand the test call, or - Exercising the real
runImport()path with a filesystem-backed test (even an in-memoryafero.MemMapFs).
As written, the test provides false confidence that the re-import path works correctly.
Prompt To Fix With AI
This is a comment left during a code review.
Path: cmd/import_test.go
Line: 341-352
Comment:
**Test duplicates production logic instead of exercising it**
`TestReimportUpdatesMetadata` manually copies the exact merge loop from `runImport()` rather than calling `runImport()` (or a helper extracted from it). This means if the merge logic in production changes, this test will continue to pass even though the behaviour is now wrong — it's testing a stale copy of the code, not the code itself.
Consider either:
- Extracting the merge logic into a package-level helper (e.g. `mergeAssetMetadata`) that both `runImport` and the test call, or
- Exercising the real `runImport()` path with a filesystem-backed test (even an in-memory `afero.MemMapFs`).
As written, the test provides false confidence that the re-import path works correctly.
How can I resolve this? If you propose a fix, please make it concise.Address PR review feedback: - Clear known import-generated metadata keys before merging so absent metrics (e.g. row_count no longer reported by DB) don't linger - Extract mergeImportMetadata() helper so test exercises the real code path instead of duplicating the merge logic Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Summary
descriptionfield to the structuredmetadatafield inbruin import databasedescriptionfield now holds only the actual database table comment, andownergoes to the dedicatedownerfieldTest plan
TestCreateAsset,TestBuildImportMetadata,TestBuildImportMetadataOptionalFields,TestReimportUpdatesMetadata)make testpassesmake formatpassesbruin import databaseand verify YAML output hasmetadata:block instead of embedded description🤖 Generated with Claude Code