Skip to content

Commit

Permalink
Fix #1 by adding bulk API supports
Browse files Browse the repository at this point in the history
  • Loading branch information
seratch committed Mar 21, 2024
1 parent c297347 commit 5ae1c73
Show file tree
Hide file tree
Showing 5 changed files with 195 additions and 2 deletions.
50 changes: 49 additions & 1 deletion data_mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ import {
Operator,
SimpleExpression,
} from "./mod.ts";
import { CountResponse } from "./types.ts";
import {
AndConditions,
BulkDeleteResponse,
BulkGetResponse,
CountResponse,
DataMapperExpressionCountArgs,
DataMapperExpressionQueryArgs,
DataMapperFindFirstExpressionQueryArgs,
DataMapperIdQueryArgs,
DataMapperIdsQueryArgs,
DataMapperInitArgs,
DataMapperSaveArgs,
Definition,
Expand Down Expand Up @@ -92,6 +95,29 @@ export class DataMapper<Def extends Definition> {
});
}

async findAllByIds(
args: DataMapperIdsQueryArgs | string[],
): Promise<BulkGetResponse<Def>> {
let datastore = this.#defaultDatastore;
let ids: string[] | undefined = undefined;
if (Array.isArray(args)) {
ids = args;
} else {
ids = args.ids;
datastore = args.datastore ?? this.#defaultDatastore;
}
if (!datastore) {
throw new ConfigurationError(this.#datastoreMissingError);
}
const [client, logger] = [this.#client, this.#logger];
return await func.findAllByIds<Def>({
client,
datastore,
logger,
ids,
});
}

async findFirstBy(
args:
| DataMapperFindFirstExpressionQueryArgs<Def>
Expand Down Expand Up @@ -270,6 +296,28 @@ export class DataMapper<Def extends Definition> {
});
}

async deleteAllByIds(
args: DataMapperIdsQueryArgs | string[],
): Promise<BulkDeleteResponse> {
let datastore = this.#defaultDatastore;
let ids: string[] | undefined = undefined;
if (Array.isArray(args)) {
ids = args;
} else {
ids = args.ids;
datastore = args.datastore ?? this.#defaultDatastore;
}
if (!datastore) {
throw new ConfigurationError(this.#datastoreMissingError);
}
return await func.deleteAllByIds({
client: this.#client,
datastore,
ids,
logger: this.#logger,
});
}

#datastoreMissingError = "`datastore` needs to be passed";
}

Expand Down
57 changes: 57 additions & 0 deletions functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import {
} from "./dependencies/deno_slack_api_typed_method_types.ts";
import { DatastoreError } from "./errors.ts";
import {
BulkDeleteResponse,
BulkGetResponse,
CountResponse,
Definition,
DeleteResponse,
FindFirstRawExpressionQueryArgs,
GetResponse,
IdQueryArgs,
IdsQueryArgs,
PutResponse,
QueryResponse,
RawExpressionQueryArgs,
Expand Down Expand Up @@ -83,6 +86,33 @@ export async function findById<Def extends Definition>({
return result as GetResponse<Def>;
}

export async function findAllByIds<Def extends Definition>({
client,
datastore,
ids,
logger,
}: IdsQueryArgs): Promise<BulkGetResponse<Def>> {
const _logger = logger ?? defaultLogger;
if (_logger.level === log.LogLevels.DEBUG) {
_logger.debug(
`${logName} Finding records (datastore: ${datastore}, IDs: ${ids})`,
);
}
const result = await client.apps.datastore.bulkGet({ datastore, ids });
if (_logger.level === log.LogLevels.DEBUG) {
const response = JSON.stringify(result);
_logger.debug(
`${logName} Found: (datastore: ${datastore}, response: ${response})`,
);
}
if (result.error) {
const error =
`Failed to fetch rows (datastore: ${datastore}, error ${result.error})`;
throw new DatastoreError(error, result);
}
return result as BulkGetResponse<Def>;
}

export async function findFirstBy<Def extends Definition>({
client,
datastore,
Expand Down Expand Up @@ -281,3 +311,30 @@ export async function deleteById({
}
return result;
}

export async function deleteAllByIds({
client,
datastore,
ids,
logger,
}: IdsQueryArgs): Promise<BulkDeleteResponse> {
const _logger = logger ?? defaultLogger;
if (_logger.level === log.LogLevels.DEBUG) {
_logger.debug(
`${logName} Deleting records (datastore: ${datastore}, IDs: ${ids})`,
);
}
const result = await client.apps.datastore.bulkDelete({ datastore, ids });
if (_logger.level === log.LogLevels.DEBUG) {
const jsonData = JSON.stringify(result);
_logger.debug(
`${logName} Deletion result: (datastore: ${datastore}, response: ${jsonData})`,
);
}
if (result.error) {
const error =
`${logName} Failed to delete rows: (datastore: ${datastore}, error: ${result.error})`;
throw new DatastoreError(error, result);
}
return result;
}
60 changes: 59 additions & 1 deletion functions_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { assertExists } from "./dependencies/testing_asserts.ts";
import { SlackAPI } from "./dependencies/deno_slack_api.ts";
import { save } from "./mod.ts";
import { DefineDatastore, Schema } from "./dependencies/deno_slack_sdk.ts";
import { findAllBy } from "./functions.ts";
import { countBy, findAllBy } from "./functions.ts";
import { findAllByIds } from "./functions.ts";

mf.install();

Expand Down Expand Up @@ -45,6 +46,39 @@ mf.mock("POST@/api/apps.datastore.query", () => {
},
);
});
mf.mock("POST@/api/apps.datastore.bulkGet", () => {
return new Response(
JSON.stringify({
"ok": true,
"datastore": "suveys",
"items": [
{
"id": "123",
"title": "Off-site event ideas",
"questions": [
"Can you share a fun idea for our off-site event in December?",
],
"closed": false,
},
],
}),
{
status: 200,
},
);
});
mf.mock("POST@/api/apps.datastore.count", () => {
return new Response(
JSON.stringify({
"ok": true,
"datastore": "suveys",
"count": 123,
}),
{
status: 200,
},
);
});

export const Surveys = DefineDatastore(
{
Expand Down Expand Up @@ -106,3 +140,27 @@ Deno.test("Run a query", async () => {
});
assertExists(result.items);
});

Deno.test("Run a bulk get request", async () => {
const client = SlackAPI("valid-token");
const result = await findAllByIds<typeof Surveys.definition>({
client,
datastore: "suveys",
ids: ["1", "2", "3"],
});
assertExists(result.items);
});

Deno.test("Run a count query", async () => {
const client = SlackAPI("valid-token");
const result = await countBy<typeof Surveys.definition>({
client,
datastore: "suveys",
expression: {
expression: "#id = :id",
attributes: { "#id": "id" },
values: { ":id": "123" },
},
});
assertExists(result.count);
});
10 changes: 10 additions & 0 deletions test-app/functions/survey_demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ export default SlackFunction(def, async ({ client }) => {
});
console.log(countResult);

const findByIdsResult = await mapper.findAllByIds({
ids: ["1", "2", "3"],
});
console.log(findByIdsResult);

const deletion1 = await mapper.deleteById({ id: "1" });
console.log(`deletion 1: ${JSON.stringify(deletion1, null, 2)}`);
if (deletion1.error) {
Expand All @@ -208,6 +213,11 @@ export default SlackFunction(def, async ({ client }) => {
return { error: `Failed to delete a record - ${deletion2.error}` };
}

const deleteAllByIdsResult = await mapper.deleteAllByIds({
ids: ["1", "2", "3"],
});
console.log(deleteAllByIdsResult);

const alreadyInserted = (await mapper.findById({ id: "100" })).item;
if (!alreadyInserted) {
for (let i = 0; i < 100; i += 1) {
Expand Down
20 changes: 20 additions & 0 deletions types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as log from "./dependencies/logger.ts";
import {
DatastoreBulkDeleteResponse,
DatastoreBulkGetResponse,
DatastoreDeleteResponse,
DatastoreGetResponse,
DatastorePutResponse,
Expand Down Expand Up @@ -172,6 +174,13 @@ export interface IdQueryArgs {
logger?: log.Logger;
}

export interface IdsQueryArgs {
client: SlackAPIClient;
datastore: string;
ids: string[];
logger?: log.Logger;
}

export type RawExpressionCountArgs = {
client: SlackAPIClient;
datastore: string;
Expand Down Expand Up @@ -201,6 +210,10 @@ export type GetResponse<Def extends Definition> =
& Omit<DatastoreGetResponse<DatastoreSchema>, "item">
& { item: SavedAttributes<Def> };

export type BulkGetResponse<Def extends Definition> =
& Omit<DatastoreBulkGetResponse<DatastoreSchema>, "items">
& { items: SavedAttributes<Def> };

export type QueryResponse<Def extends Definition> =
& Omit<DatastoreQueryResponse<DatastoreSchema>, "items">
& { items: SavedAttributes<Def>[] };
Expand All @@ -209,6 +222,8 @@ export type CountResponse = DatastoreCountResponse<DatastoreSchema>;

export type DeleteResponse = DatastoreDeleteResponse<DatastoreSchema>;

export type BulkDeleteResponse = DatastoreBulkDeleteResponse<DatastoreSchema>;

// -----------------------
// DataMapper's types
// -----------------------
Expand All @@ -230,6 +245,11 @@ export interface DataMapperIdQueryArgs {
datastore?: string;
}

export interface DataMapperIdsQueryArgs {
ids: string[];
datastore?: string;
}

export type PaginationArgs = CursorPaginationArgs & {
autoPagination?: boolean; // default: true
};
Expand Down

0 comments on commit 5ae1c73

Please sign in to comment.