fix: Ensure streaming HTTP streams the whole notification in a single chunk

This commit is contained in:
elf Pavlik
2024-08-02 15:50:07 -06:00
committed by Joachim Van Herwegen
parent 576eefede6
commit 3dd8602acc
4 changed files with 73 additions and 22 deletions

View File

@@ -1,6 +1,7 @@
import { getLoggerFor } from '../../../logging/LogUtil';
import type { Representation } from '../../../http/representation/Representation';
import { AsyncHandler } from '../../../util/handlers/AsyncHandler';
import { readableToString } from '../../../util/StreamUtil';
import type { NotificationChannel } from '../NotificationChannel';
import type { StreamingHttpMap } from './StreamingHttpMap';
@@ -27,8 +28,10 @@ export class StreamingHttp2023Emitter extends AsyncHandler<StreamingHttpEmitterI
// Called as a NotificationEmitter: emit the notification
const streams = this.streamMap.get(channel.topic);
if (streams) {
// Ensure that the whole notification gets sent in a single chunk
const chunk = await readableToString(representation.data);
for (const stream of streams) {
representation.data.pipe(stream, { end: false });
stream.write(chunk);
}
} else {
representation.data.destroy();

View File

@@ -15,6 +15,7 @@ import { IdentifierSetMultiMap } from '../../../util/map/IdentifierMap';
import { createErrorMessage } from '../../../util/errors/ErrorUtil';
import type { NotificationGenerator } from '../generate/NotificationGenerator';
import type { NotificationSerializer } from '../serialize/NotificationSerializer';
import { readableToString } from '../../../util/StreamUtil';
import type { StreamingHttpMap } from './StreamingHttpMap';
import { generateChannel } from './StreamingHttp2023Util';
@@ -54,7 +55,9 @@ export class StreamingHttpRequestHandler extends OperationHttpHandler {
try {
const notification = await this.generator.handle({ channel, topic: { path: topic }});
const representation = await this.serializer.handleSafe({ channel, notification });
representation.data.pipe(stream, { end: false });
// Ensure that the whole notification gets sent in a single chunk
const chunk = await readableToString(representation.data);
stream.write(chunk);
} catch (error: unknown) {
this.logger.error(`Problem emitting initial notification: ${createErrorMessage(error)}`);
}