sentinel-kafka-manager 1.0.2 → 1.0.4

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.
Files changed (2) hide show
  1. package/README.md +446 -467
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -27,6 +27,36 @@ In most services, Kafka setup gets repeated:
27
27
 
28
28
  `sentinel-kafka-manager` wraps those common tasks in one small class: `KafkaManager`.
29
29
 
30
+ ## Enterprise Features
31
+
32
+ This version now includes a stronger production baseline:
33
+
34
+ - config validation for client id, brokers, and broker discovery inputs
35
+ - shared producer, admin, and consumer lifecycle
36
+ - logger and metrics hooks
37
+ - standard message envelope publishing
38
+ - managed consumer runner with dead-letter topic support
39
+ - health snapshot reporting
40
+ - safer startup behavior for concurrent connections
41
+ - stable error codes and structured exception details
42
+
43
+ ## Recommended Usage Level
44
+
45
+ This package is now suitable as a shared internal Kafka module for SaaS microservices.
46
+
47
+ Recommended use:
48
+
49
+ - internal platform package for Node.js services
50
+ - event publishing with standard envelopes
51
+ - managed consumers with DLQ handling
52
+ - consistent service-layer success and error responses
53
+
54
+ Still recommended outside the package:
55
+
56
+ - automated unit and integration tests in the consuming service or platform repo
57
+ - schema validation for business payloads when required by your organization
58
+ - organization-specific tracing, alerting, and compliance rules
59
+
30
60
  ## Installation
31
61
 
32
62
  Install from npm:
@@ -48,321 +78,63 @@ npm run build
48
78
  - Kafka cluster reachable from the service
49
79
  - `kafkajs` is included automatically as a dependency of this package
50
80
 
51
- ## Create A Kafka Server With This Repo
52
-
53
- This repository already includes a full local Kafka server setup in [docker-compose.yml](/var/www/html/matrix-project/sentinel-kafka-manager/docker-compose.yml) and sample environment values in [.env.local.example](/var/www/html/matrix-project/sentinel-kafka-manager/.env.local.example).
54
-
55
- The stack includes:
56
-
57
- - 3 KRaft controllers
58
- - 3 Kafka brokers
59
- - 1 Kafka UI instance
60
-
61
- ### 1. Create your `.env`
62
-
63
- Copy the example file:
64
-
65
- ```bash
66
- cp .env.local.example .env
67
- ```
68
-
69
- If you want a standard localhost setup, the example values are already suitable.
70
-
71
- ### 2. Start the Kafka cluster
72
-
73
- ```bash
74
- docker compose --env-file .env up -d
75
- ```
76
-
77
- This creates:
78
-
79
- - controller quorum on port `9093` inside Docker
80
- - internal broker traffic on port `9092` inside Docker
81
- - host-accessible broker ports `29092`, `39092`, and `49092`
82
- - Kafka UI on `127.0.0.1:5001`
83
-
84
- ### 3. Stop the Kafka cluster
85
-
86
- ```bash
87
- docker compose --env-file .env down
88
- ```
89
-
90
- To also remove persisted Kafka data volumes:
91
-
92
- ```bash
93
- docker compose --env-file .env down -v
94
- ```
95
-
96
- ### 4. Check container status
97
-
98
- ```bash
99
- docker compose --env-file .env ps
100
- ```
101
-
102
- ### 5. Current broker endpoints
103
-
104
- For applications running on your host machine:
105
-
106
- ```text
107
- localhost:29092
108
- localhost:39092
109
- localhost:49092
110
- ```
111
-
112
- For applications running inside Docker on the same Compose network:
113
-
114
- ```text
115
- broker-1:9092
116
- broker-2:9092
117
- broker-3:9092
118
- ```
119
-
120
- Important:
121
-
122
- - application clients must connect to brokers, not controllers
123
- - controllers are internal cluster metadata nodes only
124
- - `mode: 'external'` is for host-based apps
125
- - `mode: 'internal'` is for Dockerized apps on the same network
126
-
127
- ## Kafka UI Usage
128
-
129
- The Docker stack also starts Kafka UI for cluster inspection.
130
-
131
- ### Open the UI
132
-
133
- Visit:
134
-
135
- ```text
136
- http://127.0.0.1:5001
137
- ```
138
-
139
- ### Login credentials
140
-
141
- By default, the UI uses the credentials from `.env`:
142
-
143
- ```env
144
- KAFKA_UI_USERNAME=admin
145
- KAFKA_UI_PASSWORD=Admin@007
146
- ```
147
-
148
- ### What the UI connects to
149
-
150
- Kafka UI is preconfigured in `docker-compose.yml` to use all three brokers:
151
-
152
- ```text
153
- broker-1:9092,broker-2:9092,broker-3:9092
154
- ```
155
-
156
- The cluster name shown in the UI comes from:
157
-
158
- ```env
159
- KAFKA_UI_CLUSTER_NAME=Project Omni Enterprise Kafka
160
- ```
161
-
162
- ### What you can do in the UI
163
-
164
- - view brokers and cluster health
165
- - inspect topics and partitions
166
- - browse messages
167
- - inspect consumer groups
168
- - check offsets and lag
169
-
170
- ### Read-only mode
171
-
172
- The example `.env` sets:
173
-
174
- ```env
175
- KAFKA_UI_READONLY=true
176
- ```
177
-
178
- That means the UI is intended for safe inspection only.
179
-
180
- If you want to create topics or make changes from the UI, change it to:
181
-
182
- ```env
183
- KAFKA_UI_READONLY=false
184
- ```
185
-
186
- Then restart the stack:
187
-
188
- ```bash
189
- docker compose --env-file .env up -d
190
- ```
191
-
192
- ### Typical UI flow
193
-
194
- 1. Start the Docker stack.
195
- 2. Open `http://127.0.0.1:5001`.
196
- 3. Log in with `KAFKA_UI_USERNAME` and `KAFKA_UI_PASSWORD`.
197
- 4. Open the configured cluster.
198
- 5. Go to Topics, Consumer Groups, or Brokers as needed.
199
-
200
- ## Docker Compose And `.env` Reference
201
-
202
- This project does not use a separate `Dockerfile` for Kafka. The Kafka server is created from `docker-compose.yml` and environment values from `.env`.
203
-
204
- ### Core Kafka image and cluster identity
205
-
206
- ```env
207
- KAFKA_IMAGE=confluentinc/cp-kafka:7.6.6
208
- KAFKA_CLUSTER_ID=MkU3OEVBNTcwNTJENDM2Qk
209
- KAFKA_RESTART_POLICY=unless-stopped
210
- KAFKA_STOP_GRACE_PERIOD=60s
211
- KAFKA_NETWORK_NAME=kafka-network
212
- ```
213
-
214
- - `KAFKA_IMAGE`: Kafka container image used by controllers and brokers
215
- - `KAFKA_CLUSTER_ID`: shared KRaft cluster id for all nodes
216
- - `KAFKA_NETWORK_NAME`: Docker network name used by the full stack
217
-
218
- ### Controller quorum settings
219
-
220
- ```env
221
- KAFKA_CONTROLLER_PORT=9093
222
- KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER
223
- KAFKA_CONTROLLER_QUORUM_VOTERS=1@controller-1:9093,2@controller-2:9093,3@controller-3:9093
224
- ```
225
-
226
- - controllers run only inside Docker
227
- - apps should never use these controller addresses as Kafka client brokers
228
-
229
- ### Broker listener settings
230
-
231
- ```env
232
- KAFKA_BROKER_BIND_ADDRESS=0.0.0.0
233
- KAFKA_EXTERNAL_HOST=localhost
234
- KAFKA_BROKER_INTERNAL_PORT=9092
235
- KAFKA_BROKER_EXTERNAL_CONTAINER_PORT=19092
236
- KAFKA_BROKER_1_EXTERNAL_PORT=29092
237
- KAFKA_BROKER_2_EXTERNAL_PORT=39092
238
- KAFKA_BROKER_3_EXTERNAL_PORT=49092
239
- KAFKA_INTER_BROKER_LISTENER_NAME=INTERNAL
240
- KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
241
- ```
242
-
243
- - `KAFKA_EXTERNAL_HOST=localhost` exposes brokers to your host machine
244
- - `KAFKA_BROKER_1_EXTERNAL_PORT`, `KAFKA_BROKER_2_EXTERNAL_PORT`, and `KAFKA_BROKER_3_EXTERNAL_PORT` are the ports your local apps should use
245
- - `KAFKA_BROKER_INTERNAL_PORT=9092` is used by containers on the Docker network
246
-
247
- ### Replication and durability defaults
248
-
249
- ```env
250
- KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=3
251
- KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3
252
- KAFKA_TRANSACTION_STATE_LOG_MIN_ISR=2
253
- KAFKA_DEFAULT_REPLICATION_FACTOR=3
254
- KAFKA_MIN_INSYNC_REPLICAS=2
255
- KAFKA_NUM_PARTITIONS=6
256
- ```
257
-
258
- These values are designed for the included three-broker cluster.
259
-
260
- ### Broker behavior
261
-
262
- ```env
263
- KAFKA_AUTO_CREATE_TOPICS_ENABLE=false
264
- KAFKA_DELETE_TOPIC_ENABLE=true
265
- KAFKA_LOG_RETENTION_HOURS=168
266
- KAFKA_LOG_SEGMENT_BYTES=1073741824
267
- KAFKA_MESSAGE_MAX_BYTES=10485880
268
- KAFKA_REPLICA_FETCH_MAX_BYTES=10485880
269
- KAFKA_SOCKET_REQUEST_MAX_BYTES=104857600
270
- ```
271
-
272
- - topics are not auto-created by default
273
- - deleting topics is allowed
274
- - retention is 7 days by default
275
-
276
- ### Storage and safety limits
277
-
278
- ```env
279
- KAFKA_LOG_DIRS=/var/lib/kafka/data
280
- KAFKA_ULIMIT_NOFILE_SOFT=65536
281
- KAFKA_ULIMIT_NOFILE_HARD=65536
282
- KAFKA_LOG_MAX_SIZE=100m
283
- KAFKA_LOG_MAX_FILE=5
284
- ```
285
-
286
- ### Kafka UI settings
287
-
288
- ```env
289
- KAFKA_UI_IMAGE=provectuslabs/kafka-ui:latest
290
- KAFKA_UI_CONTAINER_NAME=kafka-ui
291
- KAFKA_UI_HOSTNAME=kafka-ui
292
- KAFKA_UI_RESTART_POLICY=unless-stopped
293
- KAFKA_UI_BIND_ADDRESS=127.0.0.1
294
- KAFKA_UI_PORT=5001
295
- KAFKA_UI_DYNAMIC_CONFIG_ENABLED=false
296
- KAFKA_UI_CLUSTER_NAME=Project Omni Enterprise Kafka
297
- KAFKA_UI_READONLY=true
298
- KAFKA_UI_AUTH_TYPE=LOGIN_FORM
299
- KAFKA_UI_USERNAME=admin
300
- KAFKA_UI_PASSWORD=Admin@007
301
- ```
302
-
303
- - `KAFKA_UI_BIND_ADDRESS=127.0.0.1` keeps the UI local-only
304
- - `KAFKA_UI_PORT=5001` publishes the UI on your machine
305
- - `KAFKA_UI_READONLY=true` prevents write actions from the UI
306
-
307
- ### Healthcheck settings
308
-
309
- ```env
310
- KAFKA_HEALTHCHECK_INTERVAL=10s
311
- KAFKA_HEALTHCHECK_TIMEOUT=5s
312
- KAFKA_HEALTHCHECK_RETRIES=15
313
- KAFKA_HEALTHCHECK_START_PERIOD=30s
314
- ```
315
-
316
- ## Creating Topics
317
-
318
- Because `KAFKA_AUTO_CREATE_TOPICS_ENABLE=false`, topics should be created deliberately.
319
-
320
- You have two good options:
321
-
322
- - create topics from your service with `kafkaManager.provisionTopics()`
323
- - allow UI-based creation by setting `KAFKA_UI_READONLY=false`
324
-
325
- Example with this package:
81
+ ## Full Service Example
326
82
 
327
83
  ```ts
328
- await kafkaManager.provisionTopics([
329
- {
330
- topic: 'claims.created',
331
- numPartitions: 6,
332
- replicationFactor: 3,
333
- },
334
- ])
335
- ```
336
-
337
- ## Enterprise Features
338
-
339
- This version now includes a stronger production baseline:
84
+ import { KafkaManager } from 'sentinel-kafka-manager'
340
85
 
341
- - config validation for client id, brokers, and broker discovery inputs
342
- - shared producer, admin, and consumer lifecycle
343
- - logger and metrics hooks
344
- - standard message envelope publishing
345
- - managed consumer runner with dead-letter topic support
346
- - health snapshot reporting
347
- - safer startup behavior for concurrent connections
348
- - stable error codes and structured exception details
86
+ const kafkaManager = KafkaManager.fromEnv({
87
+ clientId: 'claims-api',
88
+ mode: 'external',
89
+ })
349
90
 
350
- ## Recommended Usage Level
91
+ async function bootstrap(): Promise<void> {
92
+ await kafkaManager.provisionTopics([
93
+ {
94
+ topic: 'claims.created',
95
+ numPartitions: 6,
96
+ replicationFactor: 3,
97
+ },
98
+ ])
351
99
 
352
- This package is now suitable as a shared internal Kafka module for SaaS microservices.
100
+ await kafkaManager.publish({
101
+ topic: 'claims.created',
102
+ key: 'claim-1001',
103
+ payload: {
104
+ claimId: 'claim-1001',
105
+ source: 'claims-api',
106
+ },
107
+ })
353
108
 
354
- Recommended use:
109
+ await kafkaManager.runConsumer({
110
+ groupId: 'claims-api-group',
111
+ topic: 'claims.created',
112
+ dlqTopic: 'claims.created.dlq',
113
+ onMessage: async ({ message, headers }) => {
114
+ console.log('Received event:', {
115
+ traceId: headers['x-trace-id'],
116
+ payload: message,
117
+ })
118
+ },
119
+ })
120
+ }
355
121
 
356
- - internal platform package for Node.js services
357
- - event publishing with standard envelopes
358
- - managed consumers with DLQ handling
359
- - consistent service-layer success and error responses
122
+ bootstrap().catch(async (error) => {
123
+ console.error('Kafka bootstrap failed:', error)
124
+ await kafkaManager.disconnect()
125
+ process.exit(1)
126
+ })
360
127
 
361
- Still recommended outside the package:
128
+ process.on('SIGINT', async () => {
129
+ await kafkaManager.disconnect()
130
+ process.exit(0)
131
+ })
362
132
 
363
- - automated unit and integration tests in the consuming service or platform repo
364
- - schema validation for business payloads when required by your organization
365
- - organization-specific tracing, alerting, and compliance rules
133
+ process.on('SIGTERM', async () => {
134
+ await kafkaManager.disconnect()
135
+ process.exit(0)
136
+ })
137
+ ```
366
138
 
367
139
  ## Basic Usage
368
140
 
@@ -702,190 +474,420 @@ console.log(health)
702
474
 
703
475
  ## Environment Setup
704
476
 
705
- This package supports two environment styles:
477
+ This package supports two environment styles:
478
+
479
+ 1. one explicit broker list with `KAFKA_BROKERS`
480
+ 2. derived brokers from your existing Kafka runtime variables
481
+
482
+ ### Option 1: Use `KAFKA_BROKERS`
483
+
484
+ This is the simplest option.
485
+
486
+ ### `.env`
487
+
488
+ ```env
489
+ KAFKA_BROKERS=localhost:29092,localhost:39092,localhost:49092
490
+ ```
491
+
492
+ ### Code
493
+
494
+ ```ts
495
+ const kafkaManager = KafkaManager.fromEnv({
496
+ clientId: 'claims-service',
497
+ })
498
+ ```
499
+
500
+ ### Option 2: Use your current Kafka cluster variables
501
+
502
+ This matches the Kafka server setup you shared.
503
+
504
+ ### For host machine apps
505
+
506
+ Use this when your Node.js service runs on the host machine.
507
+
508
+ ### `.env`
509
+
510
+ ```env
511
+ KAFKA_EXTERNAL_HOST=localhost
512
+ KAFKA_BROKER_1_EXTERNAL_PORT=29092
513
+ KAFKA_BROKER_2_EXTERNAL_PORT=39092
514
+ KAFKA_BROKER_3_EXTERNAL_PORT=49092
515
+ KAFKA_BROKER_INTERNAL_PORT=9092
516
+ ```
517
+
518
+ ### Code
519
+
520
+ ```ts
521
+ const kafkaManager = KafkaManager.fromEnv({
522
+ clientId: 'claims-service',
523
+ mode: 'external',
524
+ })
525
+ ```
526
+
527
+ This resolves to:
528
+
529
+ ```text
530
+ localhost:29092
531
+ localhost:39092
532
+ localhost:49092
533
+ ```
534
+
535
+ ### For Dockerized apps on the Kafka network
536
+
537
+ Use this when your Node.js service runs inside Docker on the same Kafka network.
538
+
539
+ ### `.env`
540
+
541
+ ```env
542
+ KAFKA_BROKER_INTERNAL_PORT=9092
543
+ ```
544
+
545
+ ### Code
546
+
547
+ ```ts
548
+ const kafkaManager = KafkaManager.fromEnv({
549
+ clientId: 'claims-service',
550
+ mode: 'internal',
551
+ })
552
+ ```
553
+
554
+ This resolves to:
555
+
556
+ ```text
557
+ broker-1:9092
558
+ broker-2:9092
559
+ broker-3:9092
560
+ ```
561
+
562
+ ### Which Mode Should You Use?
563
+
564
+ - Use `mode: 'external'` when your service uses `localhost` broker ports like `29092`, `39092`, and `49092`
565
+ - Use `mode: 'internal'` when your service is inside Docker and should reach brokers like `broker-1:9092`
566
+ - Use `KAFKA_BROKERS` when you want the simplest and most explicit configuration
567
+
568
+ ### Your Current Running Kafka Cluster
569
+
570
+ Based on your running Docker containers, your Kafka cluster is exposed like this:
571
+
572
+ - `broker-1` -> host port `29092`
573
+ - `broker-2` -> host port `39092`
574
+ - `broker-3` -> host port `49092`
575
+ - `controller-1`, `controller-2`, and `controller-3` are controller-only nodes and should not be used by application clients
576
+
577
+ If your Node.js service runs on the host machine, use:
578
+
579
+ ```env
580
+ KAFKA_EXTERNAL_HOST=localhost
581
+ KAFKA_BROKER_1_EXTERNAL_PORT=29092
582
+ KAFKA_BROKER_2_EXTERNAL_PORT=39092
583
+ KAFKA_BROKER_3_EXTERNAL_PORT=49092
584
+ KAFKA_BROKER_INTERNAL_PORT=9092
585
+ ```
586
+
587
+ ```ts
588
+ const kafkaManager = KafkaManager.fromEnv({
589
+ clientId: 'claims-service',
590
+ mode: 'external',
591
+ })
592
+ ```
593
+
594
+ If your Node.js service runs inside Docker on the same Kafka network, use:
595
+
596
+ ```ts
597
+ const kafkaManager = KafkaManager.fromEnv({
598
+ clientId: 'claims-service',
599
+ mode: 'internal',
600
+ })
601
+ ```
602
+
603
+ This package is designed to work with that exact broker layout.
604
+
605
+ ## Local Infrastructure And Operations
606
+
607
+ ### Create A Kafka Server With This Repo
608
+
609
+ This repository already includes a full local Kafka server setup in [docker-compose.yml](/var/www/html/matrix-project/sentinel-kafka-manager/docker-compose.yml) and sample environment values in [.env.local.example](/var/www/html/matrix-project/sentinel-kafka-manager/.env.local.example).
610
+
611
+ The stack includes:
612
+
613
+ - 3 KRaft controllers
614
+ - 3 Kafka brokers
615
+ - 1 Kafka UI instance
616
+
617
+ ### 1. Create your `.env`
618
+
619
+ Copy the example file:
620
+
621
+ ```bash
622
+ cp .env.local.example .env
623
+ ```
624
+
625
+ If you want a standard localhost setup, the example values are already suitable.
626
+
627
+ ### 2. Start the Kafka cluster
628
+
629
+ ```bash
630
+ docker compose --env-file .env up -d
631
+ ```
632
+
633
+ This creates:
634
+
635
+ - controller quorum on port `9093` inside Docker
636
+ - internal broker traffic on port `9092` inside Docker
637
+ - host-accessible broker ports `29092`, `39092`, and `49092`
638
+ - Kafka UI on `127.0.0.1:5001`
639
+
640
+ ### 3. Stop the Kafka cluster
641
+
642
+ ```bash
643
+ docker compose --env-file .env down
644
+ ```
645
+
646
+ To also remove persisted Kafka data volumes:
647
+
648
+ ```bash
649
+ docker compose --env-file .env down -v
650
+ ```
651
+
652
+ ### 4. Check container status
653
+
654
+ ```bash
655
+ docker compose --env-file .env ps
656
+ ```
657
+
658
+ ### 5. Current broker endpoints
659
+
660
+ For applications running on your host machine:
661
+
662
+ ```text
663
+ localhost:29092
664
+ localhost:39092
665
+ localhost:49092
666
+ ```
667
+
668
+ For applications running inside Docker on the same Compose network:
669
+
670
+ ```text
671
+ broker-1:9092
672
+ broker-2:9092
673
+ broker-3:9092
674
+ ```
675
+
676
+ Important:
677
+
678
+ - application clients must connect to brokers, not controllers
679
+ - controllers are internal cluster metadata nodes only
680
+ - `mode: 'external'` is for host-based apps
681
+ - `mode: 'internal'` is for Dockerized apps on the same network
682
+
683
+ ### Kafka UI Usage
684
+
685
+ The Docker stack also starts Kafka UI for cluster inspection.
686
+
687
+ ### Open the UI
688
+
689
+ Visit:
690
+
691
+ ```text
692
+ http://127.0.0.1:5001
693
+ ```
694
+
695
+ ### Login credentials
696
+
697
+ By default, the UI uses the credentials from `.env`:
698
+
699
+ ```env
700
+ KAFKA_UI_USERNAME=admin
701
+ KAFKA_UI_PASSWORD=Admin@007
702
+ ```
703
+
704
+ ### What the UI connects to
705
+
706
+ Kafka UI is preconfigured in `docker-compose.yml` to use all three brokers:
707
+
708
+ ```text
709
+ broker-1:9092,broker-2:9092,broker-3:9092
710
+ ```
711
+
712
+ The cluster name shown in the UI comes from:
713
+
714
+ ```env
715
+ KAFKA_UI_CLUSTER_NAME=Project Omni Enterprise Kafka
716
+ ```
717
+
718
+ ### What you can do in the UI
719
+
720
+ - view brokers and cluster health
721
+ - inspect topics and partitions
722
+ - browse messages
723
+ - inspect consumer groups
724
+ - check offsets and lag
725
+
726
+ ### Read-only mode
706
727
 
707
- 1. one explicit broker list with `KAFKA_BROKERS`
708
- 2. derived brokers from your existing Kafka runtime variables
728
+ The example `.env` sets:
709
729
 
710
- ## Option 1: Use `KAFKA_BROKERS`
730
+ ```env
731
+ KAFKA_UI_READONLY=true
732
+ ```
711
733
 
712
- This is the simplest option.
734
+ That means the UI is intended for safe inspection only.
713
735
 
714
- ### `.env`
736
+ If you want to create topics or make changes from the UI, change it to:
715
737
 
716
738
  ```env
717
- KAFKA_BROKERS=localhost:29092,localhost:39092,localhost:49092
739
+ KAFKA_UI_READONLY=false
718
740
  ```
719
741
 
720
- ### Code
742
+ Then restart the stack:
721
743
 
722
- ```ts
723
- const kafkaManager = KafkaManager.fromEnv({
724
- clientId: 'claims-service',
725
- })
744
+ ```bash
745
+ docker compose --env-file .env up -d
726
746
  ```
727
747
 
728
- ## Option 2: Use your current Kafka cluster variables
748
+ ### Typical UI flow
729
749
 
730
- This matches the Kafka server setup you shared.
750
+ 1. Start the Docker stack.
751
+ 2. Open `http://127.0.0.1:5001`.
752
+ 3. Log in with `KAFKA_UI_USERNAME` and `KAFKA_UI_PASSWORD`.
753
+ 4. Open the configured cluster.
754
+ 5. Go to Topics, Consumer Groups, or Brokers as needed.
731
755
 
732
- ### For host machine apps
756
+ ### Docker Compose And `.env` Reference
733
757
 
734
- Use this when your Node.js service runs on the host machine.
758
+ This project does not use a separate `Dockerfile` for Kafka. The Kafka server is created from `docker-compose.yml` and environment values from `.env`.
735
759
 
736
- ### `.env`
760
+ ### Core Kafka image and cluster identity
737
761
 
738
762
  ```env
739
- KAFKA_EXTERNAL_HOST=localhost
740
- KAFKA_BROKER_1_EXTERNAL_PORT=29092
741
- KAFKA_BROKER_2_EXTERNAL_PORT=39092
742
- KAFKA_BROKER_3_EXTERNAL_PORT=49092
743
- KAFKA_BROKER_INTERNAL_PORT=9092
763
+ KAFKA_IMAGE=confluentinc/cp-kafka:7.6.6
764
+ KAFKA_CLUSTER_ID=MkU3OEVBNTcwNTJENDM2Qk
765
+ KAFKA_RESTART_POLICY=unless-stopped
766
+ KAFKA_STOP_GRACE_PERIOD=60s
767
+ KAFKA_NETWORK_NAME=kafka-network
744
768
  ```
745
769
 
746
- ### Code
747
-
748
- ```ts
749
- const kafkaManager = KafkaManager.fromEnv({
750
- clientId: 'claims-service',
751
- mode: 'external',
752
- })
753
- ```
770
+ - `KAFKA_IMAGE`: Kafka container image used by controllers and brokers
771
+ - `KAFKA_CLUSTER_ID`: shared KRaft cluster id for all nodes
772
+ - `KAFKA_NETWORK_NAME`: Docker network name used by the full stack
754
773
 
755
- This resolves to:
774
+ ### Controller quorum settings
756
775
 
757
- ```text
758
- localhost:29092
759
- localhost:39092
760
- localhost:49092
776
+ ```env
777
+ KAFKA_CONTROLLER_PORT=9093
778
+ KAFKA_CONTROLLER_LISTENER_NAMES=CONTROLLER
779
+ KAFKA_CONTROLLER_QUORUM_VOTERS=1@controller-1:9093,2@controller-2:9093,3@controller-3:9093
761
780
  ```
762
781
 
763
- ### For Dockerized apps on the Kafka network
764
-
765
- Use this when your Node.js service runs inside Docker on the same Kafka network.
782
+ - controllers run only inside Docker
783
+ - apps should never use these controller addresses as Kafka client brokers
766
784
 
767
- ### `.env`
785
+ ### Broker listener settings
768
786
 
769
787
  ```env
788
+ KAFKA_BROKER_BIND_ADDRESS=0.0.0.0
789
+ KAFKA_EXTERNAL_HOST=localhost
770
790
  KAFKA_BROKER_INTERNAL_PORT=9092
791
+ KAFKA_BROKER_EXTERNAL_CONTAINER_PORT=19092
792
+ KAFKA_BROKER_1_EXTERNAL_PORT=29092
793
+ KAFKA_BROKER_2_EXTERNAL_PORT=39092
794
+ KAFKA_BROKER_3_EXTERNAL_PORT=49092
795
+ KAFKA_INTER_BROKER_LISTENER_NAME=INTERNAL
796
+ KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,INTERNAL:PLAINTEXT,EXTERNAL:PLAINTEXT
771
797
  ```
772
798
 
773
- ### Code
774
-
775
- ```ts
776
- const kafkaManager = KafkaManager.fromEnv({
777
- clientId: 'claims-service',
778
- mode: 'internal',
779
- })
780
- ```
799
+ - `KAFKA_EXTERNAL_HOST=localhost` exposes brokers to your host machine
800
+ - `KAFKA_BROKER_1_EXTERNAL_PORT`, `KAFKA_BROKER_2_EXTERNAL_PORT`, and `KAFKA_BROKER_3_EXTERNAL_PORT` are the ports your local apps should use
801
+ - `KAFKA_BROKER_INTERNAL_PORT=9092` is used by containers on the Docker network
781
802
 
782
- This resolves to:
803
+ ### Replication and durability defaults
783
804
 
784
- ```text
785
- broker-1:9092
786
- broker-2:9092
787
- broker-3:9092
805
+ ```env
806
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=3
807
+ KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR=3
808
+ KAFKA_TRANSACTION_STATE_LOG_MIN_ISR=2
809
+ KAFKA_DEFAULT_REPLICATION_FACTOR=3
810
+ KAFKA_MIN_INSYNC_REPLICAS=2
811
+ KAFKA_NUM_PARTITIONS=6
788
812
  ```
789
813
 
790
- ## Which Mode Should You Use?
791
-
792
- - Use `mode: 'external'` when your service uses `localhost` broker ports like `29092`, `39092`, and `49092`
793
- - Use `mode: 'internal'` when your service is inside Docker and should reach brokers like `broker-1:9092`
794
- - Use `KAFKA_BROKERS` when you want the simplest and most explicit configuration
814
+ These values are designed for the included three-broker cluster.
795
815
 
796
- ## Your Current Running Kafka Cluster
816
+ ### Broker behavior
797
817
 
798
- Based on your running Docker containers, your Kafka cluster is exposed like this:
818
+ ```env
819
+ KAFKA_AUTO_CREATE_TOPICS_ENABLE=false
820
+ KAFKA_DELETE_TOPIC_ENABLE=true
821
+ KAFKA_LOG_RETENTION_HOURS=168
822
+ KAFKA_LOG_SEGMENT_BYTES=1073741824
823
+ KAFKA_MESSAGE_MAX_BYTES=10485880
824
+ KAFKA_REPLICA_FETCH_MAX_BYTES=10485880
825
+ KAFKA_SOCKET_REQUEST_MAX_BYTES=104857600
826
+ ```
799
827
 
800
- - `broker-1` -> host port `29092`
801
- - `broker-2` -> host port `39092`
802
- - `broker-3` -> host port `49092`
803
- - `controller-1`, `controller-2`, and `controller-3` are controller-only nodes and should not be used by application clients
828
+ - topics are not auto-created by default
829
+ - deleting topics is allowed
830
+ - retention is 7 days by default
804
831
 
805
- If your Node.js service runs on the host machine, use:
832
+ ### Storage and safety limits
806
833
 
807
834
  ```env
808
- KAFKA_EXTERNAL_HOST=localhost
809
- KAFKA_BROKER_1_EXTERNAL_PORT=29092
810
- KAFKA_BROKER_2_EXTERNAL_PORT=39092
811
- KAFKA_BROKER_3_EXTERNAL_PORT=49092
812
- KAFKA_BROKER_INTERNAL_PORT=9092
813
- ```
814
-
815
- ```ts
816
- const kafkaManager = KafkaManager.fromEnv({
817
- clientId: 'claims-service',
818
- mode: 'external',
819
- })
835
+ KAFKA_LOG_DIRS=/var/lib/kafka/data
836
+ KAFKA_ULIMIT_NOFILE_SOFT=65536
837
+ KAFKA_ULIMIT_NOFILE_HARD=65536
838
+ KAFKA_LOG_MAX_SIZE=100m
839
+ KAFKA_LOG_MAX_FILE=5
820
840
  ```
821
841
 
822
- If your Node.js service runs inside Docker on the same Kafka network, use:
842
+ ### Kafka UI settings
823
843
 
824
- ```ts
825
- const kafkaManager = KafkaManager.fromEnv({
826
- clientId: 'claims-service',
827
- mode: 'internal',
828
- })
844
+ ```env
845
+ KAFKA_UI_IMAGE=provectuslabs/kafka-ui:latest
846
+ KAFKA_UI_CONTAINER_NAME=kafka-ui
847
+ KAFKA_UI_HOSTNAME=kafka-ui
848
+ KAFKA_UI_RESTART_POLICY=unless-stopped
849
+ KAFKA_UI_BIND_ADDRESS=127.0.0.1
850
+ KAFKA_UI_PORT=5001
851
+ KAFKA_UI_DYNAMIC_CONFIG_ENABLED=false
852
+ KAFKA_UI_CLUSTER_NAME=Project Omni Enterprise Kafka
853
+ KAFKA_UI_READONLY=true
854
+ KAFKA_UI_AUTH_TYPE=LOGIN_FORM
855
+ KAFKA_UI_USERNAME=admin
856
+ KAFKA_UI_PASSWORD=Admin@007
829
857
  ```
830
858
 
831
- This package is designed to work with that exact broker layout.
832
-
833
- ## Full Service Example
859
+ - `KAFKA_UI_BIND_ADDRESS=127.0.0.1` keeps the UI local-only
860
+ - `KAFKA_UI_PORT=5001` publishes the UI on your machine
861
+ - `KAFKA_UI_READONLY=true` prevents write actions from the UI
834
862
 
835
- ```ts
836
- import { KafkaManager } from 'sentinel-kafka-manager'
863
+ ### Healthcheck settings
837
864
 
838
- const kafkaManager = KafkaManager.fromEnv({
839
- clientId: 'claims-api',
840
- mode: 'external',
841
- })
865
+ ```env
866
+ KAFKA_HEALTHCHECK_INTERVAL=10s
867
+ KAFKA_HEALTHCHECK_TIMEOUT=5s
868
+ KAFKA_HEALTHCHECK_RETRIES=15
869
+ KAFKA_HEALTHCHECK_START_PERIOD=30s
870
+ ```
842
871
 
843
- async function bootstrap(): Promise<void> {
844
- await kafkaManager.provisionTopics([
845
- {
846
- topic: 'claims.created',
847
- numPartitions: 6,
848
- replicationFactor: 3,
849
- },
850
- ])
872
+ ### Creating Topics
851
873
 
852
- await kafkaManager.publish({
853
- topic: 'claims.created',
854
- key: 'claim-1001',
855
- payload: {
856
- claimId: 'claim-1001',
857
- source: 'claims-api',
858
- },
859
- })
874
+ Because `KAFKA_AUTO_CREATE_TOPICS_ENABLE=false`, topics should be created deliberately.
860
875
 
861
- await kafkaManager.runConsumer({
862
- groupId: 'claims-api-group',
863
- topic: 'claims.created',
864
- dlqTopic: 'claims.created.dlq',
865
- onMessage: async ({ message, headers }) => {
866
- console.log('Received event:', {
867
- traceId: headers['x-trace-id'],
868
- payload: message,
869
- })
870
- },
871
- })
872
- }
876
+ You have two good options:
873
877
 
874
- bootstrap().catch(async (error) => {
875
- console.error('Kafka bootstrap failed:', error)
876
- await kafkaManager.disconnect()
877
- process.exit(1)
878
- })
878
+ - create topics from your service with `kafkaManager.provisionTopics()`
879
+ - allow UI-based creation by setting `KAFKA_UI_READONLY=false`
879
880
 
880
- process.on('SIGINT', async () => {
881
- await kafkaManager.disconnect()
882
- process.exit(0)
883
- })
881
+ Example with this package:
884
882
 
885
- process.on('SIGTERM', async () => {
886
- await kafkaManager.disconnect()
887
- process.exit(0)
888
- })
883
+ ```ts
884
+ await kafkaManager.provisionTopics([
885
+ {
886
+ topic: 'claims.created',
887
+ numPartitions: 6,
888
+ replicationFactor: 3,
889
+ },
890
+ ])
889
891
  ```
890
892
 
891
893
  ## API Summary
@@ -1138,7 +1140,9 @@ const kafkaManager = new KafkaManager({
1138
1140
  })
1139
1141
  ```
1140
1142
 
1141
- ## Common Mistakes
1143
+ ## Operational Guidance
1144
+
1145
+ ### Common Mistakes
1142
1146
 
1143
1147
  - Do not connect application clients to KRaft controller nodes. Connect only to brokers.
1144
1148
  - Do not use `mode: 'external'` inside Docker unless you truly want host-published ports.
@@ -1149,7 +1153,7 @@ const kafkaManager = new KafkaManager({
1149
1153
  - Do not publish business-critical events without metadata. Prefer `publishEnvelope()` for traceability.
1150
1154
  - Do not depend on raw driver error strings in application logic. Use `KafkaManagerError.code`.
1151
1155
 
1152
- ## Recommended SaaS Pattern
1156
+ ### Recommended SaaS Pattern
1153
1157
 
1154
1158
  For most SaaS services, the cleanest pattern is:
1155
1159
 
@@ -1160,38 +1164,13 @@ For most SaaS services, the cleanest pattern is:
1160
1164
  5. Catch `KafkaManagerError` and branch on `error.code`.
1161
1165
  6. Wrap service outcomes in `OperationResponse<T>` where useful.
1162
1166
 
1163
- ## Publishing This Package
1164
-
1165
- Build:
1166
-
1167
- ```bash
1168
- npm run build
1169
- ```
1170
-
1171
- Publish:
1172
-
1173
- ```bash
1174
- npm publish
1175
- ```
1176
-
1177
- If npm rejects the publish:
1178
-
1179
- - `403` usually means authentication, 2FA, or token permission issues
1180
- - `404` usually means the package name is unavailable or not publishable by your account
1181
-
1182
- Useful check:
1183
-
1184
- ```bash
1185
- npm whoami
1186
- ```
1187
-
1188
- ## Notes
1167
+ ### Notes
1189
1168
 
1190
1169
  - Your current Kafka cluster works fine with PLAINTEXT, so SSL and SASL are optional unless your environment changes
1191
1170
  - This package is designed for both host-based services and Dockerized services
1192
1171
  - If you want the least surprise, use `KAFKA_BROKERS`
1193
1172
 
1194
- ## Links
1173
+ ## Additional Documentation
1195
1174
 
1196
1175
  - npm deployment guide: [NPM_DEPLOYMENT.md](/var/www/html/matrix-project/sentinel-kafka-manager/NPM_DEPLOYMENT.md)
1197
1176
  - Example folder: [examples/service-module-usage/README.md](/var/www/html/matrix-project/sentinel-kafka-manager/examples/service-module-usage/README.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sentinel-kafka-manager",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Reusable Kafka manager for Node.js microservices",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",