@venizia/ignis-docs 0.0.7-2 → 0.0.8-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/dist/mcp-server/common/paths.d.ts +4 -2
- package/dist/mcp-server/common/paths.d.ts.map +1 -1
- package/dist/mcp-server/common/paths.js +8 -6
- package/dist/mcp-server/common/paths.js.map +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/docs/get-document-content.tool.js +7 -7
- package/dist/mcp-server/tools/docs/get-document-metadata.tool.js +3 -3
- package/dist/mcp-server/tools/docs/get-package-overview.tool.d.ts +1 -1
- package/dist/mcp-server/tools/docs/get-package-overview.tool.js +1 -1
- package/package.json +1 -1
- package/wiki/best-practices/api-usage-examples.md +9 -9
- package/wiki/best-practices/architectural-patterns.md +19 -3
- package/wiki/best-practices/architecture-decisions.md +6 -6
- package/wiki/best-practices/code-style-standards/advanced-patterns.md +1 -1
- package/wiki/best-practices/code-style-standards/control-flow.md +1 -1
- package/wiki/best-practices/code-style-standards/function-patterns.md +2 -2
- package/wiki/best-practices/code-style-standards/index.md +2 -2
- package/wiki/best-practices/code-style-standards/naming-conventions.md +1 -1
- package/wiki/best-practices/code-style-standards/route-definitions.md +4 -4
- package/wiki/best-practices/data-modeling.md +1 -1
- package/wiki/best-practices/deployment-strategies.md +1 -1
- package/wiki/best-practices/error-handling.md +2 -2
- package/wiki/best-practices/performance-optimization.md +3 -3
- package/wiki/best-practices/security-guidelines.md +2 -2
- package/wiki/best-practices/troubleshooting-tips.md +1 -1
- package/wiki/{references → extensions}/components/authentication/api.md +12 -20
- package/wiki/{references → extensions}/components/authentication/errors.md +1 -1
- package/wiki/{references → extensions}/components/authentication/index.md +5 -8
- package/wiki/{references → extensions}/components/authentication/usage.md +20 -36
- package/wiki/{references → extensions}/components/authorization/api.md +62 -13
- package/wiki/{references → extensions}/components/authorization/errors.md +12 -7
- package/wiki/{references → extensions}/components/authorization/index.md +93 -6
- package/wiki/{references → extensions}/components/authorization/usage.md +42 -4
- package/wiki/{references → extensions}/components/health-check.md +5 -4
- package/wiki/{references → extensions}/components/index.md +2 -0
- package/wiki/{references → extensions}/components/mail/index.md +1 -1
- package/wiki/{references → extensions}/components/request-tracker.md +1 -1
- package/wiki/{references → extensions}/components/socket-io/api.md +2 -2
- package/wiki/{references → extensions}/components/socket-io/errors.md +2 -0
- package/wiki/{references → extensions}/components/socket-io/index.md +24 -20
- package/wiki/{references → extensions}/components/socket-io/usage.md +2 -2
- package/wiki/{references → extensions}/components/static-asset/api.md +14 -15
- package/wiki/{references → extensions}/components/static-asset/errors.md +3 -1
- package/wiki/{references → extensions}/components/static-asset/index.md +158 -89
- package/wiki/{references → extensions}/components/static-asset/usage.md +8 -5
- package/wiki/{references → extensions}/components/swagger.md +3 -3
- package/wiki/{references → extensions}/components/template/index.md +4 -4
- package/wiki/{references → extensions}/components/template/setup-page.md +1 -1
- package/wiki/{references → extensions}/components/template/single-page.md +1 -1
- package/wiki/{references → extensions}/components/websocket/api.md +7 -6
- package/wiki/{references → extensions}/components/websocket/errors.md +17 -3
- package/wiki/{references → extensions}/components/websocket/index.md +17 -11
- package/wiki/{references → extensions}/components/websocket/usage.md +2 -2
- package/wiki/{references → extensions}/helpers/crypto/index.md +1 -1
- package/wiki/{references → extensions}/helpers/env/index.md +9 -5
- package/wiki/{references → extensions}/helpers/error/index.md +2 -7
- package/wiki/{references → extensions}/helpers/index.md +18 -6
- package/wiki/{references → extensions}/helpers/kafka/admin.md +33 -16
- package/wiki/extensions/helpers/kafka/consumer.md +384 -0
- package/wiki/extensions/helpers/kafka/examples.md +361 -0
- package/wiki/extensions/helpers/kafka/index.md +639 -0
- package/wiki/{references → extensions}/helpers/kafka/producer.md +100 -96
- package/wiki/extensions/helpers/kafka/schema-registry.md +214 -0
- package/wiki/{references → extensions}/helpers/logger/index.md +2 -2
- package/wiki/{references → extensions}/helpers/queue/index.md +400 -4
- package/wiki/{references → extensions}/helpers/storage/api.md +170 -10
- package/wiki/{references → extensions}/helpers/storage/index.md +44 -8
- package/wiki/{references → extensions}/helpers/template/index.md +1 -1
- package/wiki/{references → extensions}/helpers/testing/index.md +4 -4
- package/wiki/{references → extensions}/helpers/types/index.md +63 -16
- package/wiki/{references → extensions}/helpers/websocket/index.md +1 -1
- package/wiki/extensions/index.md +48 -0
- package/wiki/guides/core-concepts/application/bootstrapping.md +55 -37
- package/wiki/guides/core-concepts/application/index.md +95 -35
- package/wiki/guides/core-concepts/components-guide.md +23 -19
- package/wiki/guides/core-concepts/components.md +34 -10
- package/wiki/guides/core-concepts/dependency-injection.md +99 -34
- package/wiki/guides/core-concepts/grpc-controllers.md +295 -0
- package/wiki/guides/core-concepts/persistent/datasources.md +27 -8
- package/wiki/guides/core-concepts/persistent/models.md +43 -1
- package/wiki/guides/core-concepts/persistent/repositories.md +75 -8
- package/wiki/guides/core-concepts/persistent/transactions.md +38 -8
- package/wiki/guides/core-concepts/{controllers.md → rest-controllers.md} +30 -33
- package/wiki/guides/core-concepts/services.md +19 -5
- package/wiki/guides/get-started/5-minute-quickstart.md +6 -7
- package/wiki/guides/get-started/philosophy.md +1 -1
- package/wiki/guides/index.md +2 -2
- package/wiki/guides/reference/glossary.md +7 -7
- package/wiki/guides/reference/mcp-docs-server.md +1 -1
- package/wiki/guides/tutorials/building-a-crud-api.md +2 -2
- package/wiki/guides/tutorials/complete-installation.md +17 -14
- package/wiki/guides/tutorials/ecommerce-api.md +18 -18
- package/wiki/guides/tutorials/realtime-chat.md +8 -8
- package/wiki/guides/tutorials/testing.md +2 -2
- package/wiki/index.md +4 -3
- package/wiki/references/base/application.md +341 -21
- package/wiki/references/base/bootstrapping.md +43 -13
- package/wiki/references/base/components.md +259 -8
- package/wiki/references/base/controllers.md +556 -253
- package/wiki/references/base/datasources.md +159 -79
- package/wiki/references/base/dependency-injection.md +299 -48
- package/wiki/references/base/filter-system/application-usage.md +18 -2
- package/wiki/references/base/filter-system/array-operators.md +14 -6
- package/wiki/references/base/filter-system/comparison-operators.md +9 -3
- package/wiki/references/base/filter-system/default-filter.md +28 -3
- package/wiki/references/base/filter-system/fields-order-pagination.md +17 -13
- package/wiki/references/base/filter-system/index.md +169 -11
- package/wiki/references/base/filter-system/json-filtering.md +51 -18
- package/wiki/references/base/filter-system/list-operators.md +4 -3
- package/wiki/references/base/filter-system/logical-operators.md +7 -2
- package/wiki/references/base/filter-system/null-operators.md +50 -0
- package/wiki/references/base/filter-system/quick-reference.md +82 -243
- package/wiki/references/base/filter-system/range-operators.md +7 -1
- package/wiki/references/base/filter-system/tips.md +34 -7
- package/wiki/references/base/filter-system/use-cases.md +6 -5
- package/wiki/references/base/grpc-controllers.md +984 -0
- package/wiki/references/base/index.md +32 -24
- package/wiki/references/base/middleware.md +347 -0
- package/wiki/references/base/models.md +390 -46
- package/wiki/references/base/providers.md +14 -14
- package/wiki/references/base/repositories/advanced.md +84 -69
- package/wiki/references/base/repositories/index.md +447 -12
- package/wiki/references/base/repositories/mixins.md +103 -98
- package/wiki/references/base/repositories/relations.md +129 -45
- package/wiki/references/base/repositories/soft-deletable.md +104 -23
- package/wiki/references/base/services.md +94 -14
- package/wiki/references/index.md +12 -10
- package/wiki/references/quick-reference.md +98 -65
- package/wiki/references/utilities/crypto.md +21 -4
- package/wiki/references/utilities/date.md +25 -7
- package/wiki/references/utilities/index.md +26 -24
- package/wiki/references/utilities/jsx.md +54 -54
- package/wiki/references/utilities/module.md +8 -6
- package/wiki/references/utilities/parse.md +16 -9
- package/wiki/references/utilities/performance.md +22 -7
- package/wiki/references/utilities/promise.md +19 -16
- package/wiki/references/utilities/request.md +48 -26
- package/wiki/references/utilities/schema.md +69 -6
- package/wiki/references/utilities/statuses.md +131 -140
- package/wiki/references/helpers/kafka/consumer.md +0 -473
- package/wiki/references/helpers/kafka/examples.md +0 -234
- package/wiki/references/helpers/kafka/index.md +0 -482
- /package/wiki/{references → extensions}/components/mail/api.md +0 -0
- /package/wiki/{references → extensions}/components/mail/errors.md +0 -0
- /package/wiki/{references → extensions}/components/mail/usage.md +0 -0
- /package/wiki/{references → extensions}/components/template/api-page.md +0 -0
- /package/wiki/{references → extensions}/components/template/errors-page.md +0 -0
- /package/wiki/{references → extensions}/components/template/usage-page.md +0 -0
- /package/wiki/{references → extensions}/helpers/cron/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/inversion/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/network/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/network/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/redis/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/socket-io/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/socket-io/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/template/single-page.md +0 -0
- /package/wiki/{references → extensions}/helpers/uid/index.md +0 -0
- /package/wiki/{references → extensions}/helpers/websocket/api.md +0 -0
- /package/wiki/{references → extensions}/helpers/worker-thread/index.md +0 -0
- /package/wiki/{references → extensions}/src-details/mcp-server.md +0 -0
|
@@ -0,0 +1,639 @@
|
|
|
1
|
+
# Kafka
|
|
2
|
+
|
|
3
|
+
Apache Kafka event streaming with producer, consumer, admin, and schema registry helpers. Built on [`@platformatic/kafka`](https://github.com/platformatic/kafka) v1.30.0 -- a pure TypeScript Kafka client with zero native dependencies.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The Kafka module provides four helper classes built on a shared `BaseKafkaHelper` base:
|
|
8
|
+
|
|
9
|
+
| Class | Wraps | Use Case |
|
|
10
|
+
|-------|-------|----------|
|
|
11
|
+
| `KafkaProducerHelper` | `Producer` | Publish messages, transactions |
|
|
12
|
+
| `KafkaConsumerHelper` | `Consumer` | Consume messages with consumer groups, lag monitoring |
|
|
13
|
+
| `KafkaAdminHelper` | `Admin` | Manage topics, partitions, groups, ACLs, configs |
|
|
14
|
+
| `KafkaSchemaRegistryHelper` | `ConfluentSchemaRegistry` | Schema validation and auto ser/deser |
|
|
15
|
+
|
|
16
|
+
All helpers (except schema registry) extend `BaseKafkaHelper` which provides:
|
|
17
|
+
|
|
18
|
+
- **Scoped logging** via `BaseHelper` (Winston with daily rotation)
|
|
19
|
+
- **Health tracking** -- `isHealthy()`, `isReady()`, `getHealthStatus()`
|
|
20
|
+
- **Broker event callbacks** -- `onBrokerConnect`, `onBrokerDisconnect`
|
|
21
|
+
- **Broker failure tracking** -- automatic `configureBrokerFailed()` sets status to `'disconnected'`
|
|
22
|
+
- **Graceful shutdown** -- timeout-based with force fallback
|
|
23
|
+
- **Sensible defaults** via `KafkaDefaults` constants
|
|
24
|
+
- **Factory pattern** via `newInstance()` static method
|
|
25
|
+
|
|
26
|
+
Use `getProducer()`, `getConsumer()`, or `getAdmin()` to access the full underlying `@platformatic/kafka` API directly.
|
|
27
|
+
|
|
28
|
+
### Import Path
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// Helpers & constants (via subpath export)
|
|
32
|
+
import {
|
|
33
|
+
KafkaProducerHelper,
|
|
34
|
+
KafkaConsumerHelper,
|
|
35
|
+
KafkaAdminHelper,
|
|
36
|
+
KafkaSchemaRegistryHelper,
|
|
37
|
+
BaseKafkaHelper,
|
|
38
|
+
KafkaDefaults,
|
|
39
|
+
KafkaAcks,
|
|
40
|
+
KafkaGroupProtocol,
|
|
41
|
+
KafkaHealthStatuses,
|
|
42
|
+
KafkaClientEvents,
|
|
43
|
+
} from '@venizia/ignis-helpers/kafka';
|
|
44
|
+
|
|
45
|
+
// Types
|
|
46
|
+
import type {
|
|
47
|
+
IKafkaConnectionOptions,
|
|
48
|
+
IKafkaProducerOptions,
|
|
49
|
+
IKafkaConsumerOptions,
|
|
50
|
+
IKafkaAdminOptions,
|
|
51
|
+
IKafkaConsumeStartOptions,
|
|
52
|
+
IKafkaSchemaRegistryOptions,
|
|
53
|
+
IKafkaTransactionContext,
|
|
54
|
+
IKafkaBaseOptions,
|
|
55
|
+
TKafkaAcks,
|
|
56
|
+
TKafkaGroupProtocol,
|
|
57
|
+
TKafkaHealthStatus,
|
|
58
|
+
TKafkaBrokerEventCallback,
|
|
59
|
+
TKafkaMessageCallback,
|
|
60
|
+
TKafkaMessageDoneCallback,
|
|
61
|
+
TKafkaMessageErrorCallback,
|
|
62
|
+
TKafkaGroupJoinCallback,
|
|
63
|
+
TKafkaGroupLeaveCallback,
|
|
64
|
+
TKafkaGroupRebalanceCallback,
|
|
65
|
+
TKafkaHeartbeatErrorCallback,
|
|
66
|
+
TKafkaLagCallback,
|
|
67
|
+
TKafkaLagErrorCallback,
|
|
68
|
+
TKafkaTransactionCallback,
|
|
69
|
+
} from '@venizia/ignis-helpers/kafka';
|
|
70
|
+
|
|
71
|
+
// @platformatic/kafka (direct usage)
|
|
72
|
+
import {
|
|
73
|
+
Producer, Consumer, Admin, MessagesStream,
|
|
74
|
+
stringSerializers, stringDeserializers,
|
|
75
|
+
stringSerializer, stringDeserializer,
|
|
76
|
+
jsonSerializer, jsonDeserializer,
|
|
77
|
+
serializersFrom, deserializersFrom,
|
|
78
|
+
} from '@platformatic/kafka';
|
|
79
|
+
|
|
80
|
+
import type {
|
|
81
|
+
Message, MessageToProduce,
|
|
82
|
+
SendOptions, ConsumeOptions,
|
|
83
|
+
Serializers, Deserializers,
|
|
84
|
+
SASLOptions, ConnectionOptions,
|
|
85
|
+
} from '@platformatic/kafka';
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
> [!NOTE]
|
|
89
|
+
> Kafka helpers are **not** re-exported from the main `@venizia/ignis-helpers` entry point. You must use the `@venizia/ignis-helpers/kafka` subpath import. This keeps the optional `@platformatic/kafka` peer dependency isolated for tree-shaking.
|
|
90
|
+
|
|
91
|
+
### Installation
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
bun add @platformatic/kafka
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Architecture
|
|
98
|
+
|
|
99
|
+
### Class Hierarchy
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
BaseHelper (scoped logging, identifier)
|
|
103
|
+
+-- BaseKafkaHelper<TClient> (health tracking, broker events, graceful shutdown)
|
|
104
|
+
| +-- KafkaProducerHelper<K,V,HK,HV>
|
|
105
|
+
| +-- KafkaConsumerHelper<K,V,HK,HV>
|
|
106
|
+
| +-- KafkaAdminHelper
|
|
107
|
+
|
|
|
108
|
+
+-- KafkaSchemaRegistryHelper<K,V,HK,HV> (no broker connection)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### BaseKafkaHelper
|
|
112
|
+
|
|
113
|
+
All Kafka helpers (except schema registry) extend `BaseKafkaHelper<TClient>`, which provides:
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
abstract class BaseKafkaHelper<TClient extends Base<BaseOptions>> extends BaseHelper {
|
|
117
|
+
// Health
|
|
118
|
+
isHealthy(): boolean; // healthStatus === 'connected'
|
|
119
|
+
isReady(): boolean; // healthStatus === 'connected' (consumer overrides: + isActive())
|
|
120
|
+
getHealthStatus(): TKafkaHealthStatus; // 'connected' | 'disconnected' | 'unknown'
|
|
121
|
+
|
|
122
|
+
// Shutdown (used by subclasses)
|
|
123
|
+
protected closeClient(): Promise<void>;
|
|
124
|
+
protected gracefulCloseClient(): Promise<void>; // races closeClient vs shutdownTimeout
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Health status transitions automatically via broker events:
|
|
129
|
+
- `client:broker:connect` -> `'connected'`
|
|
130
|
+
- `client:broker:disconnect` -> `'disconnected'`
|
|
131
|
+
- `client:broker:failed` -> `'disconnected'`
|
|
132
|
+
- `close()` -> `'disconnected'`
|
|
133
|
+
|
|
134
|
+
## Connection Options
|
|
135
|
+
|
|
136
|
+
All three helpers share a common base interface `IKafkaConnectionOptions` which extends `@platformatic/kafka`'s `ConnectionOptions`.
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
interface IKafkaConnectionOptions extends ConnectionOptions {
|
|
140
|
+
bootstrapBrokers: string[];
|
|
141
|
+
clientId: string;
|
|
142
|
+
retries?: number; // Default: 3
|
|
143
|
+
retryDelay?: number; // Default: 1000ms
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Full Options Table
|
|
148
|
+
|
|
149
|
+
| Option | Type | Default | Description |
|
|
150
|
+
|--------|------|---------|-------------|
|
|
151
|
+
| `bootstrapBrokers` | `string[]` | -- | Kafka broker addresses (`host:port`). **Required** |
|
|
152
|
+
| `clientId` | `string` | -- | Unique client identifier. **Required** |
|
|
153
|
+
| `retries` | `number` | `3` | Number of connection retries before failing |
|
|
154
|
+
| `retryDelay` | `number` | `1000` | Delay between retries in milliseconds |
|
|
155
|
+
| `sasl` | `SASLOptions` | -- | SASL authentication configuration |
|
|
156
|
+
| `tls` | `TLSConnectionOptions` | -- | TLS/SSL connection options |
|
|
157
|
+
| `ssl` | `TLSConnectionOptions` | -- | Alias for `tls` |
|
|
158
|
+
| `connectTimeout` | `number` | -- | TCP connection timeout in milliseconds |
|
|
159
|
+
| `requestTimeout` | `number` | -- | Kafka request timeout in milliseconds |
|
|
160
|
+
|
|
161
|
+
### Shared Helper Options
|
|
162
|
+
|
|
163
|
+
These options are available on all three helpers (`IKafkaProducerOptions`, `IKafkaConsumerOptions`, `IKafkaAdminOptions`):
|
|
164
|
+
|
|
165
|
+
| Option | Type | Default | Description |
|
|
166
|
+
|--------|------|---------|-------------|
|
|
167
|
+
| `identifier` | `string` | `'kafka-{type}'` | Scoped logging identifier |
|
|
168
|
+
| `shutdownTimeout` | `number` | `30000` | Graceful shutdown timeout in ms |
|
|
169
|
+
| `onBrokerConnect` | `TKafkaBrokerEventCallback` | -- | Called when broker connects |
|
|
170
|
+
| `onBrokerDisconnect` | `TKafkaBrokerEventCallback` | -- | Called when broker disconnects |
|
|
171
|
+
|
|
172
|
+
### SASL Authentication
|
|
173
|
+
|
|
174
|
+
`@platformatic/kafka` supports five SASL mechanisms:
|
|
175
|
+
|
|
176
|
+
| Mechanism | Use Case |
|
|
177
|
+
|-----------|----------|
|
|
178
|
+
| `PLAIN` | Simple username/password (use with TLS in production) |
|
|
179
|
+
| `SCRAM-SHA-256` | Challenge-response, password never sent in plaintext |
|
|
180
|
+
| `SCRAM-SHA-512` | Same as SHA-256 with stronger hash |
|
|
181
|
+
| `OAUTHBEARER` | Token-based (Azure Event Hubs, Confluent Cloud) |
|
|
182
|
+
| `GSSAPI` | Kerberos authentication |
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
interface SASLOptions {
|
|
186
|
+
mechanism: 'PLAIN' | 'SCRAM-SHA-256' | 'SCRAM-SHA-512' | 'OAUTHBEARER' | 'GSSAPI';
|
|
187
|
+
username?: string | CredentialProvider;
|
|
188
|
+
password?: string | CredentialProvider;
|
|
189
|
+
token?: string | CredentialProvider;
|
|
190
|
+
oauthBearerExtensions?: Record<string, string> | CredentialProvider<Record<string, string>>;
|
|
191
|
+
authenticate?: SASLCustomAuthenticator;
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### SCRAM-SHA-512 Example
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const helper = KafkaConsumerHelper.newInstance({
|
|
199
|
+
bootstrapBrokers: ['broker1:9092', 'broker2:9092', 'broker3:9092'],
|
|
200
|
+
clientId: 'my-consumer',
|
|
201
|
+
groupId: 'my-group',
|
|
202
|
+
sasl: {
|
|
203
|
+
mechanism: 'SCRAM-SHA-512',
|
|
204
|
+
username: 'kafka-user',
|
|
205
|
+
password: 'kafka-password',
|
|
206
|
+
},
|
|
207
|
+
connectTimeout: 30_000,
|
|
208
|
+
requestTimeout: 30_000,
|
|
209
|
+
onBrokerConnect: ({ broker }) => console.log(`Connected to ${broker.host}:${broker.port}`),
|
|
210
|
+
});
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### OAUTHBEARER Example
|
|
214
|
+
|
|
215
|
+
```typescript
|
|
216
|
+
const helper = KafkaProducerHelper.newInstance({
|
|
217
|
+
bootstrapBrokers: ['pkc-xxxxx.us-west-2.aws.confluent.cloud:9092'],
|
|
218
|
+
clientId: 'my-producer',
|
|
219
|
+
sasl: {
|
|
220
|
+
mechanism: 'OAUTHBEARER',
|
|
221
|
+
token: async () => {
|
|
222
|
+
const response = await fetch('https://auth.example.com/token', { method: 'POST' });
|
|
223
|
+
const { access_token } = await response.json();
|
|
224
|
+
return access_token;
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
tls: true,
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
#### TLS Without SASL
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
const helper = KafkaProducerHelper.newInstance({
|
|
235
|
+
bootstrapBrokers: ['broker:9093'],
|
|
236
|
+
clientId: 'my-producer',
|
|
237
|
+
tls: {
|
|
238
|
+
ca: fs.readFileSync('/path/to/ca.pem'),
|
|
239
|
+
cert: fs.readFileSync('/path/to/client-cert.pem'),
|
|
240
|
+
key: fs.readFileSync('/path/to/client-key.pem'),
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## Serialization & Deserialization
|
|
246
|
+
|
|
247
|
+
`@platformatic/kafka`'s default wire format is `Buffer`. The helpers default generic types to `string` (matching common usage), but you must provide serializers/deserializers explicitly.
|
|
248
|
+
|
|
249
|
+
### Built-in Serializers
|
|
250
|
+
|
|
251
|
+
| Export | Type | Description |
|
|
252
|
+
|--------|------|-------------|
|
|
253
|
+
| `stringSerializer` | `Serializer<string>` | `string -> Buffer` (UTF-8) |
|
|
254
|
+
| `stringDeserializer` | `Deserializer<string>` | `Buffer -> string` (UTF-8) |
|
|
255
|
+
| `jsonSerializer` | `Serializer<T>` | `object -> Buffer` (JSON.stringify + UTF-8) |
|
|
256
|
+
| `jsonDeserializer` | `Deserializer<T>` | `Buffer -> object` (UTF-8 + JSON.parse) |
|
|
257
|
+
| `stringSerializers` | `Serializers<string, string, string, string>` | All four positions as string |
|
|
258
|
+
| `stringDeserializers` | `Deserializers<string, string, string, string>` | All four positions as string |
|
|
259
|
+
|
|
260
|
+
### Helper Functions
|
|
261
|
+
|
|
262
|
+
| Export | Signature | Description |
|
|
263
|
+
|--------|-----------|-------------|
|
|
264
|
+
| `serializersFrom(s)` | `<T>(s: Serializer<T>) => Serializers<T, T, T, T>` | Create full serializers from a single serializer |
|
|
265
|
+
| `deserializersFrom(d)` | `<T>(d: Deserializer<T>) => Deserializers<T, T, T, T>` | Create full deserializers from a single deserializer |
|
|
266
|
+
|
|
267
|
+
### String Serialization
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
import { stringSerializers, stringDeserializers } from '@platformatic/kafka';
|
|
271
|
+
|
|
272
|
+
const producer = KafkaProducerHelper.newInstance({
|
|
273
|
+
bootstrapBrokers: ['localhost:9092'],
|
|
274
|
+
clientId: 'my-producer',
|
|
275
|
+
serializers: stringSerializers,
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
const consumer = KafkaConsumerHelper.newInstance({
|
|
279
|
+
bootstrapBrokers: ['localhost:9092'],
|
|
280
|
+
clientId: 'my-consumer',
|
|
281
|
+
groupId: 'my-group',
|
|
282
|
+
deserializers: stringDeserializers,
|
|
283
|
+
onMessage: async ({ message }) => {
|
|
284
|
+
console.log(message.key, message.value); // both strings
|
|
285
|
+
},
|
|
286
|
+
});
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### JSON Serialization
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
import {
|
|
293
|
+
jsonSerializer, jsonDeserializer,
|
|
294
|
+
stringSerializer, stringDeserializer,
|
|
295
|
+
serializersFrom, deserializersFrom,
|
|
296
|
+
} from '@platformatic/kafka';
|
|
297
|
+
|
|
298
|
+
const producer = KafkaProducerHelper.newInstance({
|
|
299
|
+
bootstrapBrokers: ['localhost:9092'],
|
|
300
|
+
clientId: 'my-producer',
|
|
301
|
+
serializers: { ...serializersFrom(jsonSerializer), key: stringSerializer },
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
await producer.getProducer().send({
|
|
305
|
+
messages: [{
|
|
306
|
+
topic: 'orders',
|
|
307
|
+
key: 'order-123',
|
|
308
|
+
value: { id: '123', status: 'created', amount: 99 },
|
|
309
|
+
}],
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
const consumer = KafkaConsumerHelper.newInstance({
|
|
313
|
+
bootstrapBrokers: ['localhost:9092'],
|
|
314
|
+
clientId: 'my-consumer',
|
|
315
|
+
groupId: 'my-group',
|
|
316
|
+
deserializers: { ...deserializersFrom(jsonDeserializer), key: stringDeserializer },
|
|
317
|
+
onMessage: async ({ message }) => {
|
|
318
|
+
console.log(message.value.id, message.value.status); // typed object
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Schema Registry Serialization
|
|
324
|
+
|
|
325
|
+
For schema-validated serialization (Avro, Protobuf, JSON Schema), use the schema registry helper:
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
const registry = KafkaSchemaRegistryHelper.newInstance({
|
|
329
|
+
url: 'http://localhost:8081',
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
const producer = KafkaProducerHelper.newInstance({
|
|
333
|
+
bootstrapBrokers: ['localhost:9092'],
|
|
334
|
+
clientId: 'my-producer',
|
|
335
|
+
registry: registry.getRegistry(),
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
const consumer = KafkaConsumerHelper.newInstance({
|
|
339
|
+
bootstrapBrokers: ['localhost:9092'],
|
|
340
|
+
clientId: 'my-consumer',
|
|
341
|
+
groupId: 'my-group',
|
|
342
|
+
registry: registry.getRegistry(),
|
|
343
|
+
onMessage: async ({ message }) => {
|
|
344
|
+
// message.value is auto-deserialized using registered schema
|
|
345
|
+
},
|
|
346
|
+
});
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
See **[Schema Registry](./schema-registry)** for full documentation.
|
|
350
|
+
|
|
351
|
+
## Generic Type Parameters
|
|
352
|
+
|
|
353
|
+
All helpers (and their option interfaces) support generic type parameters controlling the serialization types:
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
class KafkaProducerHelper<
|
|
357
|
+
KeyType = string,
|
|
358
|
+
ValueType = string,
|
|
359
|
+
HeaderKeyType = string,
|
|
360
|
+
HeaderValueType = string,
|
|
361
|
+
>
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
| Parameter | Default | Description |
|
|
365
|
+
|-----------|---------|-------------|
|
|
366
|
+
| `KeyType` | `string` | Message key type after serialization/deserialization |
|
|
367
|
+
| `ValueType` | `string` | Message value type after serialization/deserialization |
|
|
368
|
+
| `HeaderKeyType` | `string` | Header key type |
|
|
369
|
+
| `HeaderValueType` | `string` | Header value type |
|
|
370
|
+
|
|
371
|
+
> [!NOTE]
|
|
372
|
+
> `@platformatic/kafka` defaults to `Buffer` for all four positions. The helpers default to `string` which is more common for application code. If you don't pass serializers, your messages will be sent/received as `Buffer`.
|
|
373
|
+
|
|
374
|
+
```typescript
|
|
375
|
+
// Default: string types (most common)
|
|
376
|
+
const helper = KafkaProducerHelper.newInstance({ ... });
|
|
377
|
+
|
|
378
|
+
// Custom: string keys, JSON object values
|
|
379
|
+
const helper = KafkaProducerHelper.newInstance<string, MyEvent, string, string>({
|
|
380
|
+
serializers: { ...serializersFrom(jsonSerializer), key: stringSerializer },
|
|
381
|
+
...
|
|
382
|
+
});
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
## Constants
|
|
386
|
+
|
|
387
|
+
### KafkaDefaults
|
|
388
|
+
|
|
389
|
+
Centralized default values used by all helpers.
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
import { KafkaDefaults } from '@venizia/ignis-helpers/kafka';
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
| Constant | Value | Scope | Description |
|
|
396
|
+
|----------|-------|-------|-------------|
|
|
397
|
+
| `RETRIES` | `3` | Shared | Connection retry count |
|
|
398
|
+
| `RETRY_DELAY` | `1000` | Shared | Retry delay in ms |
|
|
399
|
+
| `SHUTDOWN_TIMEOUT` | `30000` | Shared | Graceful shutdown timeout in ms |
|
|
400
|
+
| `STRICT` | `true` | Producer | Fail on unknown topics |
|
|
401
|
+
| `AUTOCREATE_TOPICS` | `false` | Producer | Auto-create topics on produce |
|
|
402
|
+
| `AUTOCOMMIT` | `false` | Consumer | Auto-commit offsets |
|
|
403
|
+
| `SESSION_TIMEOUT` | `30000` | Consumer | Session timeout in ms |
|
|
404
|
+
| `HEARTBEAT_INTERVAL` | `3000` | Consumer | Heartbeat interval in ms |
|
|
405
|
+
| `HIGH_WATER_MARK` | `1024` | Consumer | Stream buffer size (messages) |
|
|
406
|
+
| `MIN_BYTES` | `1` | Consumer | Min bytes per fetch |
|
|
407
|
+
| `METADATA_MAX_AGE` | `300000` | Consumer | Metadata cache TTL in ms |
|
|
408
|
+
| `GROUP_PROTOCOL` | `'classic'` | Consumer | Default group protocol |
|
|
409
|
+
| `CONSUME_MODE` | `'committed'` | Consumer | Default consume mode |
|
|
410
|
+
| `CONSUME_FALLBACK_MODE` | `'latest'` | Consumer | Default consume fallback mode |
|
|
411
|
+
| `LAG_MONITOR_INTERVAL` | `30000` | Consumer | Lag monitoring poll interval in ms |
|
|
412
|
+
|
|
413
|
+
### KafkaHealthStatuses
|
|
414
|
+
|
|
415
|
+
Health status values used by all Kafka helpers.
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
import { KafkaHealthStatuses } from '@venizia/ignis-helpers/kafka';
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
| Constant | Value | Description |
|
|
422
|
+
|----------|-------|-------------|
|
|
423
|
+
| `CONNECTED` | `'connected'` | Broker connection established |
|
|
424
|
+
| `DISCONNECTED` | `'disconnected'` | Broker connection lost or closed |
|
|
425
|
+
| `UNKNOWN` | `'unknown'` | Initial state before first broker event |
|
|
426
|
+
|
|
427
|
+
### KafkaClientEvents
|
|
428
|
+
|
|
429
|
+
Event name constants for `@platformatic/kafka` event emitters.
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
import { KafkaClientEvents } from '@venizia/ignis-helpers/kafka';
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
| Constant | Value | Scope |
|
|
436
|
+
|----------|-------|-------|
|
|
437
|
+
| `BROKER_CONNECT` | `'client:broker:connect'` | All clients |
|
|
438
|
+
| `BROKER_DISCONNECT` | `'client:broker:disconnect'` | All clients |
|
|
439
|
+
| `BROKER_FAILED` | `'client:broker:failed'` | All clients |
|
|
440
|
+
| `CONSUMER_GROUP_JOIN` | `'consumer:group:join'` | Consumer |
|
|
441
|
+
| `CONSUMER_GROUP_LEAVE` | `'consumer:group:leave'` | Consumer |
|
|
442
|
+
| `CONSUMER_GROUP_REBALANCE` | `'consumer:group:rebalance'` | Consumer |
|
|
443
|
+
| `CONSUMER_HEARTBEAT_ERROR` | `'consumer:heartbeat:error'` | Consumer |
|
|
444
|
+
| `CONSUMER_LAG` | `'consumer:lag'` | Consumer |
|
|
445
|
+
| `CONSUMER_LAG_ERROR` | `'consumer:lag:error'` | Consumer |
|
|
446
|
+
| `STREAM_DATA` | `'data'` | Stream |
|
|
447
|
+
| `STREAM_ERROR` | `'error'` | Stream |
|
|
448
|
+
|
|
449
|
+
### KafkaAcks
|
|
450
|
+
|
|
451
|
+
Producer acknowledgment levels.
|
|
452
|
+
|
|
453
|
+
```typescript
|
|
454
|
+
import { KafkaAcks } from '@venizia/ignis-helpers/kafka';
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
| Constant | Value | Description | Trade-off |
|
|
458
|
+
|----------|-------|-------------|-----------|
|
|
459
|
+
| `NONE` | `0` | No acknowledgment -- fire-and-forget | Fastest, no durability guarantee |
|
|
460
|
+
| `LEADER` | `1` | Leader broker acknowledges | Fast, leader-durable |
|
|
461
|
+
| `ALL` | `-1` | All in-sync replicas acknowledge | Slowest, fully durable |
|
|
462
|
+
|
|
463
|
+
### KafkaGroupProtocol
|
|
464
|
+
|
|
465
|
+
Consumer group protocol versions.
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
import { KafkaGroupProtocol } from '@venizia/ignis-helpers/kafka';
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
| Constant | Value | Description |
|
|
472
|
+
|----------|-------|-------------|
|
|
473
|
+
| `CLASSIC` | `'classic'` | Classic consumer group protocol (default, all Kafka versions) |
|
|
474
|
+
| `CONSUMER` | `'consumer'` | New consumer group protocol -- KIP-848 (Kafka 3.7+) |
|
|
475
|
+
|
|
476
|
+
### Derived Types
|
|
477
|
+
|
|
478
|
+
```typescript
|
|
479
|
+
import type { TKafkaAcks, TKafkaGroupProtocol, TKafkaHealthStatus } from '@venizia/ignis-helpers/kafka';
|
|
480
|
+
|
|
481
|
+
// TKafkaAcks = 0 | 1 | -1
|
|
482
|
+
// TKafkaGroupProtocol = 'classic' | 'consumer'
|
|
483
|
+
// TKafkaHealthStatus = 'connected' | 'disconnected' | 'unknown'
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
## Compression
|
|
487
|
+
|
|
488
|
+
`@platformatic/kafka` supports five compression algorithms:
|
|
489
|
+
|
|
490
|
+
| Algorithm | Value | Description |
|
|
491
|
+
|-----------|-------|-------------|
|
|
492
|
+
| None | `'none'` | No compression (default) |
|
|
493
|
+
| GZIP | `'gzip'` | Good compression ratio, moderate CPU |
|
|
494
|
+
| Snappy | `'snappy'` | Fast compression, moderate ratio |
|
|
495
|
+
| LZ4 | `'lz4'` | Very fast, good for high-throughput |
|
|
496
|
+
| Zstandard | `'zstd'` | Best ratio, moderate CPU |
|
|
497
|
+
|
|
498
|
+
```typescript
|
|
499
|
+
const helper = KafkaProducerHelper.newInstance({
|
|
500
|
+
bootstrapBrokers: ['localhost:9092'],
|
|
501
|
+
clientId: 'my-producer',
|
|
502
|
+
serializers: stringSerializers,
|
|
503
|
+
compression: 'zstd',
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
// Override per-send
|
|
507
|
+
await helper.getProducer().send({
|
|
508
|
+
messages: [{ topic: 'logs', key: 'l1', value: largePayload }],
|
|
509
|
+
compression: 'lz4',
|
|
510
|
+
});
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
## Quick Usage Comparison
|
|
514
|
+
|
|
515
|
+
### Construction
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
// Admin
|
|
519
|
+
const admin = KafkaAdminHelper.newInstance({
|
|
520
|
+
bootstrapBrokers: ['127.0.0.1:29092'],
|
|
521
|
+
clientId: 'my-admin',
|
|
522
|
+
onBrokerConnect: ({ broker }) => console.log(`Connected to ${broker.host}`),
|
|
523
|
+
onBrokerDisconnect: ({ broker }) => console.log(`Disconnected from ${broker.host}`),
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
// Producer
|
|
527
|
+
const producer = KafkaProducerHelper.newInstance({
|
|
528
|
+
bootstrapBrokers: ['127.0.0.1:29092'],
|
|
529
|
+
clientId: 'my-producer',
|
|
530
|
+
acks: -1,
|
|
531
|
+
idempotent: true,
|
|
532
|
+
transactionalId: 'my-tx',
|
|
533
|
+
onBrokerConnect: ({ broker }) => console.log(`Connected to ${broker.host}`),
|
|
534
|
+
onBrokerDisconnect: ({ broker }) => console.log(`Disconnected from ${broker.host}`),
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
// Consumer
|
|
538
|
+
const consumer = KafkaConsumerHelper.newInstance({
|
|
539
|
+
bootstrapBrokers: ['127.0.0.1:29092'],
|
|
540
|
+
clientId: 'my-consumer',
|
|
541
|
+
groupId: 'my-group',
|
|
542
|
+
onBrokerConnect: ({ broker }) => console.log(`Connected to ${broker.host}`),
|
|
543
|
+
onBrokerDisconnect: ({ broker }) => console.log(`Disconnected from ${broker.host}`),
|
|
544
|
+
onMessage: async ({ message }) => {
|
|
545
|
+
console.log('Received:', message.value);
|
|
546
|
+
await message.commit();
|
|
547
|
+
},
|
|
548
|
+
onMessageDone: ({ message }) => console.log('Done:', message.key),
|
|
549
|
+
onMessageError: ({ error, message }) => console.error('Error:', error),
|
|
550
|
+
onGroupJoin: ({ groupId, memberId }) => console.log(`Joined ${groupId}`),
|
|
551
|
+
onGroupLeave: ({ groupId }) => console.log(`Left ${groupId}`),
|
|
552
|
+
onGroupRebalance: ({ groupId }) => console.log(`Rebalance ${groupId}`),
|
|
553
|
+
onHeartbeatError: ({ error }) => console.error('Heartbeat:', error),
|
|
554
|
+
onLag: ({ lag }) => console.log('Lag:', lag),
|
|
555
|
+
onLagError: ({ error }) => console.error('Lag error:', error),
|
|
556
|
+
});
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
### Core Operations
|
|
560
|
+
|
|
561
|
+
| Admin | Producer | Consumer |
|
|
562
|
+
|-------|----------|----------|
|
|
563
|
+
| `admin.getAdmin()` | `producer.getProducer()` | `consumer.getConsumer()` |
|
|
564
|
+
| -- | `producer.getProducer().send(...)` | `await consumer.start({ topics: ['t1'] })` |
|
|
565
|
+
| -- | `await producer.runInTransaction(async ({ send, addConsumer, addOffset }) => { ... })` | `consumer.startLagMonitoring({ topics: ['t1'], interval: 10_000 })` |
|
|
566
|
+
| -- | -- | `consumer.stopLagMonitoring()` |
|
|
567
|
+
| -- | -- | `consumer.getStream()` |
|
|
568
|
+
|
|
569
|
+
### Health Checks
|
|
570
|
+
|
|
571
|
+
```typescript
|
|
572
|
+
// All three -- identical API
|
|
573
|
+
helper.isHealthy(); // true when broker connected
|
|
574
|
+
helper.isReady(); // Admin/Producer: same as isHealthy()
|
|
575
|
+
// Consumer: isHealthy() + consumer.isActive()
|
|
576
|
+
helper.getHealthStatus(); // 'connected' | 'disconnected' | 'unknown'
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### Shutdown
|
|
580
|
+
|
|
581
|
+
```typescript
|
|
582
|
+
// All three -- identical API
|
|
583
|
+
await helper.close(); // graceful (timeout -> force fallback)
|
|
584
|
+
await helper.close({ isForce: true }); // immediate force close
|
|
585
|
+
```
|
|
586
|
+
|
|
587
|
+
### With Schema Registry
|
|
588
|
+
|
|
589
|
+
```typescript
|
|
590
|
+
const registry = KafkaSchemaRegistryHelper.newInstance({ url: 'http://localhost:8081' });
|
|
591
|
+
|
|
592
|
+
const producer = KafkaProducerHelper.newInstance({
|
|
593
|
+
...,
|
|
594
|
+
registry: registry.getRegistry(),
|
|
595
|
+
// or use registry.getSerializers() for manual serializer config
|
|
596
|
+
});
|
|
597
|
+
|
|
598
|
+
const consumer = KafkaConsumerHelper.newInstance({
|
|
599
|
+
...,
|
|
600
|
+
registry: registry.getRegistry(),
|
|
601
|
+
// or use registry.getDeserializers() for manual deserializer config
|
|
602
|
+
});
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
### Transaction (Producer Only)
|
|
606
|
+
|
|
607
|
+
```typescript
|
|
608
|
+
const result = await producer.runInTransaction(async ({ send, addConsumer, addOffset }) => {
|
|
609
|
+
// Send messages within transaction
|
|
610
|
+
const result = await send({
|
|
611
|
+
messages: [{ topic: 'orders', key: 'o1', value: '{"status":"created"}' }],
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
// Optionally add consumer for exactly-once semantics
|
|
615
|
+
await addConsumer(consumer.getConsumer());
|
|
616
|
+
await addOffset(message);
|
|
617
|
+
|
|
618
|
+
return result;
|
|
619
|
+
});
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
## Pages
|
|
623
|
+
|
|
624
|
+
- **[Producer](./producer)** -- Producer helper, transactions, and full `@platformatic/kafka` Producer API reference
|
|
625
|
+
- **[Consumer](./consumer)** -- Consumer helper, message callbacks, lag monitoring, and full Consumer API reference
|
|
626
|
+
- **[Admin](./admin)** -- Admin helper and full Admin API reference
|
|
627
|
+
- **[Schema Registry](./schema-registry)** -- Schema registry helper for Avro/Protobuf/JSON Schema validation
|
|
628
|
+
- **[Examples & Troubleshooting](./examples)** -- Complete examples, IoC integration, and troubleshooting guide
|
|
629
|
+
|
|
630
|
+
## See Also
|
|
631
|
+
|
|
632
|
+
- **Other Helpers:**
|
|
633
|
+
- [Queue Helper](../queue/) -- BullMQ, MQTT, and in-memory queues
|
|
634
|
+
- [Redis Helper](../redis/) -- Redis connection management
|
|
635
|
+
|
|
636
|
+
- **External Resources:**
|
|
637
|
+
- [@platformatic/kafka](https://github.com/platformatic/kafka) -- Underlying Kafka client library
|
|
638
|
+
- [Apache Kafka Documentation](https://kafka.apache.org/documentation/) -- Official Kafka docs
|
|
639
|
+
- [KIP-848](https://cwiki.apache.org/confluence/display/KAFKA/KIP-848) -- New consumer group protocol
|