1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-30 10:36:35 +02:00

Server: Added command to test a storage connection

This commit is contained in:
Laurent Cozic 2021-11-11 14:40:23 +00:00
parent 4879edc59a
commit c6dec0a045
3 changed files with 110 additions and 56 deletions

View File

@ -1,54 +0,0 @@
import { PositionalOptions, Options } from 'yargs';
import Logger from '@joplin/lib/Logger';
import BaseCommand, { RunContext } from './BaseCommand';
import parseStorageConnectionString from '../models/items/storage/parseStorageConnectionString';
const logger = Logger.create('ImportContentCommand');
interface Argv {
toStorage: string;
batchSize?: number;
}
export default class ImportContentCommand extends BaseCommand {
public command() {
return 'import-content <to-storage>';
}
public description() {
return 'import content to storage';
}
public positionals(): Record<string, PositionalOptions> {
return {
'to-storage': {
description: 'storage connection string',
type: 'string',
},
};
}
public options(): Record<string, Options> {
return {
'batch-size': {
type: 'number',
description: 'Item batch size',
},
};
}
public async run(argv: Argv, runContext: RunContext): Promise<void> {
const toStorageConfig = parseStorageConnectionString(argv.toStorage);
const batchSize = argv.batchSize || 1000;
logger.info('Importing to storage:', toStorageConfig);
logger.info(`Batch size: ${batchSize}`);
await runContext.models.item().importContentToStorage(toStorageConfig, {
batchSize: batchSize || 1000,
logger: logger as Logger,
});
}
}

View File

@ -0,0 +1,108 @@
import { PositionalOptions, Options } from 'yargs';
import Logger from '@joplin/lib/Logger';
import BaseCommand, { RunContext } from './BaseCommand';
import parseStorageConnectionString from '../models/items/storage/parseStorageConnectionString';
import loadStorageDriver from '../models/items/storage/loadStorageDriver';
import uuidgen from '../utils/uuidgen';
import { Context } from '../models/items/storage/StorageDriverBase';
const logger = Logger.create('ImportContentCommand');
enum ArgvCommand {
Import = 'import',
CheckConnection = 'check-connection',
}
interface Argv {
command: ArgvCommand;
connection: string;
batchSize?: number;
}
export default class StorageCommand extends BaseCommand {
public command() {
return 'storage <command>';
}
public description() {
return 'import content to storage';
}
public positionals(): Record<string, PositionalOptions> {
return {
'command': {
description: 'command to execute',
choices: [
ArgvCommand.Import,
ArgvCommand.CheckConnection,
],
},
};
}
public options(): Record<string, Options> {
return {
'batch-size': {
type: 'number',
description: 'Item batch size',
},
'connection': {
description: 'storage connection string',
type: 'string',
},
};
}
public async run(argv: Argv, runContext: RunContext): Promise<void> {
const commands: Record<ArgvCommand, Function> = {
[ArgvCommand.Import]: async () => {
if (!argv.connection) throw new Error('--connection option is required');
const toStorageConfig = parseStorageConnectionString(argv.connection);
const batchSize = argv.batchSize || 1000;
logger.info('Importing to storage:', toStorageConfig);
logger.info(`Batch size: ${batchSize}`);
await runContext.models.item().importContentToStorage(toStorageConfig, {
batchSize: batchSize || 1000,
logger: logger as Logger,
});
},
[ArgvCommand.CheckConnection]: async () => {
const storageConfig = parseStorageConnectionString(argv.connection);
const driver = await loadStorageDriver(storageConfig, runContext.db, { assignDriverId: false });
const itemId = `testingconnection${uuidgen(8)}`;
const itemContent = Buffer.from(uuidgen(8));
const context: Context = { models: runContext.models };
try {
await driver.write(itemId, itemContent, context);
} catch (error) {
error.message = `Could not write content to storage: ${error.message}`;
throw error;
}
if (!(await driver.exists(itemId, context))) {
throw new Error(`Written item does not exist: ${itemId}`);
}
const readContent = await driver.read(itemId, context);
if (readContent.toString() !== itemContent.toString()) throw new Error(`Could not read back written item. Expected: ${itemContent.toString()}. Got: ${readContent.toString()}`);
await driver.delete(itemId, context);
if (await driver.exists(itemId, context)) {
throw new Error(`Deleted item still exist: ${itemId}`);
}
logger.info('Item was written, read back and deleted without any error.');
},
};
await commands[argv.command]();
}
}

View File

@ -2,7 +2,7 @@ import yargs = require('yargs');
import BaseCommand from '../commands/BaseCommand';
import DbCommand from '../commands/DbCommand';
import DeleteOldChangesCommand from '../commands/DeleteOldChangesCommand';
import ImportContentCommand from '../commands/ImportContentCommand';
import StorageCommand from '../commands/StorageCommand';
import MigrateCommand from '../commands/MigrateCommand';
export interface Commands {
@ -17,7 +17,7 @@ export default async function setupCommands(): Promise<Commands> {
new MigrateCommand(),
new DbCommand(),
new DeleteOldChangesCommand(),
new ImportContentCommand(),
new StorageCommand(),
];
for (const cmd of commands) {