Skip to content

Commit 8ab41fc

Browse files
committed
feat(kafka): add Kafka integration for event streaming
- Introduced Kafka support in the Evolution API, allowing for real-time event streaming and processing. - Updated environment configuration to include Kafka-related variables. - Added KafkaController and KafkaRouter for managing Kafka events. - Enhanced event management to support Kafka alongside existing integrations. - Updated database schemas and migrations for Kafka integration in both MySQL and PostgreSQL. - Documented Kafka integration in the README file.
1 parent 5e08628 commit 8ab41fc

File tree

17 files changed

+969
-13
lines changed

17 files changed

+969
-13
lines changed

.env.example

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,60 @@ PUSHER_EVENTS_CALL=true
190190
PUSHER_EVENTS_TYPEBOT_START=false
191191
PUSHER_EVENTS_TYPEBOT_CHANGE_STATUS=false
192192

193+
# Kafka - Environment variables
194+
KAFKA_ENABLED=false
195+
KAFKA_CLIENT_ID=evolution-api
196+
KAFKA_BROKERS=localhost:9092
197+
KAFKA_CONNECTION_TIMEOUT=3000
198+
KAFKA_REQUEST_TIMEOUT=30000
199+
# Global events - By enabling this variable, events from all instances are sent to global Kafka topics.
200+
KAFKA_GLOBAL_ENABLED=false
201+
KAFKA_CONSUMER_GROUP_ID=evolution-api-consumers
202+
KAFKA_TOPIC_PREFIX=evolution
203+
KAFKA_NUM_PARTITIONS=1
204+
KAFKA_REPLICATION_FACTOR=1
205+
KAFKA_AUTO_CREATE_TOPICS=false
206+
# Choose the events you want to send to Kafka
207+
KAFKA_EVENTS_APPLICATION_STARTUP=false
208+
KAFKA_EVENTS_INSTANCE_CREATE=false
209+
KAFKA_EVENTS_INSTANCE_DELETE=false
210+
KAFKA_EVENTS_QRCODE_UPDATED=false
211+
KAFKA_EVENTS_MESSAGES_SET=false
212+
KAFKA_EVENTS_MESSAGES_UPSERT=false
213+
KAFKA_EVENTS_MESSAGES_EDITED=false
214+
KAFKA_EVENTS_MESSAGES_UPDATE=false
215+
KAFKA_EVENTS_MESSAGES_DELETE=false
216+
KAFKA_EVENTS_SEND_MESSAGE=false
217+
KAFKA_EVENTS_SEND_MESSAGE_UPDATE=false
218+
KAFKA_EVENTS_CONTACTS_SET=false
219+
KAFKA_EVENTS_CONTACTS_UPSERT=false
220+
KAFKA_EVENTS_CONTACTS_UPDATE=false
221+
KAFKA_EVENTS_PRESENCE_UPDATE=false
222+
KAFKA_EVENTS_CHATS_SET=false
223+
KAFKA_EVENTS_CHATS_UPSERT=false
224+
KAFKA_EVENTS_CHATS_UPDATE=false
225+
KAFKA_EVENTS_CHATS_DELETE=false
226+
KAFKA_EVENTS_GROUPS_UPSERT=false
227+
KAFKA_EVENTS_GROUPS_UPDATE=false
228+
KAFKA_EVENTS_GROUP_PARTICIPANTS_UPDATE=false
229+
KAFKA_EVENTS_CONNECTION_UPDATE=false
230+
KAFKA_EVENTS_LABELS_EDIT=false
231+
KAFKA_EVENTS_LABELS_ASSOCIATION=false
232+
KAFKA_EVENTS_CALL=false
233+
KAFKA_EVENTS_TYPEBOT_START=false
234+
KAFKA_EVENTS_TYPEBOT_CHANGE_STATUS=false
235+
# SASL Authentication (optional)
236+
KAFKA_SASL_ENABLED=false
237+
KAFKA_SASL_MECHANISM=plain
238+
KAFKA_SASL_USERNAME=
239+
KAFKA_SASL_PASSWORD=
240+
# SSL Configuration (optional)
241+
KAFKA_SSL_ENABLED=false
242+
KAFKA_SSL_REJECT_UNAUTHORIZED=true
243+
KAFKA_SSL_CA=
244+
KAFKA_SSL_KEY=
245+
KAFKA_SSL_CERT=
246+
193247
# WhatsApp Business API - Environment variables
194248
# Token used to validate the webhook on the Facebook APP
195249
WA_BUSINESS_TOKEN_WEBHOOK=evolution

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ Evolution API supports various integrations to enhance its functionality. Below
5555
- [RabbitMQ](https://www.rabbitmq.com/):
5656
- Receive events from the Evolution API via RabbitMQ.
5757

58+
- [Apache Kafka](https://kafka.apache.org/):
59+
- Receive events from the Evolution API via Apache Kafka for real-time event streaming and processing.
60+
5861
- [Amazon SQS](https://aws.amazon.com/pt/sqs/):
5962
- Receive events from the Evolution API via Amazon SQS.
6063

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
"json-schema": "^0.4.0",
9696
"jsonschema": "^1.4.1",
9797
"jsonwebtoken": "^9.0.2",
98+
"kafkajs": "^2.2.4",
9899
"link-preview-js": "^3.0.13",
99100
"long": "^5.2.3",
100101
"mediainfo.js": "^0.3.4",

prisma/mysql-migrations/20250918183910_add_kafka_integration/migration.sql

Lines changed: 231 additions & 0 deletions
Large diffs are not rendered by default.

prisma/mysql-schema.prisma

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ model Instance {
8888
Rabbitmq Rabbitmq?
8989
Nats Nats?
9090
Sqs Sqs?
91+
Kafka Kafka?
9192
Websocket Websocket?
9293
Typebot Typebot[]
9394
Session Session?
@@ -105,8 +106,11 @@ model Instance {
105106
EvolutionBotSetting EvolutionBotSetting?
106107
Flowise Flowise[]
107108
FlowiseSetting FlowiseSetting?
108-
Pusher Pusher?
109109
N8n N8n[]
110+
N8nSetting N8nSetting?
111+
Evoai Evoai[]
112+
EvoaiSetting EvoaiSetting?
113+
Pusher Pusher?
110114
}
111115

112116
model Session {
@@ -309,6 +313,16 @@ model Sqs {
309313
instanceId String @unique
310314
}
311315

316+
model Kafka {
317+
id String @id @default(cuid())
318+
enabled Boolean @default(false)
319+
events Json @db.Json
320+
createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
321+
updatedAt DateTime @updatedAt @db.Timestamp
322+
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
323+
instanceId String @unique
324+
}
325+
312326
model Websocket {
313327
id String @id @default(cuid())
314328
enabled Boolean @default(false)
@@ -647,7 +661,7 @@ model IsOnWhatsapp {
647661

648662
model N8n {
649663
id String @id @default(cuid())
650-
enabled Boolean @default(true) @db.TinyInt(1)
664+
enabled Boolean @default(true) @db.TinyInt()
651665
description String? @db.VarChar(255)
652666
webhookUrl String? @db.VarChar(255)
653667
basicAuthUser String? @db.VarChar(255)
@@ -666,7 +680,7 @@ model N8n {
666680
triggerType TriggerType?
667681
triggerOperator TriggerOperator?
668682
triggerValue String?
669-
createdAt DateTime? @default(now()) @db.Timestamp
683+
createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
670684
updatedAt DateTime @updatedAt @db.Timestamp
671685
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
672686
instanceId String
@@ -686,7 +700,7 @@ model N8nSetting {
686700
ignoreJids Json?
687701
splitMessages Boolean? @default(false)
688702
timePerChar Int? @default(50) @db.Int
689-
createdAt DateTime? @default(now()) @db.Timestamp
703+
createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
690704
updatedAt DateTime @updatedAt @db.Timestamp
691705
Fallback N8n? @relation(fields: [n8nIdFallback], references: [id])
692706
n8nIdFallback String? @db.VarChar(100)
@@ -696,7 +710,7 @@ model N8nSetting {
696710

697711
model Evoai {
698712
id String @id @default(cuid())
699-
enabled Boolean @default(true) @db.TinyInt(1)
713+
enabled Boolean @default(true) @db.TinyInt()
700714
description String? @db.VarChar(255)
701715
agentUrl String? @db.VarChar(255)
702716
apiKey String? @db.VarChar(255)
@@ -714,7 +728,7 @@ model Evoai {
714728
triggerType TriggerType?
715729
triggerOperator TriggerOperator?
716730
triggerValue String?
717-
createdAt DateTime? @default(now()) @db.Timestamp
731+
createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
718732
updatedAt DateTime @updatedAt @db.Timestamp
719733
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
720734
instanceId String
@@ -734,7 +748,7 @@ model EvoaiSetting {
734748
ignoreJids Json?
735749
splitMessages Boolean? @default(false)
736750
timePerChar Int? @default(50) @db.Int
737-
createdAt DateTime? @default(now()) @db.Timestamp
751+
createdAt DateTime? @default(dbgenerated("CURRENT_TIMESTAMP")) @db.Timestamp
738752
updatedAt DateTime @updatedAt @db.Timestamp
739753
Fallback Evoai? @relation(fields: [evoaiIdFallback], references: [id])
740754
evoaiIdFallback String? @db.VarChar(100)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
-- CreateTable
2+
CREATE TABLE "public"."Kafka" (
3+
"id" TEXT NOT NULL,
4+
"enabled" BOOLEAN NOT NULL DEFAULT false,
5+
"events" JSONB NOT NULL,
6+
"createdAt" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
7+
"updatedAt" TIMESTAMP NOT NULL,
8+
"instanceId" TEXT NOT NULL,
9+
10+
CONSTRAINT "Kafka_pkey" PRIMARY KEY ("id")
11+
);
12+
13+
-- CreateIndex
14+
CREATE UNIQUE INDEX "Kafka_instanceId_key" ON "public"."Kafka"("instanceId");
15+
16+
-- AddForeignKey
17+
ALTER TABLE "public"."Kafka" ADD CONSTRAINT "Kafka_instanceId_fkey" FOREIGN KEY ("instanceId") REFERENCES "public"."Instance"("id") ON DELETE CASCADE ON UPDATE CASCADE;

prisma/postgresql-schema.prisma

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ model Instance {
8888
Rabbitmq Rabbitmq?
8989
Nats Nats?
9090
Sqs Sqs?
91+
Kafka Kafka?
9192
Websocket Websocket?
9293
Typebot Typebot[]
9394
Session Session?
@@ -312,6 +313,16 @@ model Sqs {
312313
instanceId String @unique
313314
}
314315

316+
model Kafka {
317+
id String @id @default(cuid())
318+
enabled Boolean @default(false) @db.Boolean
319+
events Json @db.JsonB
320+
createdAt DateTime? @default(now()) @db.Timestamp
321+
updatedAt DateTime @updatedAt @db.Timestamp
322+
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
323+
instanceId String @unique
324+
}
325+
315326
model Websocket {
316327
id String @id @default(cuid())
317328
enabled Boolean @default(false) @db.Boolean

prisma/psql_bouncer-schema.prisma

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ model Instance {
8989
Rabbitmq Rabbitmq?
9090
Nats Nats?
9191
Sqs Sqs?
92+
Kafka Kafka?
9293
Websocket Websocket?
9394
Typebot Typebot[]
9495
Session Session?
@@ -313,6 +314,16 @@ model Sqs {
313314
instanceId String @unique
314315
}
315316

317+
model Kafka {
318+
id String @id @default(cuid())
319+
enabled Boolean @default(false) @db.Boolean
320+
events Json @db.JsonB
321+
createdAt DateTime? @default(now()) @db.Timestamp
322+
updatedAt DateTime @updatedAt @db.Timestamp
323+
Instance Instance @relation(fields: [instanceId], references: [id], onDelete: Cascade)
324+
instanceId String @unique
325+
}
326+
316327
model Websocket {
317328
id String @id @default(cuid())
318329
enabled Boolean @default(false) @db.Boolean

src/api/integrations/event/event.dto.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ export class EventDto {
4040
useTLS?: boolean;
4141
events?: string[];
4242
};
43+
44+
kafka?: {
45+
enabled?: boolean;
46+
events?: string[];
47+
};
4348
}
4449

4550
export function EventInstanceMixin<TBase extends Constructor>(Base: TBase) {
@@ -82,5 +87,10 @@ export function EventInstanceMixin<TBase extends Constructor>(Base: TBase) {
8287
useTLS?: boolean;
8388
events?: string[];
8489
};
90+
91+
kafka?: {
92+
enabled?: boolean;
93+
events?: string[];
94+
};
8595
};
8696
}

0 commit comments

Comments
 (0)