@emmett-community/emmett-google-pubsub 0.2.0 → 0.4.0
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/README.md +59 -0
- package/dist/index.d.mts +55 -6
- package/dist/index.d.ts +55 -6
- package/dist/index.js +169 -127
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +169 -127
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -378,6 +378,65 @@ JavaScript `Date` objects are preserved through serialization:
|
|
|
378
378
|
|
|
379
379
|
See [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) for design decisions.
|
|
380
380
|
|
|
381
|
+
## Observability
|
|
382
|
+
|
|
383
|
+
The package supports optional observability through structured logging and OpenTelemetry tracing.
|
|
384
|
+
|
|
385
|
+
### Logging
|
|
386
|
+
|
|
387
|
+
Logging is opt-in and completely silent by default. To enable logging, provide a logger that implements the canonical `(context, message)` contract:
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
const messageBus = getPubSubMessageBus({
|
|
391
|
+
pubsub,
|
|
392
|
+
observability: {
|
|
393
|
+
logger: {
|
|
394
|
+
debug: (context, message) => console.debug(message, context),
|
|
395
|
+
info: (context, message) => console.info(message, context),
|
|
396
|
+
warn: (context, message) => console.warn(message, context),
|
|
397
|
+
error: (context, message) => console.error(message, context),
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
});
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
**Logger Contract:**
|
|
404
|
+
|
|
405
|
+
The logger MUST implement the canonical `(context, message)` contract:
|
|
406
|
+
|
|
407
|
+
- `context`: Structured data as `Record<string, unknown>` (first parameter)
|
|
408
|
+
- `message`: Human-readable log message (second parameter, optional)
|
|
409
|
+
|
|
410
|
+
Pino is natively compatible. For Winston, use an adapter.
|
|
411
|
+
|
|
412
|
+
**Log Levels:**
|
|
413
|
+
|
|
414
|
+
- `info` - Lifecycle events (start, stop)
|
|
415
|
+
- `debug` - External I/O operations (publish, subscribe)
|
|
416
|
+
- `warn` - Recoverable failures (timeouts, retries)
|
|
417
|
+
- `error` - Failures (with Error objects in `{ err: error }` format)
|
|
418
|
+
|
|
419
|
+
### Tracing (OpenTelemetry)
|
|
420
|
+
|
|
421
|
+
The package creates OpenTelemetry spans for key operations. Tracing is passive - the `@opentelemetry/api` is a no-op by default.
|
|
422
|
+
|
|
423
|
+
To enable tracing, configure OpenTelemetry in your application:
|
|
424
|
+
|
|
425
|
+
```typescript
|
|
426
|
+
import { NodeSDK } from '@opentelemetry/sdk-node';
|
|
427
|
+
const sdk = new NodeSDK({ /* config */ });
|
|
428
|
+
sdk.start();
|
|
429
|
+
|
|
430
|
+
// Spans from emmett-google-pubsub are now captured
|
|
431
|
+
const messageBus = getPubSubMessageBus({ pubsub });
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
**Notes:**
|
|
435
|
+
|
|
436
|
+
- The package never initializes OpenTelemetry
|
|
437
|
+
- No tracing flags needed - spans are always created (no-op if SDK not initialized)
|
|
438
|
+
- Message types and payloads are never included in spans or logs
|
|
439
|
+
|
|
381
440
|
## Compatibility
|
|
382
441
|
|
|
383
442
|
- **Node.js**: >= 18.0.0
|
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,45 @@
|
|
|
1
1
|
import { PubSub, Topic, Subscription, Message as Message$1 } from '@google-cloud/pubsub';
|
|
2
2
|
import { Message, SingleMessageHandler, Command, Event, SingleRawMessageHandlerWithoutContext, AnyMessage, MessageBus, EventSubscription, CommandProcessor, ScheduledMessageProcessor } from '@event-driven-io/emmett';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Canonical Logger contract for the Emmett ecosystem.
|
|
6
|
+
*
|
|
7
|
+
* DO NOT MODIFY this interface without updating ALL packages in the ecosystem.
|
|
8
|
+
*
|
|
9
|
+
* This package defines the canonical Logger interface.
|
|
10
|
+
* Implementations (Pino, Winston, etc.) MUST adapt to this contract.
|
|
11
|
+
* This contract MUST NOT adapt to any specific implementation.
|
|
12
|
+
*
|
|
13
|
+
* Semantic Rules:
|
|
14
|
+
* - context (first parameter): ALWAYS structured data as Record<string, unknown>
|
|
15
|
+
* - message (second parameter): ALWAYS the human-readable log message
|
|
16
|
+
* - The order is NEVER inverted
|
|
17
|
+
* - The (message, data) form is NOT valid for this contract
|
|
18
|
+
* - Error objects MUST use the 'err' key (frozen semantic)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // Pino - native compatibility
|
|
23
|
+
* import pino from 'pino';
|
|
24
|
+
* const logger = pino();
|
|
25
|
+
* // logger.info({ orderId }, 'Order created') matches our contract
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
interface Logger {
|
|
29
|
+
debug(context: Record<string, unknown>, message?: string): void;
|
|
30
|
+
info(context: Record<string, unknown>, message?: string): void;
|
|
31
|
+
warn(context: Record<string, unknown>, message?: string): void;
|
|
32
|
+
error(context: Record<string, unknown>, message?: string): void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Observability configuration options.
|
|
36
|
+
*/
|
|
37
|
+
interface ObservabilityOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Optional logger instance. When not provided, the library operates silently.
|
|
40
|
+
*/
|
|
41
|
+
logger?: Logger;
|
|
42
|
+
}
|
|
4
43
|
/**
|
|
5
44
|
* Configuration for PubSub MessageBus
|
|
6
45
|
*/
|
|
@@ -43,6 +82,11 @@ interface PubSubMessageBusConfig {
|
|
|
43
82
|
* @default true
|
|
44
83
|
*/
|
|
45
84
|
closePubSubClient?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Observability options (logging).
|
|
87
|
+
* If not provided, the package remains silent.
|
|
88
|
+
*/
|
|
89
|
+
observability?: ObservabilityOptions;
|
|
46
90
|
}
|
|
47
91
|
/**
|
|
48
92
|
* Subscription configuration options
|
|
@@ -217,14 +261,16 @@ declare function getOrCreateSubscription(topic: Topic, subscriptionName: string,
|
|
|
217
261
|
* Delete a subscription
|
|
218
262
|
*
|
|
219
263
|
* @param subscription - The subscription to delete
|
|
264
|
+
* @param logger - Optional logger for observability
|
|
220
265
|
*/
|
|
221
|
-
declare function deleteSubscription(subscription: Subscription): Promise<void>;
|
|
266
|
+
declare function deleteSubscription(subscription: Subscription, logger?: Logger): Promise<void>;
|
|
222
267
|
/**
|
|
223
268
|
* Delete multiple subscriptions
|
|
224
269
|
*
|
|
225
270
|
* @param subscriptions - Array of subscriptions to delete
|
|
271
|
+
* @param logger - Optional logger for observability
|
|
226
272
|
*/
|
|
227
|
-
declare function deleteSubscriptions(subscriptions: Subscription[]): Promise<void>;
|
|
273
|
+
declare function deleteSubscriptions(subscriptions: Subscription[], logger?: Logger): Promise<void>;
|
|
228
274
|
|
|
229
275
|
/**
|
|
230
276
|
* Generate a random UUID
|
|
@@ -351,18 +397,20 @@ declare function shouldRetry(error: unknown): boolean;
|
|
|
351
397
|
* @param message - The PubSub message
|
|
352
398
|
* @param handlers - Map of message type to handlers
|
|
353
399
|
* @param commandType - The command type being processed
|
|
400
|
+
* @param logger - Optional logger for observability
|
|
354
401
|
* @returns 'ack' if successful or permanent failure, 'nack' if retriable failure
|
|
355
402
|
*/
|
|
356
|
-
declare function handleCommandMessage(message: Message$1, handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, commandType: string): Promise<'ack' | 'nack'>;
|
|
403
|
+
declare function handleCommandMessage(message: Message$1, handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, commandType: string, logger?: Logger): Promise<'ack' | 'nack'>;
|
|
357
404
|
/**
|
|
358
405
|
* Process an incoming event message from PubSub
|
|
359
406
|
*
|
|
360
407
|
* @param message - The PubSub message
|
|
361
408
|
* @param handlers - Map of message type to handlers
|
|
362
409
|
* @param eventType - The event type being processed
|
|
410
|
+
* @param logger - Optional logger for observability
|
|
363
411
|
* @returns 'ack' if all handlers successful or permanent failure, 'nack' if retriable failure
|
|
364
412
|
*/
|
|
365
|
-
declare function handleEventMessage(message: Message$1, handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, eventType: string): Promise<'ack' | 'nack'>;
|
|
413
|
+
declare function handleEventMessage(message: Message$1, handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, eventType: string, logger?: Logger): Promise<'ack' | 'nack'>;
|
|
366
414
|
/**
|
|
367
415
|
* Create a message listener for a PubSub subscription
|
|
368
416
|
*
|
|
@@ -370,8 +418,9 @@ declare function handleEventMessage(message: Message$1, handlers: Map<string, Si
|
|
|
370
418
|
* @param messageType - The message type (command or event type)
|
|
371
419
|
* @param kind - Whether this is a command or event
|
|
372
420
|
* @param handlers - Map of message type to handlers
|
|
421
|
+
* @param logger - Optional logger for observability
|
|
373
422
|
*/
|
|
374
|
-
declare function createMessageListener(subscription: Subscription, messageType: string, kind: 'command' | 'event', handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]
|
|
423
|
+
declare function createMessageListener(subscription: Subscription, messageType: string, kind: 'command' | 'event', handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, logger?: Logger): void;
|
|
375
424
|
|
|
376
425
|
/**
|
|
377
426
|
* Create a Google Cloud Pub/Sub based message bus for Emmett
|
|
@@ -410,4 +459,4 @@ declare function createMessageListener(subscription: Subscription, messageType:
|
|
|
410
459
|
*/
|
|
411
460
|
declare function getPubSubMessageBus(config: PubSubMessageBusConfig): MessageBus & EventSubscription & CommandProcessor & ScheduledMessageProcessor & PubSubMessageBusLifecycle;
|
|
412
461
|
|
|
413
|
-
export { type HandlerRegistration, MessageScheduler, type PubSubMessageBusConfig, type PubSubMessageBusLifecycle, type PubSubMessageEnvelope, type ScheduleOptions, type ScheduledMessage, type ScheduledMessageInfo, type SchedulerConfig, type SubscriptionInfo, type SubscriptionOptions, assertNotEmptyString, assertPositiveNumber, attachMessageId, calculateScheduledTime, createMessageListener, deleteSubscription, deleteSubscriptions, deserialize, extractMessageId, filterReadyMessages, generateUUID, getCommandSubscriptionName, getCommandTopicName, getEventSubscriptionName, getEventTopicName, getOrCreateSubscription, getOrCreateTopic, getPubSubMessageBus, handleCommandMessage, handleEventMessage, serialize, shouldRetry };
|
|
462
|
+
export { type HandlerRegistration, type Logger, MessageScheduler, type ObservabilityOptions, type PubSubMessageBusConfig, type PubSubMessageBusLifecycle, type PubSubMessageEnvelope, type ScheduleOptions, type ScheduledMessage, type ScheduledMessageInfo, type SchedulerConfig, type SubscriptionInfo, type SubscriptionOptions, assertNotEmptyString, assertPositiveNumber, attachMessageId, calculateScheduledTime, createMessageListener, deleteSubscription, deleteSubscriptions, deserialize, extractMessageId, filterReadyMessages, generateUUID, getCommandSubscriptionName, getCommandTopicName, getEventSubscriptionName, getEventTopicName, getOrCreateSubscription, getOrCreateTopic, getPubSubMessageBus, handleCommandMessage, handleEventMessage, serialize, shouldRetry };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,45 @@
|
|
|
1
1
|
import { PubSub, Topic, Subscription, Message as Message$1 } from '@google-cloud/pubsub';
|
|
2
2
|
import { Message, SingleMessageHandler, Command, Event, SingleRawMessageHandlerWithoutContext, AnyMessage, MessageBus, EventSubscription, CommandProcessor, ScheduledMessageProcessor } from '@event-driven-io/emmett';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Canonical Logger contract for the Emmett ecosystem.
|
|
6
|
+
*
|
|
7
|
+
* DO NOT MODIFY this interface without updating ALL packages in the ecosystem.
|
|
8
|
+
*
|
|
9
|
+
* This package defines the canonical Logger interface.
|
|
10
|
+
* Implementations (Pino, Winston, etc.) MUST adapt to this contract.
|
|
11
|
+
* This contract MUST NOT adapt to any specific implementation.
|
|
12
|
+
*
|
|
13
|
+
* Semantic Rules:
|
|
14
|
+
* - context (first parameter): ALWAYS structured data as Record<string, unknown>
|
|
15
|
+
* - message (second parameter): ALWAYS the human-readable log message
|
|
16
|
+
* - The order is NEVER inverted
|
|
17
|
+
* - The (message, data) form is NOT valid for this contract
|
|
18
|
+
* - Error objects MUST use the 'err' key (frozen semantic)
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* // Pino - native compatibility
|
|
23
|
+
* import pino from 'pino';
|
|
24
|
+
* const logger = pino();
|
|
25
|
+
* // logger.info({ orderId }, 'Order created') matches our contract
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
interface Logger {
|
|
29
|
+
debug(context: Record<string, unknown>, message?: string): void;
|
|
30
|
+
info(context: Record<string, unknown>, message?: string): void;
|
|
31
|
+
warn(context: Record<string, unknown>, message?: string): void;
|
|
32
|
+
error(context: Record<string, unknown>, message?: string): void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Observability configuration options.
|
|
36
|
+
*/
|
|
37
|
+
interface ObservabilityOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Optional logger instance. When not provided, the library operates silently.
|
|
40
|
+
*/
|
|
41
|
+
logger?: Logger;
|
|
42
|
+
}
|
|
4
43
|
/**
|
|
5
44
|
* Configuration for PubSub MessageBus
|
|
6
45
|
*/
|
|
@@ -43,6 +82,11 @@ interface PubSubMessageBusConfig {
|
|
|
43
82
|
* @default true
|
|
44
83
|
*/
|
|
45
84
|
closePubSubClient?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Observability options (logging).
|
|
87
|
+
* If not provided, the package remains silent.
|
|
88
|
+
*/
|
|
89
|
+
observability?: ObservabilityOptions;
|
|
46
90
|
}
|
|
47
91
|
/**
|
|
48
92
|
* Subscription configuration options
|
|
@@ -217,14 +261,16 @@ declare function getOrCreateSubscription(topic: Topic, subscriptionName: string,
|
|
|
217
261
|
* Delete a subscription
|
|
218
262
|
*
|
|
219
263
|
* @param subscription - The subscription to delete
|
|
264
|
+
* @param logger - Optional logger for observability
|
|
220
265
|
*/
|
|
221
|
-
declare function deleteSubscription(subscription: Subscription): Promise<void>;
|
|
266
|
+
declare function deleteSubscription(subscription: Subscription, logger?: Logger): Promise<void>;
|
|
222
267
|
/**
|
|
223
268
|
* Delete multiple subscriptions
|
|
224
269
|
*
|
|
225
270
|
* @param subscriptions - Array of subscriptions to delete
|
|
271
|
+
* @param logger - Optional logger for observability
|
|
226
272
|
*/
|
|
227
|
-
declare function deleteSubscriptions(subscriptions: Subscription[]): Promise<void>;
|
|
273
|
+
declare function deleteSubscriptions(subscriptions: Subscription[], logger?: Logger): Promise<void>;
|
|
228
274
|
|
|
229
275
|
/**
|
|
230
276
|
* Generate a random UUID
|
|
@@ -351,18 +397,20 @@ declare function shouldRetry(error: unknown): boolean;
|
|
|
351
397
|
* @param message - The PubSub message
|
|
352
398
|
* @param handlers - Map of message type to handlers
|
|
353
399
|
* @param commandType - The command type being processed
|
|
400
|
+
* @param logger - Optional logger for observability
|
|
354
401
|
* @returns 'ack' if successful or permanent failure, 'nack' if retriable failure
|
|
355
402
|
*/
|
|
356
|
-
declare function handleCommandMessage(message: Message$1, handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, commandType: string): Promise<'ack' | 'nack'>;
|
|
403
|
+
declare function handleCommandMessage(message: Message$1, handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, commandType: string, logger?: Logger): Promise<'ack' | 'nack'>;
|
|
357
404
|
/**
|
|
358
405
|
* Process an incoming event message from PubSub
|
|
359
406
|
*
|
|
360
407
|
* @param message - The PubSub message
|
|
361
408
|
* @param handlers - Map of message type to handlers
|
|
362
409
|
* @param eventType - The event type being processed
|
|
410
|
+
* @param logger - Optional logger for observability
|
|
363
411
|
* @returns 'ack' if all handlers successful or permanent failure, 'nack' if retriable failure
|
|
364
412
|
*/
|
|
365
|
-
declare function handleEventMessage(message: Message$1, handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, eventType: string): Promise<'ack' | 'nack'>;
|
|
413
|
+
declare function handleEventMessage(message: Message$1, handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, eventType: string, logger?: Logger): Promise<'ack' | 'nack'>;
|
|
366
414
|
/**
|
|
367
415
|
* Create a message listener for a PubSub subscription
|
|
368
416
|
*
|
|
@@ -370,8 +418,9 @@ declare function handleEventMessage(message: Message$1, handlers: Map<string, Si
|
|
|
370
418
|
* @param messageType - The message type (command or event type)
|
|
371
419
|
* @param kind - Whether this is a command or event
|
|
372
420
|
* @param handlers - Map of message type to handlers
|
|
421
|
+
* @param logger - Optional logger for observability
|
|
373
422
|
*/
|
|
374
|
-
declare function createMessageListener(subscription: Subscription, messageType: string, kind: 'command' | 'event', handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]
|
|
423
|
+
declare function createMessageListener(subscription: Subscription, messageType: string, kind: 'command' | 'event', handlers: Map<string, SingleRawMessageHandlerWithoutContext<AnyMessage>[]>, logger?: Logger): void;
|
|
375
424
|
|
|
376
425
|
/**
|
|
377
426
|
* Create a Google Cloud Pub/Sub based message bus for Emmett
|
|
@@ -410,4 +459,4 @@ declare function createMessageListener(subscription: Subscription, messageType:
|
|
|
410
459
|
*/
|
|
411
460
|
declare function getPubSubMessageBus(config: PubSubMessageBusConfig): MessageBus & EventSubscription & CommandProcessor & ScheduledMessageProcessor & PubSubMessageBusLifecycle;
|
|
412
461
|
|
|
413
|
-
export { type HandlerRegistration, MessageScheduler, type PubSubMessageBusConfig, type PubSubMessageBusLifecycle, type PubSubMessageEnvelope, type ScheduleOptions, type ScheduledMessage, type ScheduledMessageInfo, type SchedulerConfig, type SubscriptionInfo, type SubscriptionOptions, assertNotEmptyString, assertPositiveNumber, attachMessageId, calculateScheduledTime, createMessageListener, deleteSubscription, deleteSubscriptions, deserialize, extractMessageId, filterReadyMessages, generateUUID, getCommandSubscriptionName, getCommandTopicName, getEventSubscriptionName, getEventTopicName, getOrCreateSubscription, getOrCreateTopic, getPubSubMessageBus, handleCommandMessage, handleEventMessage, serialize, shouldRetry };
|
|
462
|
+
export { type HandlerRegistration, type Logger, MessageScheduler, type ObservabilityOptions, type PubSubMessageBusConfig, type PubSubMessageBusLifecycle, type PubSubMessageEnvelope, type ScheduleOptions, type ScheduledMessage, type ScheduledMessageInfo, type SchedulerConfig, type SubscriptionInfo, type SubscriptionOptions, assertNotEmptyString, assertPositiveNumber, attachMessageId, calculateScheduledTime, createMessageListener, deleteSubscription, deleteSubscriptions, deserialize, extractMessageId, filterReadyMessages, generateUUID, getCommandSubscriptionName, getCommandTopicName, getEventSubscriptionName, getEventTopicName, getOrCreateSubscription, getOrCreateTopic, getPubSubMessageBus, handleCommandMessage, handleEventMessage, serialize, shouldRetry };
|