pulse-sdk 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/config.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface PulseConfig {
9
9
  eventTypes: string[];
10
10
  consumerName?: string;
11
11
  grouped?: boolean;
12
+ autoCommit?: boolean;
12
13
  topics?: TopicConfig[];
13
14
  }
14
15
  export declare function loadConfig(configPath?: string): PulseConfig;
package/dist/config.js CHANGED
@@ -14,6 +14,7 @@ const DEFAULTS = {
14
14
  grpcUrl: 'localhost:50052',
15
15
  eventTypes: ['events'],
16
16
  grouped: true,
17
+ autoCommit: true,
17
18
  };
18
19
  function loadConfig(configPath) {
19
20
  const candidates = [
@@ -40,12 +41,16 @@ function loadConfig(configPath) {
40
41
  envCfg.consumerName = process.env.PULSE_CONSUMER_NAME;
41
42
  if (process.env.PULSE_GROUPED)
42
43
  envCfg.grouped = process.env.PULSE_GROUPED === 'true';
44
+ if (process.env.PULSE_AUTOCOMMIT)
45
+ envCfg.autoCommit = process.env.PULSE_AUTOCOMMIT === 'true';
43
46
  const merged = Object.assign({}, DEFAULTS, fileCfg, envCfg);
44
47
  // Ensure eventTypes array exists
45
48
  if (!merged.eventTypes)
46
49
  merged.eventTypes = DEFAULTS.eventTypes;
47
50
  if (merged.grouped === undefined)
48
51
  merged.grouped = true;
52
+ if (merged.autoCommit === undefined)
53
+ merged.autoCommit = true;
49
54
  return merged;
50
55
  }
51
56
  // Initialize topics from config using gRPC CreateTopic RPC.
@@ -1,5 +1,5 @@
1
1
  import { PulseConfig } from './config';
2
- export type EventHandler = (payload: any) => void;
2
+ export type EventHandler = (payload: any) => any;
3
3
  export declare class Consumer {
4
4
  private config;
5
5
  private handlers;
package/dist/consumer.js CHANGED
@@ -28,15 +28,25 @@ class Consumer {
28
28
  const handlers = this.handlers[topicName] || [];
29
29
  for (const h of handlers) {
30
30
  const unregister = (0, consumerManager_1.registerSharedHandler)(this.config.grpcUrl, topicName, consumerName, (msg, stub, offset) => {
31
- // run handler with context so commit() works
31
+ // run handler with context so commit() works and support auto-commit
32
32
  // debug: console.log('consumer.wrapper.invoke', consumerName, topicName);
33
- (0, message_1.runWithContext)({ stub: stub || this.client, topic: topicName, consumerName, offset: offset ?? msg.offset }, () => {
34
- try {
35
- h(msg);
36
- }
37
- catch (e) { /* ignore */ }
38
- });
39
- });
33
+ (async () => {
34
+ await (0, message_1.runWithContext)({ stub: stub || this.client, topic: topicName, consumerName, offset: offset ?? msg.offset }, async () => {
35
+ try {
36
+ const r = h(msg);
37
+ if (r && typeof r.then === 'function')
38
+ await r;
39
+ }
40
+ catch (e) { /* ignore */ }
41
+ if (this.config.autoCommit !== false) {
42
+ try {
43
+ await (0, message_1.commit)();
44
+ }
45
+ catch (_) { /* ignore commit errors */ }
46
+ }
47
+ });
48
+ })().catch(() => { });
49
+ }, { autoCommit: this.config.autoCommit });
40
50
  this.unregisterFns.push(unregister);
41
51
  }
42
52
  // Return a promise that never resolves (stream runs until process exits)
@@ -69,12 +79,27 @@ class Consumer {
69
79
  const handlers = this.handlers[req.topic] || [];
70
80
  for (const h of handlers) {
71
81
  // run handler within AsyncLocalStorage context so commit() can access stub and offset
72
- (0, message_1.runWithContext)({ stub: this.client, topic: req.topic, consumerName, offset: message.offset }, () => {
82
+ (async () => {
73
83
  try {
74
- h(message);
84
+ await (0, message_1.runWithContext)({ stub: this.client, topic: req.topic, consumerName, offset: message.offset }, async () => {
85
+ try {
86
+ const r = h(message);
87
+ if (r && typeof r.then === 'function')
88
+ await r;
89
+ }
90
+ catch (e) { /* handler error ignored here */ }
91
+ if (this.config.autoCommit !== false) {
92
+ try {
93
+ await (0, message_1.commit)();
94
+ }
95
+ catch (_) { /* ignore commit errors */ }
96
+ }
97
+ });
75
98
  }
76
- catch (e) { /* handler error ignored here */ }
77
- });
99
+ catch (err) {
100
+ // ignore
101
+ }
102
+ })().catch(() => { });
78
103
  }
79
104
  });
80
105
  const p = new Promise((resolve, reject) => {
@@ -1,4 +1,6 @@
1
- type Handler = (msg: any) => void;
1
+ type Handler = (msg: any) => any;
2
2
  export declare function shutdownAll(): Promise<void>;
3
- export declare function registerSharedHandler(grpcUrl: string, topic: string, consumerName: string, handler: Handler): () => void;
3
+ export declare function registerSharedHandler(grpcUrl: string, topic: string, consumerName: string, handler: Handler, opts?: {
4
+ autoCommit?: boolean;
5
+ }): () => void;
4
6
  export {};
@@ -46,12 +46,12 @@ const registry = new Map();
46
46
  function keyFor(grpcUrl, topic, consumerName) {
47
47
  return `${grpcUrl}::${topic}::${consumerName}`;
48
48
  }
49
- function registerSharedHandler(grpcUrl, topic, consumerName, handler) {
49
+ function registerSharedHandler(grpcUrl, topic, consumerName, handler, opts) {
50
50
  const k = keyFor(grpcUrl, topic, consumerName);
51
51
  let entry = registry.get(k);
52
52
  if (!entry) {
53
53
  const client = (0, client_1.createClient)(grpcUrl);
54
- entry = { topic, consumerName, client, stream: null, handlers: new Set(), nextIndex: 0, grpcUrl };
54
+ entry = { topic, consumerName, client, stream: null, handlers: new Set(), nextIndex: 0, grpcUrl, autoCommit: opts?.autoCommit !== false };
55
55
  // add handler before starting the stream to avoid losing early messages
56
56
  entry.handlers.add(handler);
57
57
  registry.set(k, entry);
@@ -106,16 +106,25 @@ function startStream(entry) {
106
106
  entry.nextIndex = 0;
107
107
  const h = handlers[entry.nextIndex % handlers.length];
108
108
  entry.nextIndex = (entry.nextIndex + 1) % handlers.length;
109
- try {
110
- // run handler inside context providing the stub for commit()
111
- // debug: console.log('consumerManager.dispatch', entry.topic, 'offset', message.offset, 'handlerIndex', entry.nextIndex);
112
- (0, message_1.runWithContext)({ stub: entry.client, topic: entry.topic, consumerName: entry.consumerName, offset: message.offset }, () => {
113
- h(message);
114
- });
115
- }
116
- catch (e) {
117
- console.warn('handler error', e);
118
- }
109
+ // run handler inside context providing the stub for commit(); support async handlers
110
+ (async () => {
111
+ try {
112
+ await (0, message_1.runWithContext)({ stub: entry.client, topic: entry.topic, consumerName: entry.consumerName, offset: message.offset }, async () => {
113
+ const r = h(message);
114
+ if (r && typeof r.then === 'function')
115
+ await r;
116
+ if (entry.autoCommit) {
117
+ try {
118
+ await (0, message_1.commit)();
119
+ }
120
+ catch (err) { /* ignore commit errors here */ }
121
+ }
122
+ });
123
+ }
124
+ catch (e) {
125
+ console.warn('handler error', e);
126
+ }
127
+ })().catch(() => { });
119
128
  });
120
129
  stream.on('error', (e) => {
121
130
  // Log once and clean up the registry entry to avoid reconnect storms and test leaks
package/dist/message.d.ts CHANGED
@@ -11,7 +11,7 @@ interface MessageContext {
11
11
  offset: number;
12
12
  committed?: boolean;
13
13
  }
14
- export declare function runWithContext(ctx: MessageContext, fn: () => void): void;
14
+ export declare function runWithContext(ctx: MessageContext, fn: () => void): unknown;
15
15
  export declare function getContext(): MessageContext | undefined;
16
16
  export declare function commit(): Promise<void>;
17
17
  export declare class Message implements IMessage {
package/dist/message.js CHANGED
@@ -7,7 +7,7 @@ exports.commit = commit;
7
7
  const async_hooks_1 = require("async_hooks");
8
8
  const storage = new async_hooks_1.AsyncLocalStorage();
9
9
  function runWithContext(ctx, fn) {
10
- storage.run(ctx, fn);
10
+ return storage.run(ctx, fn);
11
11
  }
12
12
  function getContext() {
13
13
  return storage.getStore();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pulse-sdk",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Pulse SDK for Node.js/TypeScript",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",