Skip to content

KMS-696: Now includes cmr errors in audit log. - #120

Open
cgokey wants to merge 6 commits into
mainfrom
KMS-696
Open

KMS-696: Now includes cmr errors in audit log.#120
cgokey wants to merge 6 commits into
mainfrom
KMS-696

Conversation

@cgokey

@cgokey cgokey commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Overview

What is the feature?

Captures CMR ingest/writeback failures in the metadata correction audit log so failed writeback attempts are visible alongside successful correction history.

Today we persist pending before writeback and applied after success, but if CMR rejects the corrected metadata the audit log does not clearly show that failure or the ingest error returned by CMR.

What is the Solution?

This branch updates the metadata correction audit flow to persist failed writeback attempts with the CMR error payload.

Key changes:

  • Adds optional writebackErrorMessage persistence to metadata correction audit rows.
  • Updates audit-log reads to return writebackErrorMessage when present.
  • Updates runCollectionMetadataCorrection so that when CMR writeback fails after corrections were applied:
    • the existing pending audit row behavior stays the same
    • a second audit row is written with status=failed
    • the failed row includes the CMR ingest/writeback error message returned for that attempt
    • the original writeback error is still rethrown
  • Prefers error.cmrResponseBody over the generic error message when building the stored writeback error text, so audit rows capture the actual CMR ingest response body when available.

What areas of the application does this impact?

  • Metadata correction audit persistence:
  • Metadata correction audit read path:
  • Metadata correction execution/writeback flow:

Testing

Checklist

  • I have added automated tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

Summary by CodeRabbit

  • New Features

    • Metadata correction audit records now include writebackErrorMessage for failed writebacks.
    • Added a local end-to-end smoke test for the writeback failure audit flow.
  • Bug Fixes

    • Improved writeback failure handling to persist and surface the most relevant error message while preserving the original failure.
    • Added a bounded ingest/writeback timeout to prevent hanging requests.
  • New/Updated Tests

    • Expanded coverage for audit log mapping/persistence and multiple writeback error formats.
  • Chores

    • Enhanced local mock server failure simulation and added reserved concurrency configuration for the correction service.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@cgokey, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 49 seconds

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bcc808a0-c01b-491a-94e6-43880a9a6eed

📥 Commits

Reviewing files that changed from the base of the PR and between 51434ef and 8b7d26d.

📒 Files selected for processing (2)
  • serverless/src/shared/__tests__/getMetadataCorrectionAuditLog.test.js
  • serverless/src/shared/getMetadataCorrectionAuditLog.js
📝 Walkthrough

Walkthrough

Changes

The metadata correction workflow records normalized CMR writeback errors on failed audit rows, exposes them through audit queries, and preserves the original failure. Local tooling simulates ingest failures and validates the end-to-end path. CMR requests now have timeouts and validation controls, and the service receives reserved concurrency configuration.

Metadata correction writeback failures

Layer / File(s) Summary
Audit error persistence and retrieval
serverless/src/shared/persistMetadataCorrectionAuditLog.js, serverless/src/shared/getMetadataCorrectionAuditLog.js, serverless/src/shared/__tests__/*AuditLog.test.js
Audit rows optionally persist and return writebackErrorMessage; tests cover present and absent values.
Correction failure handling
serverless/src/shared/runCollectionMetadataCorrection.js, serverless/src/shared/__tests__/runCollectionMetadataCorrection.test.js
Writeback failures create failed audit rows when corrections were applied, normalize varied error shapes, preserve the original error, and cover fallback paths.
Configurable mock CMR failure
scripts/local/mock_cmr_server.mjs
Environment variables configure ingest failure status and response body, returned before request processing.
End-to-end failed-audit smoke test
scripts/local/run_metadata_correction_failed_audit_smoke.mjs
The smoke test prepares Redis and RDF4J state, invokes the service, validates failed audit results, writes output, and cleans up processes.
CMR request timeout and validation controls
serverless/src/shared/cmrPutRequest.js, serverless/src/shared/writeCorrectedMetadataToCmr.js, serverless/src/shared/__tests__/*Cmr*.test.js
CMR PUT requests support abortable timeouts; metadata writeback uses a ten-second timeout and validation-bypass headers.
Reserved concurrency configuration
cdk/app/lib/..., cdk/bin/main.ts, bin/deploy-bamboo.sh
Deployment configuration passes reserved concurrency to the metadata correction Lambda, defaulting to five for invalid or missing values.

Estimated code review effort: 4 (Complex) | ~75 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SmokeTest
  participant MockCMRServer
  participant metadataCorrectionService
  participant RDF4J
  SmokeTest->>MockCMRServer: configure ingest failure
  SmokeTest->>metadataCorrectionService: invoke correction event
  metadataCorrectionService->>MockCMRServer: write corrected metadata with timeout and validation headers
  MockCMRServer-->>metadataCorrectionService: configured error response
  metadataCorrectionService->>RDF4J: persist failed audit row
  SmokeTest->>RDF4J: fetch audit rows
  RDF4J-->>SmokeTest: failed status and error message
Loading

Suggested reviewers: eudoroolivares2016, william-valencia

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: capturing CMR errors in the audit log.
Description check ✅ Passed The description covers the required overview, solution, impacted areas, testing intent, and checklist, with only testing details left sparse.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch KMS-696

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov-commenter

codecov-commenter commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.73%. Comparing base (e55397c) to head (8b7d26d).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #120   +/-   ##
=======================================
  Coverage   99.73%   99.73%           
=======================================
  Files         229      229           
  Lines        6029     6059   +30     
  Branches     1773     1776    +3     
=======================================
+ Hits         6013     6043   +30     
  Misses         14       14           
  Partials        2        2           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
serverless/src/shared/cmrPutRequest.js (1)

106-132: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Keep the timeout active through response-body consumption.

fetch() resolves once headers arrive, so Line 106 can return a Response while its body still stalls. Line 129 then clears the timer before writeCorrectedMetadataToCmr parses either a success or error body, allowing the Lambda to run until its 30-second timeout and preventing failed-audit handling. Apply the deadline through response parsing, not only until headers are received.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@serverless/src/shared/cmrPutRequest.js` around lines 106 - 132, Keep the
timeout established by the CMR PUT request active through response-body
consumption and parsing, rather than clearing it immediately after fetch
resolves. Update the request flow around the fetch return and its caller’s
success/error body parsing so the deadline covers both headers and the complete
response body; clear the timer only after parsing finishes or the request
otherwise completes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@serverless/src/shared/cmrPutRequest.js`:
- Around line 106-132: Keep the timeout established by the CMR PUT request
active through response-body consumption and parsing, rather than clearing it
immediately after fetch resolves. Update the request flow around the fetch
return and its caller’s success/error body parsing so the deadline covers both
headers and the complete response body; clear the timer only after parsing
finishes or the request otherwise completes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b88137ec-a6e6-4f3b-9ca4-fc9ff658e2e5

📥 Commits

Reviewing files that changed from the base of the PR and between 5ebdd44 and 929b150.

📒 Files selected for processing (8)
  • bin/deploy-bamboo.sh
  • cdk/app/lib/CmrEventProcessingStack.ts
  • cdk/app/lib/helper/MetadataCorrectionSetup.ts
  • cdk/bin/main.ts
  • serverless/src/shared/__tests__/cmrPutRequest.test.js
  • serverless/src/shared/__tests__/writeCorrectedMetadataToCmr.test.js
  • serverless/src/shared/cmrPutRequest.js
  • serverless/src/shared/writeCorrectedMetadataToCmr.js

* Creates the metadata correction SNS/SQS/Lambda plumbing and exports its endpoints.
*/
export class MetadataCorrectionSetup extends Construct {
private static readonly METADATA_CORRECTION_SERVICE_RESERVED_CONCURRENCY = 5

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this just going to override the bamboo var? I don't feel strongly either way of if we need it at deployment vs hardcode but

writebackErrorMessage: getWritebackErrorMessage(error)
})

logger.info('[metadata-correction] Persisted failed metadata correction audit log', {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
logger.info('[metadata-correction] Persisted failed metadata correction audit log', {
logger.debug('[metadata-correction] Persisted failed metadata correction audit log', {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could say either way I'm just trying to be conscious right now the api has alot of logging in place as a baseline

Authorization: 'Bearer writer-token'
Authorization: 'Bearer writer-token',
'cmr-validate-keywords': 'false',
'Cmr-Validate-Umm-C': 'false'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is right one thing with the cmr-validate-umm-c var one to keep in mind is in the CMR docs it says CMR was going to make that the default but, that was > 5 years ago. I haven't dug very deeply into what that code does yet

await rejectionExpectation
})

test('should skip abort wiring when AbortController is unavailable', async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good for coverage but, isn't this just a core node feature would we expect this to happen?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants