Skip to content

chore(interview): multiple challenge solutions (cleanup, UI, incident analysis)#19

Open
NahusenayH wants to merge 4 commits into
vula-africa:mainfrom
NahusenayH:chore/interview-challenges-nahusenay
Open

chore(interview): multiple challenge solutions (cleanup, UI, incident analysis)#19
NahusenayH wants to merge 4 commits into
vula-africa:mainfrom
NahusenayH:chore/interview-challenges-nahusenay

Conversation

@NahusenayH
Copy link
Copy Markdown

@NahusenayH NahusenayH commented Jan 4, 2026

Context

This PR contains multiple independent interview challenges, implemented for review purposes:

  • Backend: Cleanup of unsubmitted public forms (safe entity-aware deletion using Prisma transactions)
  • Frontend: Component breakdown for the portfolio overview UI
  • Systems: Root cause analysis for an API latency spike incident

Key Improvements & Fixes

Backend: Cleanup Unsubmitted Forms

  • Prevents deletion of entities that have submitted forms
  • Groups token deletions by entity for efficiency
  • Uses a single transaction (tx) per entity for atomic operations
  • Adds debug logs for monitoring and troubleshooting

Frontend: UI Component Breakdown

  • Structured into container and presentational components
  • Makes code modular, testable, and maintainable

Systems: Incident Analysis

  • Analysed API latency spike for lenders in Kenya
  • Provided root cause, evidence, immediate action, and prevention
  • Documented retrospective notes for future learning

Future Improvements

  • Implement partial cleanup for entities with some submitted forms
  • Introduce batch deletion for large-scale token cleanup
  • Add monitoring and alerting for long-running cleanup jobs
  • Formalise logging with structured log formats (JSON) for easier analysis

Summary by CodeRabbit

  • Documentation

    • Added comprehensive incident analysis documentation detailing latency regression investigation, mitigation strategies, and prevention recommendations.
    • Added form cleanup design documentation with implementation specifications and safety measures.
  • Bug Fixes

    • Improved unsubmitted form cleanup with transactional processing to prevent data inconsistencies and race conditions.
    • Enhanced error handling and structured logging for cleanup operations.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 4, 2026

Walkthrough

Two README documents were added outlining incident analysis and form cleanup design, while a TypeScript cleanup module was refactored to implement transactional multi-step processing with per-entity validation, proper error handling, and structured logging.

Changes

Cohort / File(s) Change Summary
Incident Analysis Documentation
tests/end_of_week_issues/README.md
Added comprehensive root cause analysis for latency regression in model v1.3 affecting /risk-score and downstream endpoints, with remediation recommendations (rollback, canary checks, SLO-based thresholds) and retrospective prevention strategies.
Form Cleanup Design Document
tests/unsubmitted_forms/README.md
Added detailed design document addressing form cleanup problems (time comparison logic, unsafe deletion, race conditions, scalability, observability) with proposed fixes, schema assumptions, and future improvements (soft deletes, batching, metrics).
Form Cleanup Implementation
tests/unsubmitted_forms/cleanup_unsubmitted_forms.ts
Refactored from single-pass to multi-step transactional cleanup: fetches expired tokens grouped by entity, validates submitted forms per entity, deletes unsubmitted tokens and related data within transactions, adds structured logging and early-exit logic.

Sequence Diagram(s)

sequenceDiagram
    actor Job
    participant DB as Database
    participant Logic as Cleanup Logic
    participant Log as Logging

    Job->>DB: Fetch expired unsubmitted tokens<br/>(createdAt > 7 days, no submittedAt)
    alt Tokens found
        DB-->>Logic: Tokens grouped by entityId
        Logic->>Log: Log job started
        loop For each entityId
            Logic->>DB: Check if entity has<br/>submitted forms
            alt Submitted forms exist
                Logic->>Log: Log entity skipped
            else No submitted forms
                Logic->>DB: Start transaction
                DB->>DB: Delete expired tokens<br/>for this entity
                DB->>DB: Delete corpus items
                DB->>DB: Delete "new" status<br/>relationships
                DB->>DB: Delete entity
                DB-->>Logic: Transaction committed
                Logic->>Log: Log entity deleted
            end
        end
        Logic->>Log: Log job completed
    else No tokens found
        Logic->>Log: Log early exit
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Our forms once lingered, seven days too long,
But now we clean with logic strong—
Transactional and true, per-entity care,
No race conditions shall we spare! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title references multiple challenge solutions (cleanup, UI, incident analysis) and aligns with the PR's three main components: backend cleanup, frontend UI refactor, and systems incident analysis.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
tests/end_of_week_issues/README.md (1)

43-48: Missing comma in JSON array causes invalid syntax.

The mock log JSON array is missing a comma after line 43, making it invalid JSON. This could cause confusion if someone tries to parse or validate these logs programmatically.

🔎 Proposed fix
-  { "timestamp": "2025-08-01T18:06:40Z", "endpoint": "/funding-approve", "responseTimeMs": 700, "status": "Timeout", "modelVersion": "v1.3" }
+  { "timestamp": "2025-08-01T18:06:40Z", "endpoint": "/funding-approve", "responseTimeMs": 700, "status": "Timeout", "modelVersion": "v1.3" },
🧹 Nitpick comments (1)
tests/unsubmitted_forms/cleanup_unsubmitted_forms.ts (1)

70-74: Consider using inferred types instead of any.

The any type annotation weakens type safety. Since expiredTokens is already typed by Prisma's return type, you can let TypeScript infer the type or use a more specific type.

🔎 Proposed improvement
    const entityIds = [
      ...new Set(
-        expiredTokens.map((t: { entityId: any }) => t.entityId).filter(Boolean)
+        expiredTokens.map((t) => t.entityId).filter((id): id is string => Boolean(id))
      ),
    ];
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 1dd21f7 and ac23957.

⛔ Files ignored due to path filters (1)
  • tests/breakdown_ui/Component_Diagram.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • tests/end_of_week_issues/README.md
  • tests/unsubmitted_forms/README.md
  • tests/unsubmitted_forms/cleanup_unsubmitted_forms.ts
🧰 Additional context used
🪛 LanguageTool
tests/end_of_week_issues/README.md

[grammar] ~101-~101: Ensure spelling is correct
Context: ...s works: - v1.2 is consistently fast (<120ms) and stable. - Rolling back immediately...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)


[style] ~123-~123: ‘a majority of’ might be wordy. Consider a shorter alternative.
Context: ...res regressions like v1.3 never reach a majority of production traffic. --- ## 4. Retrosp...

(EN_WORDINESS_PREMIUM_A_MAJORITY_OF)

🔇 Additional comments (6)
tests/unsubmitted_forms/README.md (1)

1-138: Well-structured design documentation.

This README provides excellent context for the cleanup implementation, clearly documenting the problems identified, their fixes, assumptions made, and future improvements. The explicit documentation of assumptions (lines 79-88) is particularly valuable for maintainability.

tests/end_of_week_issues/README.md (1)

50-132: Solid incident analysis with clear actionable insights.

The root cause analysis correctly identifies the v1.3 model regression with supporting evidence from the logs. The immediate action (rollback to v1.2) and prevention measures (automated performance gating) are practical and appropriate. The retrospective notes cover key learning areas.

tests/unsubmitted_forms/cleanup_unsubmitted_forms.ts (4)

31-36: LGTM!

The date calculation is correct, and the structured logging with jobId and cutoff timestamp provides good observability for the job execution.


119-123: Verify: Deleting all corpus items regardless of submission status.

This deletes all new_corpus records for the entity, whereas the token deletion (lines 109-117) and relationship deletion (lines 125-130) are more selective. If an entity somehow has corpus items associated with different forms, this could delete more than intended.

If this is intentional (i.e., all corpus items should be removed when the entity is deleted), consider adding a clarifying comment. Otherwise, consider filtering by the specific tokens being deleted.


148-155: Good error handling pattern.

The error handling correctly logs structured error information, updates job status, and re-throws to allow upstream handling.

One minor consideration: if update_job_status itself throws, the original error context could be lost. For critical jobs, you might want to wrap the status update in a try-catch, but this is a minor edge case.


81-142: Per-entity transaction approach is safe but consider future optimization.

The sequential per-entity transaction approach ensures isolation and prevents partial failures from affecting other entities. As noted in your README, batch processing could improve performance for large datasets.

For now, this is acceptable for a daily scheduled job. If the entity count grows significantly, consider adding:

  • Progress logging (e.g., every N entities processed)
  • Configurable batch sizes with controlled concurrency

Comment on lines 44 to +45
createdAt: {
gte: sevenDaysAgo, // greater than or equal to 7 days ago
lt: sevenDaysAgoPlusOneDay, // but less than 7 days ago + 1 day
lt: sevenDaysAgo, // greater than or equal to 7 days ago
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Misleading comment does not match the code logic.

The comment says "greater than or equal to 7 days ago" but the code uses lt: sevenDaysAgo, which correctly selects tokens created before the cutoff (i.e., older than 7 days). The logic is correct, but the comment is confusing.

🔎 Proposed fix
        createdAt: {
-          lt: sevenDaysAgo, // greater than or equal to 7 days ago
+          lt: sevenDaysAgo, // created more than 7 days ago
        },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
createdAt: {
gte: sevenDaysAgo, // greater than or equal to 7 days ago
lt: sevenDaysAgoPlusOneDay, // but less than 7 days ago + 1 day
lt: sevenDaysAgo, // greater than or equal to 7 days ago
createdAt: {
lt: sevenDaysAgo, // created more than 7 days ago
},
🤖 Prompt for AI Agents
In tests/unsubmitted_forms/cleanup_unsubmitted_forms.ts around lines 44-45, the
inline comment "greater than or equal to 7 days ago" contradicts the code using
lt: sevenDaysAgo (which selects items older than the cutoff); update the comment
to accurately reflect the logic (e.g., "before sevenDaysAgo (older than 7 days)"
or "created more than 7 days ago") or remove the misleading comment so it
matches the code.

Comment on lines +125 to +136
await tx.relationship.deleteMany({
where: {
entity_id: entityId,
status: "new",
},
});

await tx.entity.delete({
where: {
id: entityId,
},
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's find and read the file in question
git ls-files | grep -E "(cleanup_unsubmitted|relationship|entity)" | head -20

Repository: vula-africa/coding_tests

Length of output: 120


🏁 Script executed:

# Let's check the structure of the repository
ls -la | head -20

Repository: vula-africa/coding_tests

Length of output: 491


🏁 Script executed:

# Find the test file
find . -type f -name "cleanup_unsubmitted_forms.ts" 2>/dev/null

Repository: vula-africa/coding_tests

Length of output: 122


🏁 Script executed:

# Read the test file with line numbers
cat -n tests/unsubmitted_forms/cleanup_unsubmitted_forms.ts

Repository: vula-africa/coding_tests

Length of output: 5618


🏁 Script executed:

# Search for relationship status enum or definition
rg -n "relationship" --type ts -i | head -40

Repository: vula-africa/coding_tests

Length of output: 167


🏁 Script executed:

# Search for status-related enums or constants
rg -n "status.*new|new.*status" --type ts -i | head -30

Repository: vula-africa/coding_tests

Length of output: 151


🏁 Script executed:

# Search for any schema files or model definitions
find . -type f \( -name "schema*" -o -name "*model*" -o -name "*.prisma" \) 2>/dev/null

Repository: vula-africa/coding_tests

Length of output: 50


🏁 Script executed:

# Check what files exist in the repository
git ls-files

Repository: vula-africa/coding_tests

Length of output: 370


🏁 Script executed:

# Look for any prisma schema or similar files
rg -l "prisma|schema|relationship|entity" --type ts --type json

Repository: vula-africa/coding_tests

Length of output: 131


🏁 Script executed:

# Read the README files to understand context
cat tests/unsubmitted_forms/README.md

Repository: vula-africa/coding_tests

Length of output: 3483


🏁 Script executed:

# Also check the main README
cat README.md

Repository: vula-africa/coding_tests

Length of output: 1211


Ensure all relationships are deleted before entity deletion.

The code only deletes relationships with status: "new", assuming unsubmitted entities have no relationships with other statuses. This assumption may be true in normal operation, but if violated—due to application bugs or edge cases in form submission logic—the entity.delete() will fail with a foreign key constraint violation. For a cleanup job, either delete all relationships for the entity regardless of status, or add error handling to gracefully handle FK violations.

🤖 Prompt for AI Agents
In tests/unsubmitted_forms/cleanup_unsubmitted_forms.ts around lines 125 to 136,
the code only deletes relationships with status: "new" before deleting the
entity which can cause FK constraint failures; update the cleanup to delete all
relationships for the entity (remove the status filter) or wrap the entity
delete in error handling that detects FK constraint violations and either
retries after deleting remaining relationships or logs and continues; implement
the simpler fix by calling tx.relationship.deleteMany({ where: { entity_id:
entityId } }) before tx.entity.delete(...) to ensure no remaining relationships
block deletion.

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.

1 participant