Skip to content

Commit

Permalink
issue-56 paused methods resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
dhilt committed Mar 2, 2024
1 parent 462cee8 commit 41045ad
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 30 deletions.
47 changes: 35 additions & 12 deletions src/classes/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@ import { Logger } from './logger';
import { Buffer } from './buffer';
import { Reactive } from './reactive';
import {
AdapterPropName, AdapterPropType, EMPTY_ITEM, getDefaultAdapterProps, methodPreResult, reactiveConfigStorage
AdapterPropName,
AdapterPropType,
EMPTY_ITEM,
getDefaultAdapterProps,
methodPausedResult,
methodPreResult,
reactiveConfigStorage
} from './adapter/props';
import { wantedUtils } from './adapter/wanted';
import { Viewport } from './viewport';
Expand Down Expand Up @@ -42,9 +48,10 @@ type InitializationParams<Item> = {
}

const ADAPTER_PROPS_STUB = getDefaultAdapterProps();
const ALLOWED_METHODS_WHEN_PAUSED = ADAPTER_PROPS_STUB.filter(v => !!v.allowedWhenPaused).map(v => v.name);

const _has = (obj: unknown, prop: string): boolean =>
typeof obj === 'object' && obj !== null && Object.prototype.hasOwnProperty.call(obj, prop);
!!obj && typeof obj === 'object' && Object.prototype.hasOwnProperty.call(obj, prop);

const convertAppendArgs = <Item>(prepend: boolean, options: unknown, eof?: boolean) => {
let result = options as AdapterAppendOptions<Item> & AdapterPrependOptions<Item>;
Expand Down Expand Up @@ -113,16 +120,32 @@ export class Adapter<Item = unknown> implements IAdapter<Item> {
private relax$: Reactive<AdapterMethodResult> | null;
private relaxRun: Promise<AdapterMethodResult> | null;

private getPromisifiedMethod(method: MethodResolver, defaultMethod: MethodResolver) {
private shouldIgnorePausedMethod(method: MethodResolver) {
const methodName = method.name as AdapterPropName;
return this.paused && !ALLOWED_METHODS_WHEN_PAUSED.includes(methodName);
}

private getPausedMethodResult(method: MethodResolver) {
this.logger?.log?.(() => 'scroller is paused: ' + method.name + ' method is ignored');
return Promise.resolve(methodPausedResult);
}

private getPromisifiedMethod(method: MethodResolver, args: unknown[]) {
return new Promise<AdapterMethodResult>(resolve => {
if (this.relax$) {
this.relax$.once(value => resolve(value));
}
method.apply(this, args);
});
}

private getWorkflowRunnerMethod(method: MethodResolver, defaultMethod: MethodResolver) {
return (...args: unknown[]): Promise<AdapterMethodResult> =>
this.relax$
? new Promise(resolve => {
if (this.relax$) {
this.relax$.once(value => resolve(value));
}
method.apply(this, args);
})
: defaultMethod.apply(this, args);
!this.relax$
? defaultMethod.apply(this, args)
: this.shouldIgnorePausedMethod(method)
? this.getPausedMethodResult(method)
: this.getPromisifiedMethod(method, args);
}

constructor(context: IAdapter<Item> | null, getWorkflow: WorkflowGetter<Item>, logger: Logger) {
Expand Down Expand Up @@ -251,7 +274,7 @@ export class Adapter<Item = unknown> implements IAdapter<Item> {
if (type === AdapterPropType.Function) {
value = (value as () => void).bind(this);
} else if (type === AdapterPropType.WorkflowRunner) {
value = this.getPromisifiedMethod(value as MethodResolver, defaultValue as MethodResolver);
value = this.getWorkflowRunnerMethod(value as MethodResolver, defaultValue as MethodResolver);
} else if (type === AdapterPropType.Reactive && reactivePropsStore[name]) {
value = (context as IAdapter)[name];
} else if (name === AdapterPropName.augmented) {
Expand Down
12 changes: 10 additions & 2 deletions src/classes/adapter/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ export const methodPreResult: AdapterMethodResult = {
details: 'Adapter is not initialized'
};

export const methodPausedResult: AdapterMethodResult = {
immediate: true,
success: true,
details: 'Scroller is paused'
};

const noopWF = () => Promise.resolve(methodPreResult);

const emptyPackageInfo: IPackages = {
Expand Down Expand Up @@ -186,7 +192,8 @@ export const getDefaultAdapterProps = (): IAdapterProp[] => [
{
type: Type.WorkflowRunner,
name: Name.reset,
value: noopWF
value: noopWF,
allowedWhenPaused: true
},
{
type: Type.WorkflowRunner,
Expand Down Expand Up @@ -241,7 +248,8 @@ export const getDefaultAdapterProps = (): IAdapterProp[] => [
{
type: Type.WorkflowRunner,
name: Name.resume,
value: noopWF
value: noopWF,
allowedWhenPaused: true
},
{
type: Type.WorkflowRunner,
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface IAdapterProp {
wanted?: boolean;
onDemand?: boolean;
permanent?: boolean;
allowedWhenPaused?: boolean;
}

export interface ItemAdapter<Data = unknown> {
Expand Down
21 changes: 8 additions & 13 deletions src/processes/adapter/pause.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,19 @@ export default class Pause extends BaseAdapterProcessFactory(AdapterProcess.paus
static run(scroller: Scroller, options?: { resume: boolean }): void {
const resume = !!options?.resume;

if (!resume) {
if (!scroller.state.paused.get()) {
scroller.logger.log('pause scroller');
scroller.state.paused.set(true);
} else {
scroller.logger.log('pause scroller (cancelled)');
}
return;
}

if (!scroller.state.paused.get()) {
scroller.logger.log('resume scroller (cancelled)');
// pause branch
if (!resume && !scroller.state.paused.get()) {
scroller.logger.log('pause scroller');
scroller.state.paused.set(true);
scroller.workflow.call({
process: AdapterProcess.pause,
status: ProcessStatus.done
});
return;
}

scroller.logger.log('resume scroller');
scroller.state.paused.set(false);

scroller.workflow.call({
process: AdapterProcess.pause,
status: ProcessStatus.next
Expand Down
8 changes: 5 additions & 3 deletions src/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,11 @@ export class Workflow<ItemData = unknown> {
}
const { process, status } = processSubject;
// if the scroller is paused, any process other than "pause" and "reset" should be blocked
if (this.scroller.state.paused.get() && process !== AdapterProcess.pause && process !== AdapterProcess.reset) {
this.scroller.logger.log('scroller is paused: ' + process + ' process is ignored');
return;
if (this.scroller.state.paused.get()) {
if (![AdapterProcess.pause, AdapterProcess.reset].includes(process as AdapterProcess)) {
this.scroller.logger.log('scroller is paused: ' + process + ' process is ignored');
return;
}
}
if (process && process.startsWith('adapter') && status !== Status.next) {
this.adapterRun$.set(processSubject);
Expand Down

0 comments on commit 41045ad

Please sign in to comment.