EdgeStream
Post-Pipeline Hook
Post-pipeline hooks run after core processing and before subscriber delivery. They are for side effects — audit logging, metrics, acknowledgment — that must happen after processing but before the message reaches subscribers.
Priority Range: 300+
Post-pipeline hooks use priorities of 300 and above. They see the final, fully-processed envelope and have access to all metadata accumulated during pre-pipeline and processing stages.
Audit Hook Pattern
export class MessageAuditHook extends BaseHook {
readonly name = 'MessageAuditHook';
readonly priority = 300;
constructor(private auditStore: AuditStore) { super(); }
async execute(context: IPipelineContext): Promise<HookResult> {
// Non-blocking audit — fire and forget
this.auditStore.record({
messageId: context.envelope.meta.id,
topic: context.envelope.meta.topic,
serverId: context.envelope.meta.serverId,
userId: context.metadata.userId as string,
tenantId: context.metadata.tenantId as string,
receivedAt: context.envelope.meta.receivedAt.toISOString(),
bodyHash: await this.hashBody(context.body),
}).catch(err =>
console.warn('[MessageAuditHook] Audit write failed (non-critical):', err)
);
return { continue: true }; // always continue — audit is non-blocking
}
private async hashBody(body: unknown): Promise<string> {
const json = JSON.stringify(body);
const buffer = new TextEncoder().encode(json);
const hash = await crypto.subtle.digest('SHA-256', buffer);
return Array.from(new Uint8Array(hash))
.map(b => b.toString(16).padStart(2, '0'))
.join('');
}
}
Prometheus Metrics Hook
export class PrometheusMetricsHook extends BaseHook {
readonly name = 'PrometheusMetricsHook';
readonly priority = 310;
async execute(context: IPipelineContext): Promise<HookResult> {
const labels = {
topic: (context.envelope.meta.topic || 'unknown').split('.')[0],
transport: context.envelope.meta.transport,
server: context.envelope.meta.serverId,
};
metrics.counter('edge_stream_messages_total', labels).inc();
metrics.histogram('edge_stream_message_body_bytes', labels)
.observe(JSON.stringify(context.body).length);
return { continue: true };
}
}
Don't Block Delivery
Post-pipeline hooks run synchronously before subscriber delivery. Use
fire-and-forget (non-awaited promises) for I/O operations that should not delay subscribers. Always catch errors internally so a failed side-effect does not drop the message.