Skip to content

Modernization improvements: validation, logging, retry logic, and error handling#46

Open
heywinit wants to merge 7 commits intoniledatabase:alphafrom
heywinit:feat/modernization-improvements
Open

Modernization improvements: validation, logging, retry logic, and error handling#46
heywinit wants to merge 7 commits intoniledatabase:alphafrom
heywinit:feat/modernization-improvements

Conversation

@heywinit
Copy link
Copy Markdown

PR Overview
This PR adds several infrastructure improvements to make the CLI more robust: input validation utilities, structured logging, API retry logic for resilience, and consolidated error handling.

Follow up to #45

Changes

  1. Input Validation (src/lib/validation.ts - new)

    • validateDatabaseName() - validates DB names follow PostgreSQL naming rules (63 chars max, lowercase letters/numbers/underscores/hyphens, no reserved words)
    • validateTenantName() - validates tenant names (255 char max)
    • validateTenantId() - validates tenant IDs
  2. Structured Logging (src/lib/logger.ts - new)

    • info(), debug(), warn(), error() functions with timestamp, level, and message formatting
    • Debug mode support for verbose output
  3. API Retry Logic (src/lib/api.ts)

    • Added axios-retry with exponential backoff (3 retries)
    • Retries on 408, 429, and 5xx errors
    • Debug logging for retry attempts
  4. Error Handling Refactor (src/lib/errorHandling.ts)

    • Consolidated multiple error handlers into single handleError() function
    • Added ErrorContext type for context-aware error messages (API, Database, Tenant, User)
    • Cleaned up redundant code and comments
  5. Lint Fixes (src/commands/local.ts, .eslintrc.js)

    • Removed unused error variables in catch blocks

Copy link
Copy Markdown
Contributor

@gwenshap gwenshap left a comment

Choose a reason for hiding this comment

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

Thanks for all the validations. Overall, it looks like good improvements and we appreciate.
I had few comments around retries and validations.

src/lib/api.ts Outdated
retryDelay: axiosRetry.exponentialDelay,
retryCondition: (error) => {
const status = error.response?.status;
return !status || status === 408 || status === 429 || (status >= 500 && status < 600);
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.

Any reason not to stick to the default retry condition for axiosRetry (isNetworkOrIdempotentRequestError)?

It seems safer (since error 500 is not always safe to retry). As far as I can see, the only status your code handles and isNetworkOrIdempotentRequestError does not is 408, and Nile doesn't return that.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed it using isNetworkOrIdempotentRequestError now

return { valid: false, error: 'Database name is required' };
}

if (name.length > 63) {
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.

We actually don't limit database names in Nile

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed

}

if (!/^[a-z][a-z0-9_-]*$/.test(name)) {
return { valid: false, error: 'Database name must start with lowercase letter and contain only lowercase letters, numbers, underscores, and hyphens' };
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.

we don't allow hyphens

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed it

}

if (name.length > 255) {
return { valid: false, error: 'Tenant name must be 255 characters or less' };
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.

We allow any length

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed it

}

if (email.length > 255) {
return { valid: false, error: 'Email must be 255 characters or less' };
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.

We don't limit email length

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed it

@heywinit
Copy link
Copy Markdown
Author

heywinit commented Mar 27, 2026

Thanks for the quick review. My bad I wasn't aware of Nile's validation scope. I've fixed everything in fd878fc. Let me know if there are any other caveats I should take care of as well.

@gwenshap
Copy link
Copy Markdown
Contributor

gwenshap commented Apr 3, 2026

I just realized that our CI/CD wasn't set to run the test action for external contributions. I fixed that in a separate PR.

But, when I tested your PR locally (with npm test), I noticed 3 test failures that appear related to your changes.
Do you mind taking a look and fixing them? Hopefully the next time you add a commit to this branch, the test action will trigger and also pass :)

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.

2 participants