change: Refactor AllVoidCompositeHandler into SequenceHandler.

This commit is contained in:
Ruben Verborgh
2020-12-08 19:18:08 +00:00
committed by Joachim Van Herwegen
parent 7cae14acf7
commit ba47ce7951
11 changed files with 112 additions and 69 deletions

View File

@@ -181,10 +181,10 @@ export * from './util/locking/SingleThreadedResourceLocker';
export * from './util/locking/WrappedExpiringResourceLocker';
// Util
export * from './util/AllVoidCompositeHandler';
export * from './util/AsyncHandler';
export * from './util/FirstCompositeHandler';
export * from './util/HeaderUtil';
export * from './util/PathUtil';
export * from './util/QuadUtil';
export * from './util/SequenceHandler';
export * from './util/StreamUtil';

View File

@@ -1,24 +0,0 @@
import { AsyncHandler } from './AsyncHandler';
/**
* A composite handler that runs all of its handlers independent of their result.
* The `canHandle` check of this handler will always succeed.
*/
export class AllVoidCompositeHandler<TIn> extends AsyncHandler<TIn> {
private readonly handlers: AsyncHandler<TIn>[];
public constructor(handlers: AsyncHandler<TIn>[]) {
super();
this.handlers = handlers;
}
public async handle(input: TIn): Promise<void> {
for (const handler of this.handlers) {
try {
await handler.handleSafe(input);
} catch {
// Ignore errors
}
}
}
}

View File

@@ -1,7 +1,7 @@
/**
* Simple interface for classes that can potentially handle a specific kind of data asynchronously.
*/
export abstract class AsyncHandler<TInput = void, TOutput = void> {
export abstract class AsyncHandler<TIn = void, TOut = void> {
/**
* Checks if the input data can be handled by this class.
* Throws an error if it can't handle the data.
@@ -10,7 +10,7 @@ export abstract class AsyncHandler<TInput = void, TOutput = void> {
* @returns A promise resolving if this input can be handled, rejecting with an Error if not.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async canHandle(input: TInput): Promise<void> {
public async canHandle(input: TIn): Promise<void> {
// Support any input by default
}
@@ -20,7 +20,7 @@ export abstract class AsyncHandler<TInput = void, TOutput = void> {
*
* @returns A promise resolving when the handling is finished. Return value depends on the given type.
*/
public abstract handle(input: TInput): Promise<TOutput>;
public abstract handle(input: TIn): Promise<TOut>;
/**
* Helper function that first runs the canHandle function followed by the handle function.
@@ -30,7 +30,7 @@ export abstract class AsyncHandler<TInput = void, TOutput = void> {
*
* @returns The result of the handle function of the handler.
*/
public async handleSafe(data: TInput): Promise<TOutput> {
public async handleSafe(data: TIn): Promise<TOut> {
await this.canHandle(data);
return this.handle(data);

View File

@@ -0,0 +1,32 @@
import { AsyncHandler } from './AsyncHandler';
/**
* A composite handler that will try to run all supporting handlers sequentially
* and return the value of the last supported handler.
* The `canHandle` check of this handler will always succeed.
*/
export class SequenceHandler<TIn = void, TOut = void> extends AsyncHandler<TIn, TOut | undefined> {
private readonly handlers: AsyncHandler<TIn, TOut>[];
public constructor(handlers: AsyncHandler<TIn, TOut>[]) {
super();
this.handlers = [ ...handlers ];
}
public async handle(input: TIn): Promise<TOut | undefined> {
let result: TOut | undefined;
for (const handler of this.handlers) {
let supported: boolean;
try {
await handler.canHandle(input);
supported = true;
} catch {
supported = false;
}
if (supported) {
result = await handler.handle(input);
}
}
return result;
}
}