feat: Add CLI command to rebuild index

This commit is contained in:
Jesse Wierzbinski 2024-06-28 23:58:43 -10:00
parent 19c15f7e96
commit 93b8609411
No known key found for this signature in database
3 changed files with 89 additions and 6 deletions

View file

@ -184,16 +184,18 @@ export class SonicSearchManager {
* Rebuild search indexes * Rebuild search indexes
* @param indexes Indexes to rebuild * @param indexes Indexes to rebuild
* @param batchSize Size of each batch * @param batchSize Size of each batch
* @param progressCallback Callback for progress updates
*/ */
async rebuildSearchIndexes( async rebuildSearchIndexes(
indexes: SonicIndexType[], indexes: SonicIndexType[],
batchSize = 100, batchSize = 100,
progressCallback?: (progress: number) => void,
): Promise<void> { ): Promise<void> {
for (const index of indexes) { for (const index of indexes) {
if (index === SonicIndexType.Accounts) { if (index === SonicIndexType.Accounts) {
await this.rebuildAccountsIndex(batchSize); await this.rebuildAccountsIndex(batchSize, progressCallback);
} else if (index === SonicIndexType.Statuses) { } else if (index === SonicIndexType.Statuses) {
await this.rebuildStatusesIndex(batchSize); await this.rebuildStatusesIndex(batchSize, progressCallback);
} }
} }
} }
@ -201,8 +203,12 @@ export class SonicSearchManager {
/** /**
* Rebuild accounts index * Rebuild accounts index
* @param batchSize Size of each batch * @param batchSize Size of each batch
* @param progressCallback Callback for progress updates
*/ */
private async rebuildAccountsIndex(batchSize: number): Promise<void> { private async rebuildAccountsIndex(
batchSize: number,
progressCallback?: (progress: number) => void,
): Promise<void> {
const accountCount = await User.getCount(); const accountCount = await User.getCount();
const batchCount = Math.ceil(accountCount / batchSize); const batchCount = Math.ceil(accountCount / batchSize);
@ -221,15 +227,19 @@ export class SonicSearchManager {
), ),
), ),
); );
this.logger.info`Indexed accounts batch ${i + 1}/${batchCount}`; progressCallback?.((i + 1) / batchCount);
} }
} }
/** /**
* Rebuild statuses index * Rebuild statuses index
* @param batchSize Size of each batch * @param batchSize Size of each batch
* @param progressCallback Callback for progress updates
*/ */
private async rebuildStatusesIndex(batchSize: number): Promise<void> { private async rebuildStatusesIndex(
batchSize: number,
progressCallback?: (progress: number) => void,
): Promise<void> {
const statusCount = await Note.getCount(); const statusCount = await Note.getCount();
const batchCount = Math.ceil(statusCount / batchSize); const batchCount = Math.ceil(statusCount / batchSize);
@ -245,7 +255,7 @@ export class SonicSearchManager {
), ),
), ),
); );
this.logger.info`Indexed statuses batch ${i + 1}/${batchCount}`; progressCallback?.((i + 1) / batchCount);
} }
} }

View file

@ -0,0 +1,68 @@
import { Args, Flags } from "@oclif/core";
import ora from "ora";
import { SonicIndexType, searchManager } from "~/classes/search/search-manager";
import { BaseCommand } from "~/cli/base";
import { config } from "~/packages/config-manager";
export default class IndexRebuild extends BaseCommand<typeof IndexRebuild> {
static override args = {
type: Args.string({
description: "Index category to rebuild",
options: ["accounts", "statuses"],
required: true,
}),
};
static override description = "Rebuild search indexes";
static override examples = ["<%= config.bin %> <%= command.id %>"];
static override flags = {
"batch-size": Flags.integer({
char: "b",
description: "Number of items to process in each batch",
default: 100,
}),
};
public async run(): Promise<void> {
const { flags, args } = await this.parse(IndexRebuild);
if (!config.sonic.enabled) {
this.error("Sonic search is disabled");
this.exit(1);
}
await searchManager.connect();
const spinner = ora("Rebuilding search indexes").start();
switch (args.type) {
case "accounts":
await searchManager.rebuildSearchIndexes(
[SonicIndexType.Accounts],
flags["batch-size"],
(progress) => {
spinner.text = `Rebuilding search indexes (${(progress * 100).toFixed(2)}%)`;
},
);
break;
case "statuses":
await searchManager.rebuildSearchIndexes(
[SonicIndexType.Statuses],
flags["batch-size"],
(progress) => {
spinner.text = `Rebuilding search indexes (${(progress * 100).toFixed(2)}%)`;
},
);
break;
default: {
this.error("Invalid index type");
}
}
spinner.succeed("Search indexes rebuilt");
this.exit(0);
}
}

View file

@ -1,8 +1,10 @@
import { configureLoggers } from "@/loggers";
import { execute } from "@oclif/core"; import { execute } from "@oclif/core";
import EmojiAdd from "./commands/emoji/add"; import EmojiAdd from "./commands/emoji/add";
import EmojiDelete from "./commands/emoji/delete"; import EmojiDelete from "./commands/emoji/delete";
import EmojiImport from "./commands/emoji/import"; import EmojiImport from "./commands/emoji/import";
import EmojiList from "./commands/emoji/list"; import EmojiList from "./commands/emoji/list";
import IndexRebuild from "./commands/index/rebuild";
import Start from "./commands/start"; import Start from "./commands/start";
import UserCreate from "./commands/user/create"; import UserCreate from "./commands/user/create";
import UserDelete from "./commands/user/delete"; import UserDelete from "./commands/user/delete";
@ -10,6 +12,8 @@ import UserList from "./commands/user/list";
import UserRefetch from "./commands/user/refetch"; import UserRefetch from "./commands/user/refetch";
import UserReset from "./commands/user/reset"; import UserReset from "./commands/user/reset";
await configureLoggers();
// Use "explicit" oclif strategy to avoid issues with oclif's module resolver and bundling // Use "explicit" oclif strategy to avoid issues with oclif's module resolver and bundling
export const commands = { export const commands = {
"user:list": UserList, "user:list": UserList,
@ -21,6 +25,7 @@ export const commands = {
"emoji:delete": EmojiDelete, "emoji:delete": EmojiDelete,
"emoji:list": EmojiList, "emoji:list": EmojiList,
"emoji:import": EmojiImport, "emoji:import": EmojiImport,
"index:rebuild": IndexRebuild,
start: Start, start: Start,
}; };