From 64e9e26230d9c1bf51bbc059f2d0b52f3b86c4f6 Mon Sep 17 00:00:00 2001 From: ogzhanolguncu Date: Thu, 11 Jan 2024 13:39:43 +0300 Subject: [PATCH] Add range command --- src/commands/client/delete/index.test.ts | 27 +++++++++++------------- src/commands/client/fetch/index.ts | 7 +----- src/commands/client/range/index.test.ts | 26 +++++++++++++++++++++++ src/commands/client/range/index.ts | 20 ++++++++++++++++++ src/commands/client/types.ts | 5 +++++ src/commands/index.ts | 2 +- src/http/index.ts | 9 +------- src/vector.ts | 2 ++ 8 files changed, 68 insertions(+), 30 deletions(-) create mode 100644 src/commands/client/range/index.test.ts create mode 100644 src/commands/client/range/index.ts create mode 100644 src/commands/client/types.ts diff --git a/src/commands/client/delete/index.test.ts b/src/commands/client/delete/index.test.ts index ec30e29..8d3be84 100644 --- a/src/commands/client/delete/index.test.ts +++ b/src/commands/client/delete/index.test.ts @@ -21,20 +21,17 @@ describe("DELETE", () => { expect(deletionResult).toBeTruthy(); }); - test("deleting the same ids should throw", () => { - const throwable = async () => { - const initialVector = [6.6, 7.7]; - const idsToUpsert = [randomID(), randomID(), randomID()]; - - const upsertPromises = idsToUpsert.map((id) => - new UpsertCommand({ id, vector: initialVector }).exec(client) - ); - await Promise.all(upsertPromises); - - await new DeleteCommand({ ids: idsToUpsert }).exec(client); - //This should throw - await new DeleteCommand({ ids: idsToUpsert }).exec(client); - }; - expect(throwable).toThrow(); + test("deleting the same ids should throw", async () => { + const initialVector = [6.6, 7.7]; + const idsToUpsert = [randomID(), randomID(), randomID()]; + + const upsertPromises = idsToUpsert.map((id) => + new UpsertCommand({ id, vector: initialVector }).exec(client) + ); + await Promise.all(upsertPromises); + + await new DeleteCommand({ ids: idsToUpsert }).exec(client); + const res1 = await new DeleteCommand({ ids: idsToUpsert }).exec(client); + expect(res1).toBeNull(); }); }); diff --git a/src/commands/client/fetch/index.ts b/src/commands/client/fetch/index.ts index 712fec9..9be33a8 100644 --- a/src/commands/client/fetch/index.ts +++ b/src/commands/client/fetch/index.ts @@ -1,4 +1,5 @@ import { Command } from "../../index"; +import { Vector } from "../types"; type Payload = { ids: number[] | string[]; @@ -6,12 +7,6 @@ type Payload = { includeVectors?: boolean; }; -type Vector = { - id: string; - vector: number[]; - metadata?: TMetadata; -}; - type FetchReturnResponse = Vector | null; export class FetchCommand extends Command[]> { diff --git a/src/commands/client/range/index.test.ts b/src/commands/client/range/index.test.ts new file mode 100644 index 0000000..6acb31b --- /dev/null +++ b/src/commands/client/range/index.test.ts @@ -0,0 +1,26 @@ +import { afterAll, describe, expect, test } from "bun:test"; +import { RangeCommand } from "."; +import { newHttpClient, randomFloat, randomID, resetIndexes } from "../../../utils/test-utils"; +import { UpsertCommand } from "../upsert"; + +const client = newHttpClient(); + +describe("RANGE", () => { + afterAll(async () => await resetIndexes()); + + test("should query records successfully", async () => { + const randomizedData = new Array(20) + .fill("") + .map(() => ({ id: randomID(), vector: [randomFloat(), randomFloat()] })); + + const payloads = randomizedData.map((data) => new UpsertCommand(data).exec(client)); + await Promise.all(payloads); + + const res = await new RangeCommand({ + cursor: 0, + limit: 5, + includeVectors: true, + }).exec(client); + expect(res.nextCursor).toBe("5"); + }); +}); diff --git a/src/commands/client/range/index.ts b/src/commands/client/range/index.ts new file mode 100644 index 0000000..926ccd3 --- /dev/null +++ b/src/commands/client/range/index.ts @@ -0,0 +1,20 @@ +import { Command } from "../../index"; +import { Vector } from "../types"; + +type Payload = { + cursor: number; + limit: number; + includeVectors?: boolean; + includeMetadata?: boolean; +}; + +type RangeReturnResponse = { + nextCursor: string; + vectors: Vector[]; +}; + +export class RangeCommand extends Command> { + constructor(payload: Payload) { + super(payload, "range"); + } +} diff --git a/src/commands/client/types.ts b/src/commands/client/types.ts new file mode 100644 index 0000000..6613d63 --- /dev/null +++ b/src/commands/client/types.ts @@ -0,0 +1,5 @@ +export type Vector = { + id: string; + vector: number[]; + metadata?: TMetadata; +}; diff --git a/src/commands/index.ts b/src/commands/index.ts index 7547439..2562f3d 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -1,7 +1,7 @@ import { UpstashError } from "../error"; import { Requester } from "../http"; -const ENDPOINTS = ["upsert", "query", "delete", "fetch", "reset"] as const; +const ENDPOINTS = ["upsert", "query", "delete", "fetch", "reset", "range"] as const; export type EndpointVariants = (typeof ENDPOINTS)[number]; /** diff --git a/src/http/index.ts b/src/http/index.ts index ee8b096..5351b0a 100644 --- a/src/http/index.ts +++ b/src/http/index.ts @@ -154,10 +154,7 @@ export class HttpClient implements Requester { return body as UpstashResponse; } - if (isArray(body)) { - return { result: body }; - } - throw new UpstashError(`${body}, command was: ${JSON.stringify(req.body)}`); + return { result: body }; } } @@ -166,7 +163,3 @@ function isResultErrorTuple( ): response is { result?: string; error?: string } { return response && typeof response === "object" && ("result" in response || "error" in response); } - -function isArray(response: RawUpstashResponse): response is T { - return Array.isArray(response); -} diff --git a/src/vector.ts b/src/vector.ts index 37b0aed..7b86a77 100644 --- a/src/vector.ts +++ b/src/vector.ts @@ -1,6 +1,7 @@ import { FetchCommand } from "./commands/client"; import { DeleteCommand } from "./commands/client/delete"; import { QueryCommand } from "./commands/client/query"; +import { RangeCommand } from "./commands/client/range"; import { ResetCommand } from "./commands/client/reset"; import { UpsertCommand } from "./commands/client/upsert"; import { Requester } from "./http"; @@ -34,4 +35,5 @@ export class Index { upsert = (args: CommandArgs) => new UpsertCommand(args).exec(this.client); fetch = (args: CommandArgs) => new FetchCommand(args).exec(this.client); reset = () => new ResetCommand().exec(this.client); + range = (args: CommandArgs) => new RangeCommand(args).exec(this.client); }