Skip to content

feat(new-webui): Port search APIs from Meteor methods to Fastify routes.#913

Merged
davemarco merged 33 commits into
y-scope:mainfrom
davemarco:routes
May 26, 2025
Merged

feat(new-webui): Port search APIs from Meteor methods to Fastify routes.#913
davemarco merged 33 commits into
y-scope:mainfrom
davemarco:routes

Conversation

@davemarco

@davemarco davemarco commented May 16, 2025

Copy link
Copy Markdown
Contributor

Description

This PR adds three fastify routes to replace meteor methods from old webui.
The methods were defined here previously:

clp/components/webui/imports/api/search/server/methods.js

The logic is basically identical. Main changes are related to typescript and porting to fastify.
Minor logic change was required to create searchJob and AggregationJob collections in query route, as
before they were created in meteor publication, which no longer exists.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

Created a simple test app, which was used to test all three routes. Routes functioned as expected. Here is code for test app. The package must be running to test


import {CssVarsProvider} from "@mui/joy";
import {useState} from "react";
import axios from "axios";

import {LOCAL_STORAGE_KEY} from "./typings/config";
import QueryStatus from "./ui/QueryStatus";


/**
 * Renders the main application.
 *
 * @return
 */
const App = () => {
    const [output, setOutput] = useState("");
    const [queryString, setQueryString] = useState("test query");
    const [timestampBegin, setTimestampBegin] = useState(0);
    const [timestampEnd, setTimestampEnd] = useState(Date.now());
    const [ignoreCase, setIgnoreCase] = useState(true);
    const [timeRangeBucketSizeMillis, setTimeRangeBucketSizeMillis] = useState(60000);
    const [searchJobId, setSearchJobId] = useState(1);
    const [aggregationJobId, setAggregationJobId] = useState(2);

    const sendRequest = async (url: string, method: string, body: object) => {
        try {
            const response = await axios({
                url,
                method,
                data: body,
                headers: {"Content-Type": "application/json"},
            });
            setOutput(JSON.stringify(response.data, null, 2));
        } catch (error: unknown) {
            if (axios.isAxiosError(error)) {
                setOutput(`Error: ${error.response?.data?.message || error.message}`);
            } else {
                setOutput(`Error: ${String(error)}`);
            }
        }
    };

    return (
        <CssVarsProvider modeStorageKey={LOCAL_STORAGE_KEY.THEME}>
            <QueryStatus/>
            <div style={{padding: "20px"}}>
                <h1>Search API Test</h1>
                <div>
                    <label>
                        Query String:
                        <input
                            type="text"
                            value={queryString}
                            onChange={(e) => setQueryString(e.target.value)}
                        />
                    </label>
                    <label>
                        Timestamp Begin:
                        <input
                            type="number"
                            value={timestampBegin}
                            onChange={(e) => setTimestampBegin(Number(e.target.value))}
                        />
                    </label>
                    <label>
                        Timestamp End:
                        <input
                            type="number"
                            value={timestampEnd}
                            onChange={(e) => setTimestampEnd(Number(e.target.value))}
                        />
                    </label>
                    <label>
                        Ignore Case:
                        <input
                            type="checkbox"
                            checked={ignoreCase}
                            onChange={(e) => setIgnoreCase(e.target.checked)}
                        />
                    </label>
                    <label>
                        Time Range Bucket Size (ms):
                        <input
                            type="number"
                            value={timeRangeBucketSizeMillis}
                            onChange={(e) => setTimeRangeBucketSizeMillis(Number(e.target.value))}
                        />
                    </label>
                    <label>
                        Search Job ID:
                        <input
                            type="number"
                            value={searchJobId}
                            onChange={(e) => setSearchJobId(Number(e.target.value))}
                        />
                    </label>
                    <label>
                        Aggregation Job ID:
                        <input
                            type="number"
                            value={aggregationJobId}
                            onChange={(e) => setAggregationJobId(Number(e.target.value))}
                        />
                    </label>
                </div>
                <button
                    onClick={() =>
                        sendRequest("/api/search/search", "POST", {
                            queryString,
                            timestampBegin,
                            timestampEnd,
                            ignoreCase,
                            timeRangeBucketSizeMillis,
                        })
                    }
                >
                    Submit Search
                </button>
                <button
                    onClick={() =>
                        sendRequest("/api/search/search/results", "DELETE", {
                            searchJobId,
                            aggregationJobId,
                        })
                    }
                >
                    Clear Results
                </button>
                <button
                    onClick={() =>
                        sendRequest("/api/search/search/cancel", "POST", {
                            searchJobId,
                            aggregationJobId,
                        })
                    }
                >
                    Cancel Search
                </button>
                <pre style={{marginTop: "20px", background: "#f4f4f4", padding: "10px"}}>
                    {output}
                </pre>
            </div>
        </CssVarsProvider>
    );
};

export default App;

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced API endpoints to submit, manage, and cancel search queries in the log viewer web UI backend.
    • Added validation schemas for search requests, IDs, strings, and error responses.
  • Refactor

    • Standardized error handling by using centralized HTTP status codes.
    • Improved type definitions and metadata updates for search results.
    • Added utilities for managing search metadata and MongoDB collections.
  • Chores

    • Removed deprecated search metadata plugin and example route code.
    • Enhanced ESLint configuration with additional exceptions for naming conventions.

@davemarco davemarco requested a review from a team as a code owner May 16, 2025 20:17
@coderabbitai

coderabbitai Bot commented May 16, 2025

Copy link
Copy Markdown
Contributor
## Walkthrough

This change removes the Fastify plugin for `SearchResultsMetadataCollection`, deletes a sample route, and introduces a new search API with supporting utility and schema modules. It also updates TypeScript typings, adjusts error handling, and refines ESLint and type definitions for search results metadata.

## Changes

| File(s)                                                                                                     | Change Summary                                                                                                                                                                                                                                                                                                                                                                                                         |
|-------------------------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| .../server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/index.ts                        | Removed the Fastify plugin and related type augmentations for exposing the SearchResultsMetadataCollection.                                                                                                                                                                                                                                                                    |
| .../server/src/fastify-v2/routes/sample.ts                                                                   | Deleted the sample Fastify route plugin for `/Example`.                                                                                                                                                                                                                                                                                                                        |
| .../server/src/fastify-v2/routes/api/search/index.ts                                                        | Added a new Fastify plugin implementing `/api/search` endpoints for query, results deletion, and cancellation, managing job submission and MongoDB metadata.                                                                                                                                                                                                                   |
| .../server/src/fastify-v2/routes/api/search/utils.ts                                                        | Added utility functions for checking collections, updating search results metadata, monitoring job completion, and creating MongoDB indexes.                                                                                                                                                                                                                                    |
| .../server/src/fastify-v2/routes/api/search/typings.ts                                                      | Added TypeScript typings and constants for search API operations, including metadata update and job monitoring parameters.                                                                                                                                                                                                                                                     |
| .../server/src/fastify-v2/schemas/common.ts                                                                 | Added common TypeBox JSON schemas for strings and IDs.                                                                                                                                                                                                                                                                                                                         |
| .../server/src/fastify-v2/schemas/error.ts                                                                  | Added a TypeBox JSON schema for API error responses.                                                                                                                                                                                                                                                                                                                           |
| .../server/src/fastify-v2/schemas/search.ts                                                                 | Added TypeBox JSON schemas for search job creation and job identification.                                                                                                                                                                                                                                                              |
| .../server/src/fastify-v2/app.ts                                                                            | Replaced a local HTTP 500 constant with `StatusCodes.INTERNAL_SERVER_ERROR` from `http-status-codes`.                                                                                                                                                                                                                                   |
| .../server/eslint.config.mjs                                                                                | Updated ESLint config: added `Type.Null` to exceptions.                                                                                                                                                                                                                                                                                                                            |
| .../common/searchResultsMetadata.ts                                                                         | Changed `errorMsg` property type from `Nullable<string>` to `string | null`, removed `Nullable` import, and reformatted `SEARCH_SIGNAL` export.                                                                                                                                                                                       |

## Sequence Diagram(s)

```mermaid
sequenceDiagram
    participant Client
    participant FastifyServer
    participant SQLJobManager
    participant MongoDB

    Client->>FastifyServer: POST /api/search/query
    FastifyServer->>SQLJobManager: Submit search & aggregation jobs
    SQLJobManager-->>FastifyServer: Return job IDs
    FastifyServer->>MongoDB: Ensure collections, insert metadata
    FastifyServer-->>Client: Respond with job IDs
    FastifyServer->>SQLJobManager: Monitor job completion (async)
    SQLJobManager-->>FastifyServer: Notify on completion
    FastifyServer->>MongoDB: Update metadata, create indexes

    Client->>FastifyServer: DELETE /api/search/results
    FastifyServer->>MongoDB: Drop collections
    FastifyServer-->>Client: Respond 204

    Client->>FastifyServer: POST /api/search/cancel
    FastifyServer->>SQLJobManager: Cancel jobs
    FastifyServer->>MongoDB: Update metadata as cancelled
    FastifyServer-->>Client: Respond 204

Possibly related PRs

  • y-scope/clp#912: Introduced the now-removed Fastify plugin for SearchResultsMetadataCollection, directly related to its removal here.

Suggested reviewers

  • junhaoliao

<!-- walkthrough_end -->


---

<details>
<summary>📜 Recent review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: ASSERTIVE**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between da1787642d7acf7f3c47b17b071fafa19bcde5a0 and 13c55e4a7165fe87564cfc5ba04ec2f955de336e.

</details>

<details>
<summary>📒 Files selected for processing (2)</summary>

* `components/log-viewer-webui/common/searchResultsMetadata.ts` (1 hunks)
* `components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts` (1 hunks)

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>📓 Path-based instructions (1)</summary>

<details>
<summary>`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == <expression>` rather than `!<expression>`.</summary>

> `**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == <expression>` rather than `!<expression>`.

- `components/log-viewer-webui/common/searchResultsMetadata.ts`
- `components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts`

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms (2)</summary>

* GitHub Check: lint-check (ubuntu-latest)
* GitHub Check: lint-check (macos-latest)

</details>

</details>
<!-- internal state start -->


<!-- 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 -->

<!-- internal state end -->
<!-- finishing_touch_checkbox_start -->

<details open="true">
<summary>✨ Finishing Touches</summary>

- [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings

</details>

<!-- finishing_touch_checkbox_end -->
<!-- tips_start -->

---

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.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=y-scope/clp&utm_content=913):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Explain this complex logic.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai explain this code block.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and explain its main purpose.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

### Support

Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 7

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ecb63cb and 99d9612.

📒 Files selected for processing (20)
  • components/log-viewer-webui/server/eslint.config.mjs (1 hunks)
  • components/log-viewer-webui/server/settings.json (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/app.ts (3 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/typings.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchJobCollectionsManager/index.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchJobCollectionsManager/typings.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/index.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/typings.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/schemas/common.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/schemas/error.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts (1 hunks)
  • components/log-viewer-webui/server/src/plugins/DbManager.ts (1 hunks)
  • components/log-viewer-webui/server/src/routes/query.ts (1 hunks)
  • components/log-viewer-webui/server/src/typings/DbManager.ts (0 hunks)
  • components/log-viewer-webui/server/src/typings/query.ts (1 hunks)
  • components/log-viewer-webui/server/tsconfig.json (1 hunks)
💤 Files with no reviewable changes (1)
  • components/log-viewer-webui/server/src/typings/DbManager.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/typings.ts
  • components/log-viewer-webui/server/src/fastify-v2/schemas/error.ts
  • components/log-viewer-webui/server/src/routes/query.ts
  • components/log-viewer-webui/server/src/fastify-v2/schemas/common.ts
  • components/log-viewer-webui/server/src/plugins/DbManager.ts
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchJobCollectionsManager/typings.ts
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/index.ts
  • components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchJobCollectionsManager/index.ts
  • components/log-viewer-webui/server/src/typings/query.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/typings.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts
  • components/log-viewer-webui/server/src/fastify-v2/app.ts
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts
🧬 Code Graph Analysis (4)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/index.ts (3)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts (1)
  • FastifyInstance (160-162)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchJobCollectionsManager/index.ts (1)
  • FastifyInstance (86-88)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/typings.ts (1)
  • SearchResultsMetadataDocument (32-32)
components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts (1)
components/log-viewer-webui/server/src/fastify-v2/schemas/common.ts (2)
  • StringSchema (10-10)
  • IdSchema (10-10)
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (6)
components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts (2)
  • CreateQueryJobSchema (25-25)
  • QueryJobSchema (26-26)
components/log-viewer-webui/server/src/fastify-v2/schemas/error.ts (1)
  • ErrorSchema (8-8)
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts (1)
  • SEARCH_MAX_NUM_RESULTS (42-42)
components/webui/imports/api/search/collections.js (1)
  • SearchResultsMetadataCollection (15-17)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/typings.ts (1)
  • SEARCH_SIGNAL (33-33)
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts (3)
  • updateSearchSignalWhenJobsFinish (141-141)
  • createMongoIndexes (139-139)
  • updateSearchResultsMeta (140-140)
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts (4)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/typings.ts (2)
  • SEARCH_SIGNAL (33-33)
  • SearchResultsMetadataDocument (32-32)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/index.ts (1)
  • FastifyInstance (26-28)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchJobCollectionsManager/index.ts (1)
  • FastifyInstance (86-88)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/sample.ts (1)
  • FastifyInstance (31-33)
🪛 Biome (1.9.4)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts

[error] 7-7: A Node.js builtin module should be imported with the node: protocol.

Using the node: protocol is more explicit and signals that the imported module belongs to Node.js.
Unsafe fix: Add the node: protocol.

(lint/style/useNodejsImportProtocol)

⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: lint-check (ubuntu-latest)
  • GitHub Check: lint-check (macos-latest)
🔇 Additional comments (30)
components/log-viewer-webui/server/settings.json (1)

11-11: MongoDB collection configuration added correctly

The new MongoDB collection name for search results metadata has been properly added to the settings file, maintaining the consistent naming pattern with other MongoDB collection settings.

components/log-viewer-webui/server/eslint.config.mjs (2)

28-28: Adding Type.Null exception to new-cap rule

This addition is appropriate for supporting TypeBox imports in the new code.


36-52: New max-len rule configuration

The max-len rule configuration looks reasonable with a 100-character limit. The TODO comment indicates this should eventually be moved to eslint-config-yscope.

components/log-viewer-webui/server/src/routes/query.ts (2)

7-10: Updated imports for job type constants

Import paths have been properly updated to reflect the refactoring that centralizes query job type definitions.


32-32: Coding convention correctly applied

Good job using the false === expression pattern instead of the !expression pattern, which follows the project's coding guidelines.

components/log-viewer-webui/server/src/fastify-v2/schemas/error.ts (1)

1-8: Well-structured error schema implementation

The error schema provides a clean, simple structure for consistent error responses across the API. The implementation follows TypeScript best practices with appropriate imports and exports.

components/log-viewer-webui/server/tsconfig.json (1)

21-22: Path alias for settings.json looks good.

Adding a path alias for the settings file makes imports cleaner and more maintainable throughout the codebase.

components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/typings.ts (1)

1-4: Well-documented polling interval constant.

Good use of JSDoc comments and appropriate naming convention for the constant. The 500ms polling interval is a reasonable balance between responsiveness and system load.

components/log-viewer-webui/server/src/fastify-v2/schemas/common.ts (1)

1-10: Well-structured common schema definitions.

Creating reusable schema validators is a good practice that ensures consistent validation across API endpoints. Both schemas enforce reasonable constraints:

  • StringSchema ensures non-empty strings
  • IdSchema ensures positive integers for IDs
components/log-viewer-webui/server/src/plugins/DbManager.ts (1)

13-24: Clean separation of type imports.

Good refactoring to separate MongoDB-related types from query-related types, improving code organization by grouping related types together. This separation of concerns enhances maintainability.

components/log-viewer-webui/server/src/fastify-v2/app.ts (5)

10-10: Good use of status code constants.

Using named constants from http-status-codes instead of magic numbers improves code readability and maintainability.


17-17: Clear file filtering pattern for autoloading.

The regex pattern properly identifies utility and typing files that shouldn't be autoloaded as plugins or routes.


51-52: Appropriate application of ignore pattern.

Good implementation of the ignore pattern for application plugins to prevent loading utility and typing files.


59-61: Clean route autoloading configuration.

Well-structured autoloading configuration with proper pattern exclusion for routes.


78-80: 🧹 Nitpick (assertive)

Consider using equality check pattern from coding guidelines.

While this comparison works correctly, the coding guidelines indicate a preference for false == <expression> pattern over negation operators.

Consider rewriting the condition to match the coding guidelines:

-        if ("undefined" !== typeof err.statusCode &&
-            StatusCodes.INTERNAL_SERVER_ERROR as number > err.statusCode
-        ) {
+        if ("undefined" !== typeof err.statusCode &&
+            false == (StatusCodes.INTERNAL_SERVER_ERROR as number <= err.statusCode)
+        ) {

Likely an incorrect or invalid review comment.

components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchJobCollectionsManager/typings.ts (2)

4-11: Well-structured document interface

The SearchResultsDocument interface provides a clear and complete structure for search results. Each field has a specific purpose and type, making it easy to understand and work with the data.


16-21: Properly implemented error class

The CollectionDroppedError class is well designed, extending the standard Error class with a meaningful error message and custom name. This will help with error identification and handling throughout the application.

components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts (2)

10-16: Well-defined request schema

The CreateQueryJobSchema correctly defines all necessary parameters for creating a query job with appropriate types. Using TypeBox ensures proper validation of incoming requests.


19-22: Appropriate job identification schema

The QueryJobSchema properly defines the structure for identifying a query job using both search and aggregation job IDs, leveraging the reusable IdSchema.

components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/typings.ts (2)

10-19: Comprehensive search signal enumeration

The SEARCH_SIGNAL enum effectively captures all the necessary states in the search lifecycle, clearly separating request signals from response signals. This provides a solid foundation for tracking search operation states.


25-30: Well-structured metadata document interface

The SearchResultsMetadataDocument interface is appropriately designed with clear field definitions. The optional numTotalResults field is properly documented, explaining that it's only set when the search job is completed.

components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/index.ts (2)

15-23: Well-implemented collection creation function

The function properly checks for database availability and throws a meaningful error if the database is not found. The collection is correctly typed with SearchResultsMetadataDocument and uses the collection name from settings.


31-41: Correctly implemented Fastify plugin

The plugin is properly structured using fastify-plugin, with appropriate decoration of the Fastify instance and named export. The implementation follows Fastify plugin best practices.

components/log-viewer-webui/server/src/typings/query.ts (1)

1-72: Code looks well structured and properly typed

This new TypeScript module provides clear enum definitions, constants, and interfaces for query jobs that appropriately extend MySQL row data types. The JSDoc comments and typing are comprehensive.

components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchJobCollectionsManager/index.ts (2)

19-83: Well-designed collection manager with proper error handling

The SearchJobCollectionsManager class effectively manages MongoDB collections for search jobs with appropriate error handling and defensive programming techniques. The implementation uses private class fields and static factory method pattern correctly.


85-101: Fastify plugin implementation follows best practices

The module correctly extends the Fastify interface and registers the manager as a singleton plugin using fastify-plugin.

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (1)

27-118: Search query route implemented with comprehensive workflow

The POST /query endpoint correctly implements a multi-step workflow with proper error handling, schema validation, and non-blocking signal updates.

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts (3)

21-39: Clean implementation of metadata updates

The updateSearchResultsMeta function properly handles metadata updates with appropriate logging and MongoDB operations.


52-100: Good error handling in the signal update function

The updateSearchSignalWhenJobsFinish function properly handles various error conditions, including specific handling for dropped collections, with appropriate early returns.


110-136: Effective MongoDB index creation implementation

The createMongoIndexes function correctly builds and applies both ascending and descending compound indexes on timestamp and _id fields, which should provide good query performance.

Comment on lines +123 to +163
fastify.delete(
"/results",
{
schema: {
body: QueryJobSchema,
response: {
[StatusCodes.NO_CONTENT]: Type.Null(),
[StatusCodes.INTERNAL_SERVER_ERROR]: ErrorSchema,
},
tags: ["Search"],
},
},
async (request, reply) => {
const {searchJobId, aggregationJobId} = request.body;

request.log.info({
searchJobId,
aggregationJobId,
}, "api/search/results args");

try {
await SearchJobCollectionsManager.dropCollection(searchJobId);
await SearchJobCollectionsManager.dropCollection(aggregationJobId);
} catch (err: unknown) {
const errMsg = "Failed to clear search results";
request.log.error(
{
err,
searchJobId,
aggregationJobId,
},
errMsg
);

return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, ` +
`aggregationJobId=${aggregationJobId}`);
}

return reply.code(StatusCodes.NO_CONTENT);
}
);

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.

🧹 Nitpick (assertive)

Consider using template literals instead of string concatenation

The error message uses string concatenation with the + operator which is less readable than template literals.

-                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, ` +
-                `aggregationJobId=${aggregationJobId}`);
+                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, aggregationJobId=${aggregationJobId}`);
🤖 Prompt for AI Agents
In components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts
between lines 123 and 163, the error message in the catch block uses string
concatenation with the + operator. Replace this concatenation with a single
template literal to improve readability and maintain consistency in string
formatting.

Comment on lines +166 to +217
fastify.post(
"/cancel",
{
schema: {
body: QueryJobSchema,
response: {
[StatusCodes.NO_CONTENT]: Type.Null(),
[StatusCodes.INTERNAL_SERVER_ERROR]: ErrorSchema,
},
tags: ["Search"],
},
},
async (request, reply) => {
const {searchJobId, aggregationJobId} = request.body;

request.log.info({
searchJobId,
aggregationJobId,
}, "api/search/cancel args");

try {
await QueryJobsDbManager.submitQueryCancellation(searchJobId);
await QueryJobsDbManager.submitQueryCancellation(aggregationJobId);

await updateSearchResultsMeta({
fields: {
lastSignal: SEARCH_SIGNAL.RESP_DONE,
errorMsg: "Query cancelled before it could be completed.",
},
jobId: searchJobId,
lastSignal: SEARCH_SIGNAL.RESP_QUERYING,
logger: request.log,
searchResultsMetadataCollection: SearchResultsMetadataCollection,
});
} catch (err: unknown) {
const errMsg = "Failed to submit cancel request";
request.log.error(
{
err,
searchJobId,
aggregationJobId,
},
errMsg
);

return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, ` +
`aggregationJobId=${aggregationJobId}`);
}

return reply.code(StatusCodes.NO_CONTENT);
}
);

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.

🧹 Nitpick (assertive)

Consider using template literals instead of string concatenation

Similar to the previous route, the error message uses string concatenation with the + operator which is less readable than template literals.

-                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, ` +
-                `aggregationJobId=${aggregationJobId}`);
+                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, aggregationJobId=${aggregationJobId}`);
📝 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
fastify.post(
"/cancel",
{
schema: {
body: QueryJobSchema,
response: {
[StatusCodes.NO_CONTENT]: Type.Null(),
[StatusCodes.INTERNAL_SERVER_ERROR]: ErrorSchema,
},
tags: ["Search"],
},
},
async (request, reply) => {
const {searchJobId, aggregationJobId} = request.body;
request.log.info({
searchJobId,
aggregationJobId,
}, "api/search/cancel args");
try {
await QueryJobsDbManager.submitQueryCancellation(searchJobId);
await QueryJobsDbManager.submitQueryCancellation(aggregationJobId);
await updateSearchResultsMeta({
fields: {
lastSignal: SEARCH_SIGNAL.RESP_DONE,
errorMsg: "Query cancelled before it could be completed.",
},
jobId: searchJobId,
lastSignal: SEARCH_SIGNAL.RESP_QUERYING,
logger: request.log,
searchResultsMetadataCollection: SearchResultsMetadataCollection,
});
} catch (err: unknown) {
const errMsg = "Failed to submit cancel request";
request.log.error(
{
err,
searchJobId,
aggregationJobId,
},
errMsg
);
return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, ` +
`aggregationJobId=${aggregationJobId}`);
}
return reply.code(StatusCodes.NO_CONTENT);
}
);
} catch (err: unknown) {
const errMsg = "Failed to submit cancel request";
request.log.error(
{
err,
searchJobId,
aggregationJobId,
},
errMsg
);
return reply.internalServerError(
`${errMsg} for searchJobId=${searchJobId}, aggregationJobId=${aggregationJobId}`
);
}
return reply.code(StatusCodes.NO_CONTENT);
}
);
🤖 Prompt for AI Agents
In components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts
between lines 166 and 217, the error message in the catch block uses string
concatenation with the + operator. Replace this concatenation with a single
template literal to improve readability and maintain consistency with other
parts of the code.

Comment on lines +17 to +23
type UpdateSearchResultsMetaProps = {
jobId: number;
lastSignal: SEARCH_SIGNAL;
searchResultsMetadataCollection: FastifyInstance["SearchResultsMetadataCollection"];
logger: FastifyBaseLogger;
fields: Partial<SearchResultsMetadataDocument>;
};

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.

🧹 Nitpick (assertive)

Guard against unintended mutation of fields

fields will likely be forwarded to MongoDB’s $set update. Wrapping it in Readonly helps catch accidental in-place mutations at compile-time:

-    fields: Partial<SearchResultsMetadataDocument>;
+    fields: Readonly<Partial<SearchResultsMetadataDocument>>;

This is a zero-cost change that tightens the contract.

📝 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
type UpdateSearchResultsMetaProps = {
jobId: number;
lastSignal: SEARCH_SIGNAL;
searchResultsMetadataCollection: FastifyInstance["SearchResultsMetadataCollection"];
logger: FastifyBaseLogger;
fields: Partial<SearchResultsMetadataDocument>;
};
type UpdateSearchResultsMetaProps = {
jobId: number;
lastSignal: SEARCH_SIGNAL;
searchResultsMetadataCollection: FastifyInstance["SearchResultsMetadataCollection"];
logger: FastifyBaseLogger;
fields: Readonly<Partial<SearchResultsMetadataDocument>>;
};
🤖 Prompt for AI Agents
In
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts
around lines 17 to 23, the fields property in UpdateSearchResultsMetaProps is
mutable but will be forwarded to MongoDB’s $set update. To prevent accidental
in-place mutations, change the type of fields to
Readonly<Partial<SearchResultsMetadataDocument>>. This enforces immutability at
compile-time without runtime cost.

Comment on lines +110 to +156
async awaitJobCompletion (jobId: number): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
while (true) {
let rows: QueryJob[];
try {
const [queryRows] = await this.#sqlDbConnPool.query<QueryJob[]>(
`
SELECT ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS}
FROM ${settings.SqlDbQueryJobsTableName}
WHERE ${QUERY_JOBS_TABLE_COLUMN_NAMES.ID} = ?
`,
jobId
);

rows = queryRows;
} catch (e: unknown) {
let errorMessage: string;

if (e instanceof Error) {
errorMessage = e.message;
} else {
errorMessage = String(e);
}

throw new Error(`Failed to query status for job ${jobId} - ${errorMessage}`);
}
if (0 === rows.length) {
throw new Error(`Job ${jobId} not found in database.`);
}

const status = (rows[0] as QueryJob)[QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS];

if (false === QUERY_JOB_STATUS_WAITING_STATES.has(status)) {
if (QUERY_JOB_STATUS.CANCELLED === status) {
throw new Error(`Job ${jobId} was cancelled.`);
} else if (QUERY_JOB_STATUS.SUCCEEDED !== status) {
throw new Error(
`Job ${jobId} exited with unexpected status=${status}: ` +
`${Object.keys(QUERY_JOB_STATUS)[status]}.`
);
}
break;
}

await setTimeout(JOB_COMPLETION_STATUS_POLL_INTERVAL_MILLIS);
}
}

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.

⚠️ Potential issue

Add an upper-bound timeout when awaiting job completion

The current while (true) loop polls indefinitely.
If the job hangs or a DB network partition occurs, the promise never resolves, tying up a Fastify request thread forever and risking memory leaks.

Suggested defensive enhancement:

+        const ABS_TIMEOUT = Date.now() + settings.JobCompletionMaxWaitMillis; // e.g. 10 min
         // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
         while (true) {
@@
             await setTimeout(JOB_COMPLETION_STATUS_POLL_INTERVAL_MILLIS);
+
+            if (Date.now() > ABS_TIMEOUT) {
+                throw new Error(
+                    `Timed out waiting for job ${jobId} after ` +
+                    `${settings.JobCompletionMaxWaitMillis} ms`,
+                );
+            }
         }

This change prevents runaway loops and surfaces issues to the caller in a predictable manner.

📝 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
async awaitJobCompletion (jobId: number): Promise<void> {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
while (true) {
let rows: QueryJob[];
try {
const [queryRows] = await this.#sqlDbConnPool.query<QueryJob[]>(
`
SELECT ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS}
FROM ${settings.SqlDbQueryJobsTableName}
WHERE ${QUERY_JOBS_TABLE_COLUMN_NAMES.ID} = ?
`,
jobId
);
rows = queryRows;
} catch (e: unknown) {
let errorMessage: string;
if (e instanceof Error) {
errorMessage = e.message;
} else {
errorMessage = String(e);
}
throw new Error(`Failed to query status for job ${jobId} - ${errorMessage}`);
}
if (0 === rows.length) {
throw new Error(`Job ${jobId} not found in database.`);
}
const status = (rows[0] as QueryJob)[QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS];
if (false === QUERY_JOB_STATUS_WAITING_STATES.has(status)) {
if (QUERY_JOB_STATUS.CANCELLED === status) {
throw new Error(`Job ${jobId} was cancelled.`);
} else if (QUERY_JOB_STATUS.SUCCEEDED !== status) {
throw new Error(
`Job ${jobId} exited with unexpected status=${status}: ` +
`${Object.keys(QUERY_JOB_STATUS)[status]}.`
);
}
break;
}
await setTimeout(JOB_COMPLETION_STATUS_POLL_INTERVAL_MILLIS);
}
}
async awaitJobCompletion (jobId: number): Promise<void> {
// set an absolute timeout so this loop can’t spin forever
const ABS_TIMEOUT = Date.now() + settings.JobCompletionMaxWaitMillis; // e.g. 10 min
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
while (true) {
let rows: QueryJob[];
try {
const [queryRows] = await this.#sqlDbConnPool.query<QueryJob[]>(
`
SELECT ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS}
FROM ${settings.SqlDbQueryJobsTableName}
WHERE ${QUERY_JOBS_TABLE_COLUMN_NAMES.ID} = ?
`,
jobId
);
rows = queryRows;
} catch (e: unknown) {
let errorMessage: string;
if (e instanceof Error) {
errorMessage = e.message;
} else {
errorMessage = String(e);
}
throw new Error(`Failed to query status for job ${jobId} - ${errorMessage}`);
}
if (0 === rows.length) {
throw new Error(`Job ${jobId} not found in database.`);
}
const status = (rows[0] as QueryJob)[QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS];
if (false === QUERY_JOB_STATUS_WAITING_STATES.has(status)) {
if (QUERY_JOB_STATUS.CANCELLED === status) {
throw new Error(`Job ${jobId} was cancelled.`);
} else if (QUERY_JOB_STATUS.SUCCEEDED !== status) {
throw new Error(
`Job ${jobId} exited with unexpected status=${status}: ` +
`${Object.keys(QUERY_JOB_STATUS)[status]}.`
);
}
break;
}
await setTimeout(JOB_COMPLETION_STATUS_POLL_INTERVAL_MILLIS);
if (Date.now() > ABS_TIMEOUT) {
throw new Error(
`Timed out waiting for job ${jobId} after ` +
`${settings.JobCompletionMaxWaitMillis} ms`
);
}
}
}
🤖 Prompt for AI Agents
In
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts
between lines 110 and 156, the awaitJobCompletion method uses an infinite
while(true) loop to poll job status, which can cause indefinite hanging if the
job never completes or the database is unreachable. To fix this, introduce an
upper-bound timeout or maximum retry count for the polling loop. Track elapsed
time or number of attempts and throw a timeout error if the limit is exceeded,
ensuring the promise resolves or rejects predictably and preventing resource
leaks.

Comment on lines +91 to +99
async submitQueryCancellation (jobId: number): Promise<void> {
await this.#sqlDbConnPool.query(
`UPDATE ${settings.SqlDbQueryJobsTableName}
SET ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS} = ${QUERY_JOB_STATUS.CANCELLING}
WHERE ${QUERY_JOBS_TABLE_COLUMN_NAMES.ID} = ?
AND ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS}
IN (${QUERY_JOB_STATUS.PENDING}, ${QUERY_JOB_STATUS.RUNNING})`,
jobId,
);

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.

🛠️ Refactor suggestion

Parameterise status constants to prevent SQL-injection-like surprises

Although QUERY_JOB_STATUS.* are numeric enums, embedding them directly in the SQL string still mixes data with code. Use placeholders for consistency and to prevent future regressions if the enum ever becomes a string:

-                SET ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS} = ${QUERY_JOB_STATUS.CANCELLING}
+                SET ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS} = ?
                 WHERE ${QUERY_JOBS_TABLE_COLUMN_NAMES.ID} = ?
-                AND ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS}
-                IN (${QUERY_JOB_STATUS.PENDING}, ${QUERY_JOB_STATUS.RUNNING})`,
-            jobId,
+                AND ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS} IN (?, ?)`,
+            [
+                QUERY_JOB_STATUS.CANCELLING,
+                jobId,
+                QUERY_JOB_STATUS.PENDING,
+                QUERY_JOB_STATUS.RUNNING,
+            ],

This maintains the strong guarantee that all dynamic values are bound variables.

📝 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
async submitQueryCancellation (jobId: number): Promise<void> {
await this.#sqlDbConnPool.query(
`UPDATE ${settings.SqlDbQueryJobsTableName}
SET ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS} = ${QUERY_JOB_STATUS.CANCELLING}
WHERE ${QUERY_JOBS_TABLE_COLUMN_NAMES.ID} = ?
AND ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS}
IN (${QUERY_JOB_STATUS.PENDING}, ${QUERY_JOB_STATUS.RUNNING})`,
jobId,
);
async submitQueryCancellation (jobId: number): Promise<void> {
await this.#sqlDbConnPool.query(
`UPDATE ${settings.SqlDbQueryJobsTableName}
SET ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS} = ?
WHERE ${QUERY_JOBS_TABLE_COLUMN_NAMES.ID} = ?
AND ${QUERY_JOBS_TABLE_COLUMN_NAMES.STATUS} IN (?, ?)`,
[
QUERY_JOB_STATUS.CANCELLING,
jobId,
QUERY_JOB_STATUS.PENDING,
QUERY_JOB_STATUS.RUNNING,
],
);
}
🤖 Prompt for AI Agents
In
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts
around lines 91 to 99, the SQL query embeds numeric enum constants directly in
the query string, which risks mixing data with code and potential SQL injection
if enums change. Refactor the query to use placeholders for all dynamic values,
including the status constants, and pass them as bound parameters in the query
call to ensure all dynamic data is parameterized safely.

@davemarco davemarco changed the title feat(new-webui): Add fastify routes for search api. feat(new-webui): Port meteor methods to fastify routes for search api. May 16, 2025
@davemarco davemarco changed the title feat(new-webui): Port meteor methods to fastify routes for search api. feat(new-webui): Port meteor methods to Fastify routes for search api. May 16, 2025
@davemarco davemarco changed the title feat(new-webui): Port meteor methods to Fastify routes for search api. feat(new-webui): Port Meteor methods to Fastify routes for search api. May 16, 2025

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 22

🔭 Outside diff range comments (1)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts (1)

1-25: ⚠️ Potential issue

Fix import sorting and duplicate import issues.

The linting pipeline indicates several import-related issues that need to be addressed.

Apply this diff to fix the import issues:

+import type {
+    Collection,
+    Db,
+} from "mongodb";
 import {setTimeout} from "node:timers/promises";

 import type {MySQLPromisePool} from "@fastify/mysql";
 import {encode} from "@msgpack/msgpack";
 import {FastifyInstance} from "fastify";
 import fp from "fastify-plugin";
 import {ResultSetHeader} from "mysql2";

 import settings from "../../../../../../settings.json" with {type: "json"};
 import {
     QUERY_JOB_STATUS,
     QUERY_JOB_STATUS_WAITING_STATES,
     QUERY_JOB_TYPE,
     QUERY_JOBS_TABLE_COLUMN_NAMES,
     QueryJob,
 } from "../../../../../typings/query.js";
 import {JOB_COMPLETION_STATUS_POLL_INTERVAL_MILLIS} from "./typings.js";
-
-import type {
-    Collection,
-    Db,
-} from "mongodb";
-
-import type {SearchResultsMetadataDocument} from "./typings.js";
+import type {SearchResultsMetadataDocument} from "./typings.js";
🧰 Tools
🪛 GitHub Actions: clp-lint

[warning] 1-1: Run autofix to sort these imports! (simple-import-sort/imports)


[error] 24-24: './typings.js' import is duplicated (no-duplicate-imports)

♻️ Duplicate comments (5)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts (2)

113-124: Previous review comment still applies: Parameterize status constants.

The SQL injection concern raised in previous reviews about embedding status constants directly in the SQL string is still valid and should be addressed.


134-172: Previous review comment still applies: Add timeout to job completion polling.

The infinite loop timeout issue identified in previous reviews for the awaitJobCompletion method still needs to be addressed to prevent indefinite hanging.

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (1)

207-208: Use template literals instead of string concatenation.

The string concatenation issue identified in previous reviews should be addressed for better readability.

Apply this diff:

-                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, ` +
-                `aggregationJobId=${aggregationJobId}`);
+                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, aggregationJobId=${aggregationJobId}`);
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts (2)

31-31: Consider exporting the constant inline for clarity.

The previous review comment about exporting the constant inline is still valid and should be addressed for better code clarity.


38-38: Guard against unintended mutation of fields.

The previous review comment about making the fields property readonly is still valid and should be addressed to prevent accidental mutations.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 99d9612 and 5bb5538.

📒 Files selected for processing (10)
  • components/log-viewer-webui/common/searchResultsMetadata.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/app.ts (3 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts (2 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/typings.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/index.ts (0 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/sample.ts (0 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/schemas/common.ts (1 hunks)
💤 Files with no reviewable changes (2)
  • components/log-viewer-webui/server/src/fastify-v2/routes/sample.ts
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/SearchResultsMetadataCollection/index.ts
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/server/src/fastify-v2/schemas/common.ts
  • components/log-viewer-webui/common/searchResultsMetadata.ts
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts
  • components/log-viewer-webui/server/src/fastify-v2/app.ts
  • components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/typings.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts
🪛 GitHub Actions: clp-lint
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts

[warning] 1-1: Run autofix to sort these imports! (simple-import-sort/imports)


[error] 24-24: './typings.js' import is duplicated (no-duplicate-imports)


[error] 32-33: Expected blank line between class members (@stylistic/lines-between-class-members); '#searchResultsMetadataCollection' is defined but never used (no-unused-private-class-members)


[error] 37-37: Missing semicolon (@stylistic/semi)


[warning] 39-39: This line has a length of 104. Maximum allowed is 100 (@stylistic/max-len)


[warning] 44-44: Missing JSDoc @throws declaration (jsdoc/require-throws)


[error] 50-50: Block must not be padded by blank lines (@stylistic/padded-blocks)

components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/typings.ts

[error] 1-1: Expected 2 empty lines after import statement not followed by another import (import/newline-after-import)

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts

[warning] 1-1: Run autofix to sort these imports! (simple-import-sort/imports)


[error] 13-13: Imports must be broken into multiple lines if there are more than 1 elements (import-newlines/enforce); Expected a line break after this opening brace (@stylistic/object-curly-newline); Expected a line break before this closing brace (@stylistic/object-curly-newline)


[error] 20-20: Expected 2 empty lines after import statement not followed by another import (import/newline-after-import)


[error] 33-33: Missing semicolon (@stylistic/semi)

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts

[error] 1-1: Too many blank lines at the beginning of file. Max of 0 allowed (@stylistic/no-multiple-empty-lines)


[warning] 2-2: Run autofix to sort these imports! (simple-import-sort/imports)


[error] 8-8: Expected 2 empty lines after import statement not followed by another import (import/newline-after-import)


[error] 17-19: Unexpected any. Specify a different type (@typescript-eslint/no-explicit-any); Unsafe assignment of an any value (@typescript-eslint/no-unsafe-assignment); Unsafe call of a(n) any typed value (@typescript-eslint/no-unsafe-call); Unsafe member access on an any value (@typescript-eslint/no-unsafe-member-access); Unsafe return of a value of type any (@typescript-eslint/no-unsafe-return)


[error] 19-19: Unexpected space(s) after '{' and before '}' (@stylistic/block-spacing, @stylistic/object-curly-spacing)


[warning] 52-118: Missing JSDoc @param "props.mongoDb" declaration and missing or incorrect @param names (jsdoc/require-param, jsdoc/check-param-names)


[error] 92-92: There should be no space before this paren (@stylistic/space-in-parens)


[warning] 93-93: Expected blank line before this statement (@stylistic/padding-line-between-statements)


[warning] 148-148: Run autofix to sort these exports! (simple-import-sort/exports)

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts

[warning] 1-1: Run autofix to sort these imports! (simple-import-sort/imports)


[error] 6-8: Imports must not be broken into multiple lines if there are 1 or less elements (import-newlines/enforce); Unexpected line break after this opening brace (@stylistic/object-curly-newline); Unexpected line break before this closing brace (@stylistic/object-curly-newline)


[error] 15-15: Expected 2 empty lines after import statement not followed by another import (import/newline-after-import); There should be no space after '{' (@stylistic/object-curly-spacing); There should be no space before '}' (@stylistic/object-curly-spacing)


[error] 44-54: Expected a semicolon (@stylistic/member-delimiter-style)


[warning] 57-57: Run autofix to sort these exports! (simple-import-sort/exports)

🔇 Additional comments (8)
components/log-viewer-webui/common/searchResultsMetadata.ts (3)

7-16: LGTM! Well-defined enum structure.

The SEARCH_SIGNAL enum provides clear categorization of request and response states for search operations, making the API more predictable and type-safe.


22-27: Good explicit typing approach.

Using string | null instead of a Nullable type alias improves clarity and reduces dependency on additional type definitions.


30-32: Export formatting is consistent.

The multi-line export format improves readability and follows common TypeScript conventions.

components/log-viewer-webui/server/src/fastify-v2/schemas/common.ts (2)

4-6: Solid string validation schema.

The StringSchema with minLength constraint effectively prevents empty string inputs, which is essential for API validation.


8-8: Appropriate ID validation.

The IdSchema ensures positive integer values, which aligns with typical database ID requirements.

components/log-viewer-webui/server/src/fastify-v2/app.ts (3)

10-10: Good practice using status code constants.

Importing StatusCodes improves code maintainability and reduces magic numbers.


17-17: Effective file filtering pattern.

The regex pattern correctly excludes utility and typings files from autoloading, preventing them from being treated as plugins.


77-79:

Details

✅ Verification successful

Verify error handling logic correctness.

The condition checks if err.statusCode < 500 to use the original status code, otherwise defaults to internal server error. This logic appears sound but should be verified for edge cases.


🏁 Script executed:

#!/bin/bash
# Description: Verify error handling patterns in similar Fastify applications
# Expected: Confirm this is a standard pattern for error status code handling

rg -A 5 -B 5 "StatusCodes\.INTERNAL_SERVER_ERROR.*err\.statusCode|err\.statusCode.*StatusCodes\.INTERNAL_SERVER_ERROR"

Length of output: 1034


Error handling logic verified

The condition in components/log-viewer-webui/server/src/fastify-v2/app.ts (lines 77–79) correctly uses any defined err.statusCode below 500 and defaults to 500 otherwise. This matches Fastify’s typical distinction between client and server errors—no changes needed here.

Comment on lines +14 to +23
enum SEARCH_SIGNAL {
NONE = "none",

REQ_CANCELLING = "req-cancelling",
REQ_CLEARING = "req-clearing",
REQ_QUERYING = "req-querying",

RESP_DONE = "resp-done",
RESP_QUERYING = "resp-querying",
}

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.

🛠️ Refactor suggestion

Address code duplication with common module.

The SEARCH_SIGNAL enum is duplicated between this file and components/log-viewer-webui/common/searchResultsMetadata.ts. This creates maintenance overhead and potential inconsistencies.

Consider importing the enum from the common module instead:

-enum SEARCH_SIGNAL {
-    NONE = "none",
-
-    REQ_CANCELLING = "req-cancelling",
-    REQ_CLEARING = "req-clearing",
-    REQ_QUERYING = "req-querying",
-
-    RESP_DONE = "resp-done",
-    RESP_QUERYING = "resp-querying",
-}
+import {SEARCH_SIGNAL} from "../../../../../common/searchResultsMetadata.js";

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/typings.ts
around lines 14 to 23, the SEARCH_SIGNAL enum is duplicated from
components/log-viewer-webui/common/searchResultsMetadata.ts. To fix this, remove
the enum declaration here and instead import SEARCH_SIGNAL from the common
module to avoid duplication and ensure consistency.

Comment on lines +29 to +34
interface SearchResultsMetadataDocument {
_id: string;
errorMsg: Nullable<string>;
lastSignal: SEARCH_SIGNAL;
numTotalResults?: number;
}

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.

⚠️ Potential issue

Fix type inconsistency and eliminate duplication.

The SearchResultsMetadataDocument interface is duplicated with a type inconsistency. In the common module, errorMsg is typed as string | null, but here it uses Nullable<string>. This creates potential runtime issues and maintenance problems.

Consider importing the interface from the common module and ensuring consistent typing:

-interface SearchResultsMetadataDocument {
-    _id: string;
-    errorMsg: Nullable<string>;
-    lastSignal: SEARCH_SIGNAL;
-    numTotalResults?: number;
-}
+import {SearchResultsMetadataDocument} from "../../../../../common/searchResultsMetadata.js";

This also eliminates the need for the Nullable import if no other types in this file require it.

📝 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
interface SearchResultsMetadataDocument {
_id: string;
errorMsg: Nullable<string>;
lastSignal: SEARCH_SIGNAL;
numTotalResults?: number;
}
import {SearchResultsMetadataDocument} from "../../../../../common/searchResultsMetadata.js";
🤖 Prompt for AI Agents
In
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/typings.ts
around lines 29 to 34, the SearchResultsMetadataDocument interface is duplicated
and uses Nullable<string> for errorMsg, causing type inconsistency with the
common module where errorMsg is string | null. To fix this, remove the local
interface definition and import SearchResultsMetadataDocument directly from the
common module to ensure consistent typing and eliminate duplication. Also,
remove the Nullable import if it is no longer needed elsewhere in the file.

Comment on lines +39 to +41
this.#searchResultsMetadataCollection = this.#mongoDb.collection<SearchResultsMetadataDocument>(
settings.MongoDbSearchResultsMetadataCollectionName
);

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.

🧹 Nitpick (assertive)

Fix line length and add proper spacing.

The line exceeds the maximum allowed length of 100 characters.

-        this.#searchResultsMetadataCollection = this.#mongoDb.collection<SearchResultsMetadataDocument>(
-            settings.MongoDbSearchResultsMetadataCollectionName
-        );
+        this.#searchResultsMetadataCollection = this.#mongoDb
+            .collection<SearchResultsMetadataDocument>(
+                settings.MongoDbSearchResultsMetadataCollectionName
+            );
📝 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
this.#searchResultsMetadataCollection = this.#mongoDb.collection<SearchResultsMetadataDocument>(
settings.MongoDbSearchResultsMetadataCollectionName
);
this.#searchResultsMetadataCollection = this.#mongoDb
.collection<SearchResultsMetadataDocument>(
settings.MongoDbSearchResultsMetadataCollectionName
);
🧰 Tools
🪛 GitHub Actions: clp-lint

[warning] 39-39: This line has a length of 104. Maximum allowed is 100 (@stylistic/max-len)

🤖 Prompt for AI Agents
In
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts
around lines 39 to 41, the line assigning this.#searchResultsMetadataCollection
exceeds 100 characters. Break the line into multiple lines to keep each under
100 characters and add proper spacing for readability, such as placing the
collection name argument on a new line and aligning parentheses correctly.

Comment thread components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts Outdated
Comment thread components/log-viewer-webui/server/src/fastify-v2/routes/api/search/utils.ts Outdated
Comment thread components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts Outdated
Comment on lines +1 to +16
import {
FastifyBaseLogger,
FastifyInstance,
} from "fastify";

import {
SEARCH_SIGNAL,
} from "@common/searchResultsMetadata.js";

import type {
Collection,
Db,
} from "mongodb";

import { Nullable } from "../../../../typings/common.js";

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.

⚠️ Potential issue

Fix import sorting and formatting issues.

Multiple linting issues need to be addressed in the import section.

Apply this diff to fix the import and formatting issues:

-import {
-    FastifyBaseLogger,
-    FastifyInstance,
-} from "fastify";
+import {FastifyBaseLogger, FastifyInstance} from "fastify";
+import type {Collection, Db} from "mongodb";

-import {
-    SEARCH_SIGNAL,
-} from "@common/searchResultsMetadata.js";
+import {SEARCH_SIGNAL} from "@common/searchResultsMetadata.js";
+import {Nullable} from "../../../../typings/common.js";

-import type {
-    Collection,
-    Db,
-} from "mongodb";

-import { Nullable } from "../../../../typings/common.js";

+
📝 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
import {
FastifyBaseLogger,
FastifyInstance,
} from "fastify";
import {
SEARCH_SIGNAL,
} from "@common/searchResultsMetadata.js";
import type {
Collection,
Db,
} from "mongodb";
import { Nullable } from "../../../../typings/common.js";
import {FastifyBaseLogger, FastifyInstance} from "fastify";
import type {Collection, Db} from "mongodb";
import {SEARCH_SIGNAL} from "@common/searchResultsMetadata.js";
import {Nullable} from "../../../../typings/common.js";
🧰 Tools
🪛 GitHub Actions: clp-lint

[warning] 1-1: Run autofix to sort these imports! (simple-import-sort/imports)


[error] 6-8: Imports must not be broken into multiple lines if there are 1 or less elements (import-newlines/enforce); Unexpected line break after this opening brace (@stylistic/object-curly-newline); Unexpected line break before this closing brace (@stylistic/object-curly-newline)


[error] 15-15: Expected 2 empty lines after import statement not followed by another import (import/newline-after-import); There should be no space after '{' (@stylistic/object-curly-spacing); There should be no space before '}' (@stylistic/object-curly-spacing)

🤖 Prompt for AI Agents
In
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts
lines 1 to 16, the import statements have sorting and formatting issues causing
lint errors. Reorder the imports alphabetically by module source, group related
imports together, and ensure consistent spacing and line breaks between import
groups. Also, align the import braces and remove any unnecessary blank lines to
comply with linting rules.

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

♻️ Duplicate comments (10)
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (5)

1-21: Fix import sorting, formatting, and spacing issues.

Multiple linting issues need to be addressed in the import section.

Apply this diff to fix the import and formatting issues:

-import {
-    FastifyPluginAsyncTypebox,
-    Type,
-} from "@fastify/type-provider-typebox";
+import {FastifyPluginAsyncTypebox, Type} from "@fastify/type-provider-typebox";
 import {StatusCodes} from "http-status-codes";

 import {SEARCH_SIGNAL} from "@common/searchResultsMetadata.js";
 import {ErrorSchema} from "../../../schemas/error.js";
 import {
     CreateQueryJobSchema,
     QueryJobSchema,
 } from "../../../schemas/search.js";
-import {SEARCH_MAX_NUM_RESULTS, SearchResultsMetadataDocument} from "./typings.js";
+import {
+    SEARCH_MAX_NUM_RESULTS,
+    SearchResultsMetadataDocument,
+} from "./typings.js";
 import {
     createMongoIndexes,
     updateSearchResultsMeta,
     updateSearchSignalWhenJobsFinish,
 } from "./utils.js";

+
 import settings from "../../../../../settings.json" with {type: "json"};
🧰 Tools
🪛 GitHub Actions: clp-lint

[error] 1-33: ESLint errors: imports must be broken into multiple lines (line 13), expected line breaks after opening and before closing braces (line 13), expected 2 empty lines after import statement (line 20), missing semicolon (line 33); also warnings for import sorting.


33-33: Add missing semicolon.

The linting pipeline indicates a missing semicolon.

-    const mongoDb = mongo.db
+    const mongoDb = mongo.db;
🧰 Tools
🪛 GitHub Actions: clp-lint

[error] 1-33: ESLint errors: imports must be broken into multiple lines (line 13), expected line breaks after opening and before closing braces (line 13), expected 2 empty lines after import statement (line 20), missing semicolon (line 33); also warnings for import sorting.


93-94: Add error handling for MongoDB collection creation.

The comment indicates collections should not throw errors if they already exist, but it's better to handle potential errors explicitly.

-            await mongoDb.createCollection(searchJobId.toString());
-            await mongoDb.createCollection(aggregationJobId.toString());
+            try {
+                // Should not throw an error if the collection already exists.
+                await mongoDb.createCollection(searchJobId.toString());
+                await mongoDb.createCollection(aggregationJobId.toString());
+            } catch (err: unknown) {
+                // Collection might already exist, which is fine
+                request.log.debug(err, "Collection creation failed (might already exist)");
+            }

152-153: Add error handling for collection drop operations.

The collection drop operations should include error handling in case the collections don't exist.

-            await mongoDb.collection(searchJobId.toString()).drop();
-            await mongoDb.collection(aggregationJobId.toString()).drop();
+            try {
+                await mongoDb.collection(searchJobId.toString()).drop();
+                await mongoDb.collection(aggregationJobId.toString()).drop();
+            } catch (err: unknown) {
+                const errMsg = "Failed to drop search result collections";
+                request.log.error(err, errMsg);
+                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, aggregationJobId=${aggregationJobId}`);
+            }

205-206: Consider using template literals instead of string concatenation

The error message uses string concatenation with the + operator which is less readable than template literals.

-                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, ` +
-                `aggregationJobId=${aggregationJobId}`);
+                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, aggregationJobId=${aggregationJobId}`);
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts (5)

1-15: Fix import sorting and formatting issues.

Multiple linting issues need to be addressed in the import section.

Apply this diff to fix the import and formatting issues:

-import {
-    FastifyBaseLogger,
-    FastifyInstance,
-} from "fastify";
+import {FastifyBaseLogger, FastifyInstance} from "fastify";
+import type {Collection, Db} from "mongodb";

-import {
-    SEARCH_SIGNAL,
-    SearchResultsMetadataDocument,
-} from "@common/searchResultsMetadata.js";
+import {SEARCH_SIGNAL, SearchResultsMetadataDocument} from "@common/searchResultsMetadata.js";

-import type {
-    Collection,
-    Db,
-} from "mongodb";

+
🧰 Tools
🪛 GitHub Actions: clp-lint

[error] 1-45: ESLint errors: expected 2 empty lines after import (line 14), expected semicolons (lines 32, 42); warnings for import and export sorting.


19-19: Consider exporting the constant inline for clarity

Declaring & exporting in one step makes the intent unmistakable and avoids the risk of the variable being mutated before export.

-const SEARCH_MAX_NUM_RESULTS = 1000;
+export const SEARCH_MAX_NUM_RESULTS = 1_000 as const;

Using the numeric separator also improves readability.


22-22: Guard against unintended mutation of fields

fields will likely be forwarded to MongoDB's $set update. Wrapping it in Readonly helps catch accidental in-place mutations at compile-time:

-    fields: Partial<SearchResultsMetadataDocument>;
+    fields: Readonly<Partial<SearchResultsMetadataDocument>>;

This is a zero-cost change that tightens the contract.


29-43: Add missing semicolons.

The linting pipeline indicates missing semicolons in the type definitions.

 type UpdateSearchSignalWhenJobsFinishProps = {
     aggregationJobId: number;
     logger: FastifyBaseLogger;
-    mongoDb: Db,
+    mongoDb: Db;
     queryJobsDbManager: FastifyInstance["QueryJobsDbManager"];
     searchJobId: number;
     searchResultsMetadataCollection: Collection<SearchResultsMetadataDocument>;
-
 };

 type CreateMongoIndexesProps = {
     searchJobId: number;
     logger: FastifyBaseLogger;
-    mongoDb: Db,
+    mongoDb: Db;
 };

45-51: Fix export sorting.

The linting pipeline indicates the exports should be sorted alphabetically.

 export {
     CreateMongoIndexesProps,
     SEARCH_MAX_NUM_RESULTS,
-    UpdateSearchResultsMetaProps,
     SearchResultsMetadataDocument,
+    UpdateSearchResultsMetaProps,
     UpdateSearchSignalWhenJobsFinishProps,
 };
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5bb5538 and 93c53cb.

📒 Files selected for processing (4)
  • components/log-viewer-webui/common/searchResultsMetadata.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/app.ts (2 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/server/src/fastify-v2/app.ts
  • components/log-viewer-webui/common/searchResultsMetadata.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts
🧬 Code Graph Analysis (1)
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts (3)
components/log-viewer-webui/common/searchResultsMetadata.ts (2)
  • SearchResultsMetadataDocument (29-29)
  • SEARCH_SIGNAL (31-31)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/search/QueryJobsDbManager/index.ts (1)
  • FastifyInstance (158-160)
components/log-viewer-webui/server/src/fastify-v2/plugins/app/sample.ts (1)
  • FastifyInstance (31-33)
🪛 GitHub Actions: clp-lint
components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts

[error] 1-33: ESLint errors: imports must be broken into multiple lines (line 13), expected line breaks after opening and before closing braces (line 13), expected 2 empty lines after import statement (line 20), missing semicolon (line 33); also warnings for import sorting.

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/typings.ts

[error] 1-45: ESLint errors: expected 2 empty lines after import (line 14), expected semicolons (lines 32, 42); warnings for import and export sorting.

🔇 Additional comments (4)
components/log-viewer-webui/server/src/fastify-v2/app.ts (1)

10-10:

Details

✅ Verification successful

Import StatusCodes for standard HTTP status codes
The new import correctly replaces the hard-coded constant with a centralised source. Ensure that http-status-codes is declared in your package.json dependencies.


🏁 Script executed:

#!/bin/bash
# Verify that http-status-codes is listed in package.json dependencies
grep -R '"http-status-codes"' -n package.json

Length of output: 93


🏁 Script executed:

#!/bin/bash
# Locate all package.json files in the repo
find . -type f -name "package.json"

# Search for http-status-codes in all files
grep -R '"http-status-codes"' -n .

Length of output: 921


Import StatusCodes for standard HTTP status codes
The new import replaces the hard-coded constant with a centralised source. Verified that http-status-codes is declared in components/log-viewer-webui/server/package.json.

# Confirm dependency in server package.json
grep -R '"http-status-codes"' -n components/log-viewer-webui/server/package.json
# -> 38:    "http-status-codes": "^2.3.0",
components/log-viewer-webui/common/searchResultsMetadata.ts (1)

24-24: Good type simplification!

Replacing Nullable<string> with the explicit union type string | null improves code clarity and reduces dependency on custom type aliases.

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (2)

35-37: Good defensive programming!

Checking for undefined MongoDB database before proceeding prevents runtime errors.


103-114: Excellent async pattern for response optimization!

Using setImmediate to defer the signal update ensures the client receives a quick response while background processing continues. The error handling is also properly implemented.

Comment on lines +75 to +77
if ("undefined" !== typeof err.statusCode &&
StatusCodes.INTERNAL_SERVER_ERROR as number > err.statusCode
) {

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.

🧹 Nitpick (assertive)

Refactor conditional for readability and remove redundant cast
The current check:

if ("undefined" !== typeof err.statusCode &&
    StatusCodes.INTERNAL_SERVER_ERROR as number > err.statusCode
) {  }

can be clearer and drop the unnecessary as number cast. Consider rewriting it as:

-if ( "undefined" !== typeof err.statusCode &&
-     StatusCodes.INTERNAL_SERVER_ERROR as number > err.statusCode
-) {
+if ( typeof err.statusCode !== "undefined" &&
+     err.statusCode < StatusCodes.INTERNAL_SERVER_ERROR
+) {
🤖 Prompt for AI Agents
In components/log-viewer-webui/server/src/fastify-v2/app.ts around lines 75 to
77, refactor the conditional that checks err.statusCode for better readability
by reversing the typeof check to 'typeof err.statusCode !== "undefined"' and
remove the redundant 'as number' cast on StatusCodes.INTERNAL_SERVER_ERROR.
Rewrite the condition to a clearer form without the type assertion.

@davemarco

Copy link
Copy Markdown
Contributor Author

rerequesting @junhaoliao now that i merged main

@junhaoliao junhaoliao left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

looks mostly clean to me

interface SearchResultsMetadataDocument {
_id: string;
errorMsg: Nullable<string>;
errorMsg: string | null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it is equivalent to Nullable<string>?

Suggested change
errorMsg: string | null;
errorMsg: Nullable<string>;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we dont have nullable type in global common directory yet. I want to change the common directory a bit, but it will require changes to the client outside of this PR. so thats why for now i just did | null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how about

Suggested change
errorMsg: string | null;
// eslint-disable-next-line no-warning-comments
// TODO: Replace with Nullable<string> when the `@common` directory refactoring is completed.
errorMsg: string | null;

Comment on lines +30 to +32
export {
SEARCH_SIGNAL
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
export {
SEARCH_SIGNAL
};
export {SEARCH_SIGNAL};

Comment on lines +36 to +52
// eslint-disable-next-line no-warning-comments
// TODO: update eslint-config-yscope
"@stylistic/max-len": [
"warn",
{
code: 100,
comments: 100,
ignoreComments: false,
ignorePattern: "^(import\\s.+\\sfrom\\s.+|\\} from)",
ignoreRegExpLiterals: true,
ignoreStrings: false,
ignoreTemplateLiterals: false,
ignoreTrailingComments: false,
ignoreUrls: true,
tabWidth: 4,
},
],

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

i suppose this is added to ignore a super long import line? is it still needed in current code?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i needed it before, but maybe after refactoring from #912, it is actually no longer needed. I will remove


if ("undefined" !== typeof err.statusCode && INTERNAL_SERVER_ERROR_CODE > err.statusCode) {
if ("undefined" !== typeof err.statusCode &&
StatusCodes.INTERNAL_SERVER_ERROR as number > err.statusCode

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

would it be better to write

Suggested change
StatusCodes.INTERNAL_SERVER_ERROR as number > err.statusCode
Number(StatusCodes.INTERNAL_SERVER_ERROR) > err.statusCode

searchJobId: searchJobId,
logger: request.log,
mongoDb: mongoDb,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

seems this suggestion has not been applied



/* Schema for request to create a new query job */
const CreateQueryJobSchema = Type.Object({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how about QueryJobCreationSchema?

} from "./common.js";


/* Schema for request to create a new query job */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

let's write this as JSDoc

timestampEnd: Type.Integer(),
});

/* Schema to identify query job */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

let's write this as JSDoc

});

/* Schema to identify query job */
const QueryJobSchema = Type.Object({

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how about QueryJobIdSchema

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Since there are 2 ids, i think QueryJobId is a bit confusing, and prefer to leave it. lmk

interface SearchResultsMetadataDocument {
_id: string;
errorMsg: Nullable<string>;
errorMsg: string | null;

@hoophalab hoophalab May 26, 2025

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.

Is there any specific reason for changing Nullable to | null?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

see other comment

Comment on lines +89 to +94
} catch (err: unknown) {
const errMsg = "Unable to submit search/aggregation job to the SQL database";
request.log.error(err, errMsg);

return reply.internalServerError(errMsg);
}

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.

Since fastify automatically prints informative debugging information and replies with a 500 error when an error is uncaught, I personally feel we could just don't catch error at all in routes,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I dont disagree with this. But now at least we get to send a custom error to the client. So in that sense it is a little better to catch the error. Especially if there is more than one possible error per request

@davemarco davemarco left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

addressed comments

interface SearchResultsMetadataDocument {
_id: string;
errorMsg: Nullable<string>;
errorMsg: string | null;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we dont have nullable type in global common directory yet. I want to change the common directory a bit, but it will require changes to the client outside of this PR. so thats why for now i just did | null

Comment on lines +36 to +52
// eslint-disable-next-line no-warning-comments
// TODO: update eslint-config-yscope
"@stylistic/max-len": [
"warn",
{
code: 100,
comments: 100,
ignoreComments: false,
ignorePattern: "^(import\\s.+\\sfrom\\s.+|\\} from)",
ignoreRegExpLiterals: true,
ignoreStrings: false,
ignoreTemplateLiterals: false,
ignoreTrailingComments: false,
ignoreUrls: true,
tabWidth: 4,
},
],

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i needed it before, but maybe after refactoring from #912, it is actually no longer needed. I will remove

interface SearchResultsMetadataDocument {
_id: string;
errorMsg: Nullable<string>;
errorMsg: string | null;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

see other comment

Comment on lines +89 to +94
} catch (err: unknown) {
const errMsg = "Unable to submit search/aggregation job to the SQL database";
request.log.error(err, errMsg);

return reply.internalServerError(errMsg);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I dont disagree with this. But now at least we get to send a custom error to the client. So in that sense it is a little better to catch the error. Especially if there is more than one possible error per request

Comment on lines +154 to +155
await mongoDb.collection(searchJobId.toString()).drop();
await mongoDb.collection(aggregationJobId.toString()).drop();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Anyways it should not be possible for the collection not to exist. So maybe its fine anyways

});

/* Schema to identify query job */
const QueryJobSchema = Type.Object({

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Since there are 2 ids, i think QueryJobId is a bit confusing, and prefer to leave it. lmk

@davemarco davemarco requested review from hoophalab and junhaoliao May 26, 2025 21:35

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

♻️ Duplicate comments (9)
components/log-viewer-webui/common/searchResultsMetadata.ts (2)

24-24: Consider using the Nullable type alias for consistency.

Previous reviewers have suggested using Nullable<string> instead of the explicit union type for consistency with the codebase conventions.


30-30: Use single-line export format.

Previous reviewers have suggested using a single-line export format for consistency.

components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts (1)

23-26: Consider renaming to QueryJobIdSchema for clarity.

Previous reviewers suggested renaming this schema to QueryJobIdSchema since it specifically contains job IDs rather than full job information.

components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (6)

1-22: Fix import formatting and ordering issues.

The imports have multiple linting issues that need to be addressed:

  • Import sorting is incorrect
  • Line 17 needs multi-line formatting for consistency
  • Missing empty line after imports

Apply this diff to fix the issues:

-import {
-    SEARCH_SIGNAL,
-    SearchResultsMetadataDocument,
-} from "@common/searchResultsMetadata.js";
-import {
-    FastifyPluginAsyncTypebox,
-    Type,
-} from "@fastify/type-provider-typebox";
+import {FastifyPluginAsyncTypebox, Type} from "@fastify/type-provider-typebox";
 import {StatusCodes} from "http-status-codes";

-import settings from "../../../../../settings.json" with {type: "json"};
+import {
+    SEARCH_SIGNAL,
+    SearchResultsMetadataDocument,
+} from "@common/searchResultsMetadata.js";
 import {ErrorSchema} from "../../../schemas/error.js";
 import {
     QueryJobCreationSchema,
     QueryJobSchema,
 } from "../../../schemas/search.js";
-import {SEARCH_MAX_NUM_RESULTS} from "./typings.js";
+import {
+    SEARCH_MAX_NUM_RESULTS,
+    SearchResultsMetadataDocument,
+} from "./typings.js";
 import {
     createMongoIndexes,
     updateSearchResultsMeta,
     updateSearchSignalWhenJobsFinish,
 } from "./utils.js";

+
+import settings from "../../../../../settings.json" with {type: "json"};

36-36: Add missing semicolon.

-    const mongoDb = mongo.db
+    const mongoDb = mongo.db;

96-97: Add error handling for MongoDB collection creation.

While MongoDB's createCollection is idempotent (won't error if collection exists), it's good practice to handle potential errors explicitly for robustness.

-            await mongoDb.createCollection(searchJobId.toString());
-            await mongoDb.createCollection(aggregationJobId.toString());
+            try {
+                await mongoDb.createCollection(searchJobId.toString());
+                await mongoDb.createCollection(aggregationJobId.toString());
+            } catch (err: unknown) {
+                // Collection might already exist, which is fine
+                request.log.debug(err, "Collection creation failed (might already exist)");
+            }

123-124: Remove trailing comma.

                 searchJobId: searchJobId,
                 logger: request.log,
                 mongoDb: mongoDb,
-
             });

154-155: Add error handling for collection drop operations.

The drop operations should handle cases where collections might not exist (e.g., if /results is called multiple times with the same job IDs).

-            await mongoDb.collection(searchJobId.toString()).drop();
-            await mongoDb.collection(aggregationJobId.toString()).drop();
+            try {
+                await mongoDb.collection(searchJobId.toString()).drop();
+                await mongoDb.collection(aggregationJobId.toString()).drop();
+            } catch (err: any) {
+                // Only log/handle if it's not a "collection doesn't exist" error
+                if (err.code !== 26) { // 26 is MongoDB's "NamespaceNotFound" error code
+                    request.log.error(err, "Unexpected error dropping collections");
+                    return reply.internalServerError("Failed to drop collections");
+                }
+                // Otherwise, silently ignore - collections were already deleted
+            }

207-208: Use template literal instead of string concatenation.

For consistency and better readability, use a single template literal.

-                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, ` +
-                `aggregationJobId=${aggregationJobId}`);
+                return reply.internalServerError(`${errMsg} for searchJobId=${searchJobId}, aggregationJobId=${aggregationJobId}`);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2dfcad4 and da17876.

📒 Files selected for processing (5)
  • components/log-viewer-webui/common/searchResultsMetadata.ts (1 hunks)
  • components/log-viewer-webui/server/eslint.config.mjs (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/app.ts (2 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts (1 hunks)
  • components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}`: - Prefer `false == ` rather than `!`.

**/*.{cpp,hpp,java,js,jsx,tpp,ts,tsx}: - Prefer false == <expression> rather than !<expression>.

  • components/log-viewer-webui/common/searchResultsMetadata.ts
  • components/log-viewer-webui/server/src/fastify-v2/app.ts
  • components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts
  • components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts
🧬 Code Graph Analysis (1)
components/log-viewer-webui/server/src/fastify-v2/schemas/search.ts (1)
components/log-viewer-webui/server/src/fastify-v2/schemas/common.ts (2)
  • StringSchema (11-11)
  • IdSchema (11-11)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: lint-check (ubuntu-latest)
🔇 Additional comments (2)
components/log-viewer-webui/server/src/fastify-v2/app.ts (1)

10-10: LGTM! Good use of standard HTTP status codes.

Using StatusCodes from the http-status-codes package instead of magic numbers improves code maintainability and readability.

components/log-viewer-webui/server/eslint.config.mjs (1)

24-34: LGTM!

The addition of Type.Null to the capIsNewExceptions array is necessary to support the TypeBox null type schema used in the new search API routes (e.g., for 204 No Content responses).

Comment on lines +75 to +77
if ("undefined" !== typeof err.statusCode &&
Number(StatusCodes.INTERNAL_SERVER_ERROR) > err.statusCode
) {

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.

💡 Verification agent

🧩 Analysis chain

Improve readability of the typeof check and verify Number() wrapper necessity.

While the logic is correct, the typeof check could be more readable, and the Number() wrapper might be redundant since StatusCodes.INTERNAL_SERVER_ERROR should already be a number.

Consider this more readable approach:

-        if ("undefined" !== typeof err.statusCode &&
-            Number(StatusCodes.INTERNAL_SERVER_ERROR) > err.statusCode
+        if (typeof err.statusCode !== "undefined" &&
+            err.statusCode < StatusCodes.INTERNAL_SERVER_ERROR

Let me verify if the Number() wrapper is actually necessary:


🏁 Script executed:

#!/bin/bash
# Description: Check the type of StatusCodes.INTERNAL_SERVER_ERROR to determine if Number() wrapper is needed

# Search for StatusCodes usage and type definitions
rg -A 3 -B 3 "StatusCodes\.INTERNAL_SERVER_ERROR"

# Look for the http-status-codes package type definitions
fd "http-status-codes" --type f

Length of output: 3094


Refactor error status code comparison

The typeof check can be made more idiomatic and the Number() wrapper around StatusCodes.INTERNAL_SERVER_ERROR is unnecessary (it’s already a number). Please update the check in components/log-viewer-webui/server/src/fastify-v2/app.ts (lines 75–77) accordingly:

-        if ("undefined" !== typeof err.statusCode &&
-            Number(StatusCodes.INTERNAL_SERVER_ERROR) > err.statusCode
+        if (typeof err.statusCode !== "undefined" &&
+            err.statusCode < StatusCodes.INTERNAL_SERVER_ERROR

This change improves readability and removes the redundant conversion.

📝 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
if ("undefined" !== typeof err.statusCode &&
Number(StatusCodes.INTERNAL_SERVER_ERROR) > err.statusCode
) {
if (typeof err.statusCode !== "undefined" &&
err.statusCode < StatusCodes.INTERNAL_SERVER_ERROR
) {
🤖 Prompt for AI Agents
In components/log-viewer-webui/server/src/fastify-v2/app.ts around lines 75 to
77, refactor the typeof check on err.statusCode to a more idiomatic form by
comparing it directly to the string "undefined" using strict equality, and
remove the Number() wrapper around StatusCodes.INTERNAL_SERVER_ERROR since it is
already a number. This will improve readability and eliminate unnecessary type
conversion.

Comment on lines +38 to +40
if ("undefined" === typeof mongoDb) {
throw new Error("MongoDB database not found");
}

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.

🧹 Nitpick (assertive)

Use direct undefined comparison.

Prefer direct comparison over string comparison for better readability and consistency with the coding guidelines.

-    if ("undefined" === typeof mongoDb) {
+    if (undefined === mongoDb) {
         throw new Error("MongoDB database not found");
     }
📝 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
if ("undefined" === typeof mongoDb) {
throw new Error("MongoDB database not found");
}
if (undefined === mongoDb) {
throw new Error("MongoDB database not found");
}
🤖 Prompt for AI Agents
In components/log-viewer-webui/server/src/fastify-v2/routes/api/search/index.ts
at lines 38 to 40, replace the string comparison "undefined" === typeof mongoDb
with a direct undefined comparison by checking if mongoDb === undefined. This
improves readability and aligns with coding guidelines.


export type {SearchResultsMetadataDocument};
export {SEARCH_SIGNAL};
export { SEARCH_SIGNAL };

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
export { SEARCH_SIGNAL };
export {SEARCH_SIGNAL};

interface SearchResultsMetadataDocument {
_id: string;
errorMsg: Nullable<string>;
errorMsg: string | null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

how about

Suggested change
errorMsg: string | null;
// eslint-disable-next-line no-warning-comments
// TODO: Replace with Nullable<string> when the `@common` directory refactoring is completed.
errorMsg: string | null;

searchJobId: searchJobId,
logger: request.log,
mongoDb: mongoDb,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

seems this suggestion has not been applied

@junhaoliao

Copy link
Copy Markdown
Member

For the PR title, how about:

feat(new-webui): Port search APIs from Meteor methods to Fastify routes.

@davemarco davemarco changed the title feat(new-webui): Port Meteor methods to Fastify routes for search api. feat(new-webui): Port search APIs from Meteor methods to Fastify routes. May 26, 2025
@davemarco davemarco requested a review from junhaoliao May 26, 2025 23:04
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