fix: Don't buffer data before sending response with InMemoryResourceStore

This commit is contained in:
Joachim Van Herwegen 2020-09-03 10:46:26 +02:00
parent 52e1e065df
commit 785ec1ee07
2 changed files with 15 additions and 8 deletions

View File

@ -1,3 +1,4 @@
import { PassThrough } from 'stream';
import arrayifyStream from 'arrayify-stream'; import arrayifyStream from 'arrayify-stream';
import streamifyArray from 'streamify-array'; import streamifyArray from 'streamify-array';
import { RuntimeConfig } from '../init/RuntimeConfig'; import { RuntimeConfig } from '../init/RuntimeConfig';
@ -113,7 +114,7 @@ export class InMemoryResourceStore implements ResourceStore {
/** /**
* Checks if the relative path is in the store. * Checks if the relative path is in the store.
* @param identifier - Incoming identifier. * @param path - Incoming identifier.
* *
* @throws {@link NotFoundHttpError} * @throws {@link NotFoundHttpError}
* If the path is not in the store. * If the path is not in the store.
@ -127,7 +128,7 @@ export class InMemoryResourceStore implements ResourceStore {
/** /**
* Copies the Representation by draining the original data stream and creating a new one. * Copies the Representation by draining the original data stream and creating a new one.
* *
* @param data - Incoming Representation. * @param source - Incoming Representation.
*/ */
private async copyRepresentation(source: Representation): Promise<Representation> { private async copyRepresentation(source: Representation): Promise<Representation> {
const arr = await arrayifyStream(source.data); const arr = await arrayifyStream(source.data);
@ -147,13 +148,19 @@ export class InMemoryResourceStore implements ResourceStore {
* @returns The resulting Representation. * @returns The resulting Representation.
*/ */
private async generateRepresentation(path: string): Promise<Representation> { private async generateRepresentation(path: string): Promise<Representation> {
// Note: when converting to a complete ResourceStore and using readable-stream
// object mode should be set correctly here (now fixed due to Node 10)
const source = this.store[path]; const source = this.store[path];
const arr = await arrayifyStream(source.data); const streamInternal = new PassThrough({ writableObjectMode: true, readableObjectMode: true });
source.data = streamifyArray([ ...arr ]); const streamOutput = new PassThrough({ writableObjectMode: true, readableObjectMode: true });
source.data.pipe(streamInternal);
source.data.pipe(streamOutput);
source.data = streamInternal;
return { return {
binary: source.binary, binary: source.binary,
data: streamifyArray([ ...arr ]), data: streamOutput,
metadata: source.metadata, metadata: source.metadata,
}; };
} }

View File

@ -1,11 +1,11 @@
import { Readable } from 'stream'; import { Readable } from 'stream';
import arrayifyStream from 'arrayify-stream';
import streamifyArray from 'streamify-array'; import streamifyArray from 'streamify-array';
import { RuntimeConfig } from '../../../src/init/RuntimeConfig'; import { RuntimeConfig } from '../../../src/init/RuntimeConfig';
import { Representation } from '../../../src/ldp/representation/Representation'; import { Representation } from '../../../src/ldp/representation/Representation';
import { RepresentationMetadata } from '../../../src/ldp/representation/RepresentationMetadata'; import { RepresentationMetadata } from '../../../src/ldp/representation/RepresentationMetadata';
import { InMemoryResourceStore } from '../../../src/storage/InMemoryResourceStore'; import { InMemoryResourceStore } from '../../../src/storage/InMemoryResourceStore';
import { NotFoundHttpError } from '../../../src/util/errors/NotFoundHttpError'; import { NotFoundHttpError } from '../../../src/util/errors/NotFoundHttpError';
import { readableToString } from '../../../src/util/Util';
const base = 'http://test.com/'; const base = 'http://test.com/';
@ -46,7 +46,7 @@ describe('A InMemoryResourceStore', (): void => {
data: expect.any(Readable), data: expect.any(Readable),
metadata: representation.metadata, metadata: representation.metadata,
}); });
await expect(arrayifyStream(result.data)).resolves.toEqual([ dataString ]); await expect(readableToString(result.data)).resolves.toEqual(dataString);
}); });
it('can add resources to previously added resources.', async(): Promise<void> => { it('can add resources to previously added resources.', async(): Promise<void> => {
@ -64,7 +64,7 @@ describe('A InMemoryResourceStore', (): void => {
data: expect.any(Readable), data: expect.any(Readable),
metadata: representation.metadata, metadata: representation.metadata,
}); });
await expect(arrayifyStream(result.data)).resolves.toEqual([ dataString ]); await expect(readableToString(result.data)).resolves.toEqual(dataString);
}); });
it('can delete data.', async(): Promise<void> => { it('can delete data.', async(): Promise<void> => {