Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ImportResponse[] as type of ImportError.importResults #181

Merged
merged 2 commits into from
Aug 2, 2024

Conversation

jasongwartz
Copy link
Contributor

Change Summary

The docs indicate that the error thrown by import() (as in: client.collections(...).documents().import(...)) contains a key importResults. In my usage, I found that the runtime type of the value of importResults is an array, which seems to contain either ImportResponseSuccess or ImportResponseFail. At the moment I'm force-casting to override the type given by the library, but if my experimentation is correct, it'd be good to include the correct type here.

PR Checklist

@sgarner
Copy link

sgarner commented Jul 30, 2024

I'm experiencing the same issue.

It's clear from the usage that an array of both successful and failed responses (resultsInJSONFormat) is being given as the second argument to the ImportError constructor:

throw new ImportError(
`${resultsInJSONFormat.length - failedItems.length
} documents imported successfully, ${failedItems.length
} documents failed during import. Use \`error.importResults\` from the raised exception to get a detailed error reason for each document.`,
resultsInJSONFormat,
);

And there is already a test which demonstrates that ImportError.importResults is intended to be an array:

expect(error.constructor.name).to.eq("ImportError");
expect(error.importResults.length).to.eq(2);
expect(error.importResults[0].success).to.eq(false);
expect(error.importResults[0].message).to.eq("Error message");

The fix for the types in this PR looks good, and I wonder why it hasn't been merged yet?

@sgarner
Copy link

sgarner commented Jul 30, 2024

I would just add that this mistake could have been picked up sooner if the ImportError class had typings on its constructor arguments. Unfortunately they're implicit any:

constructor(message, importResults) {

Copy link
Contributor

@tharropoulos tharropoulos left a comment

Choose a reason for hiding this comment

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

I think a better way to approach this is, since the error is thrown, the most important information for the caller is which of the import statements failed. Currently, it will print all of the import responses. I think a better solution would be to use something like this:

import TypesenseError from "./TypesenseError";
import type { ImportResponseFail } from "../Documents";

export default class ImportError extends TypesenseError {
  importResults: ImportResponseFail[];
  constructor(message: string, importResults: ImportResponseFail[]) {
    super(message);
    this.importResults = importResults;
  }
}

And then, on the import function, handle errors like so:

    if (Array.isArray(documents)) {
      const resultsInJSONFormat = resultsInJSONLFormat
        .split("\n")
        .map((r) => JSON.parse(r)) as ImportResponse[];
      const failedItems = resultsInJSONFormat.filter(
        (r) => r.success === false,
      ) as ImportResponseFail[];
      if (failedItems.length > 0) {
        throw new ImportError(
          `${
            resultsInJSONFormat.length - failedItems.length
          } documents imported successfully, ${
            failedItems.length
          } documents failed during import. Use \`error.importResults\` from the raised exception to get a detailed error reason for each document.`,
          failedItems,
        );
      } else {...

One thing also worth noting is to later introduce zod to safely parse JSON to the desired type like documented here. This is out of the scope of this PR and something that should be introduced separately.

Copy link
Contributor

@tharropoulos tharropoulos left a comment

Choose a reason for hiding this comment

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

We should add type annotations to the constructor as well, as @sgarner mentioned, as even with this change, the Typescript compiler will still issue an error for implicit any's, if set to strict.

export default class ImportError extends TypesenseError {
  importResults: ImportResponse[];
  constructor(message: string, importResults: ImportResponse[]) {...

@sgarner
Copy link

sgarner commented Aug 1, 2024

Thank you both for following up on this 👍

I think a better way to approach this is, since the error is thrown, the most important information for the caller is which of the import statements failed. Currently, it will print all of the import responses.

If the thrown error only contains the failed responses, the calling application will have no way to inspect the successful responses. So I would favour retaining the current behaviour. (This would also be a breaking change.)

@tharropoulos
Copy link
Contributor

Thank you both for following up on this 👍

I think a better way to approach this is, since the error is thrown, the most important information for the caller is which of the import statements failed. Currently, it will print all of the import responses.

If the thrown error only contains the failed responses, the calling application will have no way to inspect the successful responses. So I would favour retaining the current behaviour. (This would also be a breaking change.)

Another way to approach this is leaving it to the caller to unwrap it themselves, although that breaks even more things in terms of backwards compatibility. So I think we should leave it as is for the time being then! As soon as @jasongwartz has the type annotations in place, I think we're done

@jasonbosco
Copy link
Member

Thank you for the PR!

@jasonbosco jasonbosco merged commit f9ad42f into typesense:master Aug 2, 2024
1 check passed
@jasonbosco
Copy link
Member

Published in 2.0.0-1

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.

4 participants