From 81373206a17d0fcb8d3af701e5266287113d545c Mon Sep 17 00:00:00 2001 From: Jacopo Scazzosi Date: Wed, 14 Apr 2021 11:07:16 +0200 Subject: [PATCH] Allow context modification in optimize-query-operation bus --- .../lib/ActorInitSparql-browser.ts | 4 +- .../test/ActorInitSparql-test.ts | 21 ++++++++++ .../lib/ActorHttpInvalidateListenable.ts | 2 +- .../lib/ActorOptimizeQueryOperation.ts | 2 + .../bus-optimize-query-operation/package.json | 1 + .../lib/MediatorCombinePipeline.ts | 2 +- .../test/MediatorCombinePipeline-test.ts | 39 ++++++++++++++++--- 7 files changed, 63 insertions(+), 8 deletions(-) diff --git a/packages/actor-init-sparql/lib/ActorInitSparql-browser.ts b/packages/actor-init-sparql/lib/ActorInitSparql-browser.ts index 9672a129d3..4883dfc567 100644 --- a/packages/actor-init-sparql/lib/ActorInitSparql-browser.ts +++ b/packages/actor-init-sparql/lib/ActorInitSparql-browser.ts @@ -199,7 +199,9 @@ export class ActorInitSparql extends ActorInit implements IActorInitSparqlArgs, } // Optimize the query operation - operation = (await this.mediatorOptimizeQueryOperation.mediate({ context, operation })).operation; + const mediatorResult = await this.mediatorOptimizeQueryOperation.mediate({ context, operation }); + operation = mediatorResult.operation; + context = mediatorResult.context || context; // Pre-processing the context, this time with the operation context = (await this.mediatorContextPreprocess.mediate({ context, operation })).context; diff --git a/packages/actor-init-sparql/test/ActorInitSparql-test.ts b/packages/actor-init-sparql/test/ActorInitSparql-test.ts index f91e0bed31..4166b32ad4 100644 --- a/packages/actor-init-sparql/test/ActorInitSparql-test.ts +++ b/packages/actor-init-sparql/test/ActorInitSparql-test.ts @@ -621,6 +621,27 @@ describe('ActorInitSparql', () => { '@comunica/actor-init-sparql:baseIRI': 'myBaseIRI', }); }); + + it('should pass down the provided context if optimize actors do not return one', async() => { + mediatorOptimizeQueryOperation.mediate = (action: any) => { + return Promise.resolve({ ...action, context: undefined }); + }; + const result = await actor.query('SELECT * WHERE { ?s ?p ?o }', { 'the-answer': 42 }); + expect(result).toHaveProperty('context'); + expect(result.context!.get('the-answer')).toEqual(42); + }); + + it('should allow optimize actors to modify the context', async() => { + mediatorOptimizeQueryOperation.mediate = (action: any) => { + return Promise.resolve({ + ...action, + context: action.context.set('the-answer', 42), + }); + }; + const result = await actor.query('SELECT * WHERE { ?s ?p ?o }'); + expect(result).toHaveProperty('context'); + expect(result.context!.get('the-answer')).toEqual(42); + }); }); it('bindings() should collect all bindings until "end" event occurs on triples', async() => { diff --git a/packages/bus-http-invalidate/lib/ActorHttpInvalidateListenable.ts b/packages/bus-http-invalidate/lib/ActorHttpInvalidateListenable.ts index 1780c4efec..f97d35e4f4 100644 --- a/packages/bus-http-invalidate/lib/ActorHttpInvalidateListenable.ts +++ b/packages/bus-http-invalidate/lib/ActorHttpInvalidateListenable.ts @@ -27,7 +27,7 @@ export class ActorHttpInvalidateListenable extends ActorHttpInvalidate { for (const listener of this.invalidateListeners) { listener(action); } - return true; + return {}; } } diff --git a/packages/bus-optimize-query-operation/lib/ActorOptimizeQueryOperation.ts b/packages/bus-optimize-query-operation/lib/ActorOptimizeQueryOperation.ts index d6eb13f9fc..b2af1394e9 100644 --- a/packages/bus-optimize-query-operation/lib/ActorOptimizeQueryOperation.ts +++ b/packages/bus-optimize-query-operation/lib/ActorOptimizeQueryOperation.ts @@ -1,5 +1,6 @@ import type { IAction, IActorArgs, IActorOutput, IActorTest } from '@comunica/core'; import { Actor } from '@comunica/core'; +import type { ActionContext } from '@comunica/types'; import type { Algebra } from 'sparqlalgebrajs'; /** @@ -26,4 +27,5 @@ export interface IActionOptimizeQueryOperation extends IAction { export interface IActorOptimizeQueryOperationOutput extends IActorOutput { operation: Algebra.Operation; + context?: ActionContext; } diff --git a/packages/bus-optimize-query-operation/package.json b/packages/bus-optimize-query-operation/package.json index 7db1747dc7..842ffdb84b 100644 --- a/packages/bus-optimize-query-operation/package.json +++ b/packages/bus-optimize-query-operation/package.json @@ -31,6 +31,7 @@ "index.js" ], "dependencies": { + "@comunica/types": "^1.20.0", "sparqlalgebrajs": "^2.5.5" }, "peerDependencies": { diff --git a/packages/mediator-combine-pipeline/lib/MediatorCombinePipeline.ts b/packages/mediator-combine-pipeline/lib/MediatorCombinePipeline.ts index 70c9cefbf2..8a3307a32f 100644 --- a/packages/mediator-combine-pipeline/lib/MediatorCombinePipeline.ts +++ b/packages/mediator-combine-pipeline/lib/MediatorCombinePipeline.ts @@ -27,7 +27,7 @@ export class MediatorCombinePipeline, H extends IAction // and each actor output as input to the following actor. let handle: H = action; for (const actor of testResults.map(result => result.actor)) { - handle = await actor.runObservable(handle); + handle = { ...handle, ...await actor.runObservable(handle) }; } // Return the final actor output diff --git a/packages/mediator-combine-pipeline/test/MediatorCombinePipeline-test.ts b/packages/mediator-combine-pipeline/test/MediatorCombinePipeline-test.ts index 9c9daafc08..b0069a4404 100644 --- a/packages/mediator-combine-pipeline/test/MediatorCombinePipeline-test.ts +++ b/packages/mediator-combine-pipeline/test/MediatorCombinePipeline-test.ts @@ -1,5 +1,5 @@ import type { IAction, IActorOutput, IActorTest } from '@comunica/core'; -import { Actor, Bus, Mediator } from '@comunica/core'; +import { Actor, Bus, Mediator, ActionContext } from '@comunica/core'; import { MediatorCombinePipeline } from '../lib/MediatorCombinePipeline'; describe('MediatorCombinePipeline', () => { @@ -39,6 +39,21 @@ describe('MediatorCombinePipeline', () => { it('should mediate', () => { return expect(mediator.mediate({ field: 1 })).resolves.toEqual({ field: 2_101 }); }); + + it('should mediate without changing the context', async() => { + const context = ActionContext({}); + const result = await mediator.mediate({ field: 1, context }); + expect(result).toEqual({ field: 2_101, context }); + }); + + it('should mediate changing the context', async() => { + new DummyActorContextOutput(1_000, bus); + const context = ActionContext({}); + const result = await mediator.mediate({ field: 1, context }); + expect(result).toHaveProperty('context'); + expect(result.context).not.toEqual(context); + expect(result.context!.get('id')).toEqual(1_000); + }); }); describe('An MediatorCombinePipeline instance without actors', () => { @@ -54,10 +69,10 @@ describe('MediatorCombinePipeline', () => { }); }); -class DummyActor extends Actor { +class DummyActor extends Actor { public readonly id: number; - public constructor(id: number, bus: Bus) { + public constructor(id: number, bus: Bus) { super({ name: `dummy${id}`, bus }); this.id = id; } @@ -66,11 +81,25 @@ class DummyActor extends Actor { return true; } - public async run(action: IDummyAction): Promise { + public async run(action: IDummyAction): Promise { return { field: action.field * this.id + this.id }; } } -interface IDummyAction extends IAction, IActorOutput { +class DummyActorContextOutput extends DummyActor { + public async run(action: IDummyAction): Promise { + return { + ...super.run(action), + context: (action.context || ActionContext({})).set('id', this.id), + }; + } +} + +interface IDummyAction extends IAction { + field: number; +} + +interface IDummyOutput extends IActorOutput { field: number; + context?: ActionContext; }