feat(streaming): Add streaming support: chunked stream transfers, file send/receive, stream events and helpers
This commit is contained in:
@@ -200,6 +200,12 @@ export class IpcServer extends plugins.EventEmitter {
|
||||
this.emit('error', error, 'server');
|
||||
});
|
||||
|
||||
// Forward streaming events to server level
|
||||
this.primaryChannel.on('stream', (info: any, readable: plugins.stream.Readable) => {
|
||||
// Emit ('stream', info, readable)
|
||||
this.emit('stream', info, readable);
|
||||
});
|
||||
|
||||
this.primaryChannel.on('heartbeatTimeout', (error) => {
|
||||
// Forward heartbeatTimeout event (when heartbeatThrowOnTimeout is false)
|
||||
this.emit('heartbeatTimeout', error, 'server');
|
||||
@@ -396,6 +402,52 @@ export class IpcServer extends plugins.EventEmitter {
|
||||
await client.channel.sendMessage(type, payload, routedHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Node.js readable stream to a specific client
|
||||
*/
|
||||
public async sendStreamToClient(clientId: string, readable: plugins.stream.Readable | NodeJS.ReadableStream, options?: { headers?: Record<string, any>; chunkSize?: number; streamId?: string; meta?: Record<string, any> }): Promise<void> {
|
||||
const client = this.clients.get(clientId);
|
||||
if (!client) {
|
||||
throw new Error(`Client ${clientId} not found`);
|
||||
}
|
||||
const headers = { ...(options?.headers || {}), clientId };
|
||||
await (client.channel as any).sendStream(readable as any, { ...options, headers });
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a file to a specific client via streaming
|
||||
*/
|
||||
public async sendFileToClient(clientId: string, filePath: string, options?: { headers?: Record<string, any>; chunkSize?: number; streamId?: string; meta?: Record<string, any> }): Promise<void> {
|
||||
const client = this.clients.get(clientId);
|
||||
if (!client) {
|
||||
throw new Error(`Client ${clientId} not found`);
|
||||
}
|
||||
const fs = plugins.fs;
|
||||
const path = plugins.path;
|
||||
const stat = fs.statSync(filePath);
|
||||
const meta = {
|
||||
...(options?.meta || {}),
|
||||
type: 'file',
|
||||
basename: path.basename(filePath),
|
||||
size: stat.size,
|
||||
mtimeMs: stat.mtimeMs
|
||||
};
|
||||
const rs = fs.createReadStream(filePath);
|
||||
await this.sendStreamToClient(clientId, rs, { ...options, meta });
|
||||
}
|
||||
|
||||
/** Cancel a stream incoming from a client (server side) */
|
||||
public async cancelIncomingStreamFromClient(clientId: string, streamId: string): Promise<void> {
|
||||
if (!this.primaryChannel) return;
|
||||
await (this.primaryChannel as any).cancelIncomingStream(streamId, { clientId });
|
||||
}
|
||||
|
||||
/** Cancel a server->client outgoing stream */
|
||||
public async cancelOutgoingStreamToClient(clientId: string, streamId: string): Promise<void> {
|
||||
if (!this.primaryChannel) return;
|
||||
await (this.primaryChannel as any).cancelOutgoingStream(streamId, { clientId });
|
||||
}
|
||||
|
||||
/**
|
||||
* Send request to specific client and wait for response
|
||||
*/
|
||||
|
Reference in New Issue
Block a user