@cdp-forge/plugin-pipeline-sdk 1.1.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 (51) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +352 -0
  3. package/config/config.yml +7 -0
  4. package/config/plugin.yml +4 -0
  5. package/dist/ConfigListener.d.ts +11 -0
  6. package/dist/ConfigListener.d.ts.map +1 -0
  7. package/dist/ConfigListener.js +32 -0
  8. package/dist/ConfigListener.js.map +1 -0
  9. package/dist/ConfigReader.d.ts +6 -0
  10. package/dist/ConfigReader.d.ts.map +1 -0
  11. package/dist/ConfigReader.js +51 -0
  12. package/dist/ConfigReader.js.map +1 -0
  13. package/dist/PipelineStage.d.ts +19 -0
  14. package/dist/PipelineStage.d.ts.map +1 -0
  15. package/dist/PipelineStage.js +68 -0
  16. package/dist/PipelineStage.js.map +1 -0
  17. package/dist/config/config.yml +7 -0
  18. package/dist/config/plugin.yml +4 -0
  19. package/dist/config.d.ts +8 -0
  20. package/dist/config.d.ts.map +1 -0
  21. package/dist/config.js +66 -0
  22. package/dist/config.js.map +1 -0
  23. package/dist/gTopics.d.ts +472 -0
  24. package/dist/gTopics.d.ts.map +1 -0
  25. package/dist/gTopics.js +476 -0
  26. package/dist/gTopics.js.map +1 -0
  27. package/dist/index.d.ts +7 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +30 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/plugin/PipelinePluginI.d.ts +6 -0
  32. package/dist/plugin/PipelinePluginI.d.ts.map +1 -0
  33. package/dist/plugin/PipelinePluginI.js +3 -0
  34. package/dist/plugin/PipelinePluginI.js.map +1 -0
  35. package/dist/plugin/Plugin.d.ts +7 -0
  36. package/dist/plugin/Plugin.d.ts.map +1 -0
  37. package/dist/plugin/Plugin.js +12 -0
  38. package/dist/plugin/Plugin.js.map +1 -0
  39. package/dist/server.d.ts +2 -0
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +38 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/startServer.d.ts +9 -0
  44. package/dist/startServer.d.ts.map +1 -0
  45. package/dist/startServer.js +41 -0
  46. package/dist/startServer.js.map +1 -0
  47. package/dist/types.d.ts +79 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +3 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +53 -0
package/README.md ADDED
@@ -0,0 +1,352 @@
1
+ # CDP Forge Plugin Pipeline SDK
2
+
3
+ SDK for easily implementing pipeline plugins for the CDP Forge platform.
4
+
5
+ This project serves as an SDK for building plugins that can be integrated into the data processing pipeline of the CDP Forge platform. It is designed to simplify the development of custom data transformation and processing logic within the platform ecosystem.
6
+
7
+ ## 📦 Installation as NPM Library
8
+
9
+ You can install this library as a dependency in other projects:
10
+
11
+ ```bash
12
+ npm install plugin-pipeline-sdk
13
+ ```
14
+
15
+ ### Usage as Library
16
+
17
+ ```typescript
18
+ import {
19
+ PipelinePluginI,
20
+ PipelineStage,
21
+ ConfigListener,
22
+ ConfigReader,
23
+ Log,
24
+ start
25
+ } from 'plugin-pipeline-sdk';
26
+
27
+ // Create a custom plugin
28
+ class MyCustomPlugin implements PipelinePluginI {
29
+ async elaborate(log: Log): Promise<Log | null> {
30
+ // Implement your processing logic
31
+ console.log('Processing log:', log);
32
+ return log;
33
+ }
34
+
35
+ async init(): Promise<void> {
36
+ console.log('Plugin initialization');
37
+ }
38
+ }
39
+
40
+ // Load configuration
41
+ const config = ConfigReader.getInstance('./config/config.yml', './config/plugin.yml').config;
42
+
43
+ // Create plugin instance and start the server
44
+ const customPlugin = new MyCustomPlugin();
45
+ start(customPlugin, config).then(({ stage, configListener }) => {
46
+ console.log('Server started successfully');
47
+ }).catch(error => {
48
+ console.error('Error during startup:', error);
49
+ });
50
+ ```
51
+
52
+ ## 🚀 Features
53
+
54
+ - **Pipeline Plugin:** Provides a structure for creating plugins that fit into a sequential or parallel processing pipeline
55
+ - **Kafka Integration:** Uses Kafka for asynchronous communication and data streaming between pipeline stages
56
+ - **TypeScript:** Written in TypeScript to improve code maintainability, type safety, and developer productivity
57
+ - **Docker Support:** Includes Docker configuration for deployment
58
+ - **Testing:** Jest configuration for unit tests
59
+ - **Configuration Management:** Automatic merging of cluster and plugin configurations
60
+
61
+ ## 📋 Prerequisites
62
+
63
+ - Node.js 20.11.1 or higher
64
+ - npm or yarn
65
+ - Docker (optional, for deployment)
66
+ - Access to a Kafka cluster
67
+
68
+ ## 🛠️ Installation
69
+
70
+ 1. **Clone the repository:**
71
+ ```bash
72
+ git clone <repository-url>
73
+ cd plugin-pipeline-template
74
+ ```
75
+
76
+ 2. **Install dependencies:**
77
+ ```bash
78
+ npm install
79
+ ```
80
+
81
+ 3. **Configure the environment:**
82
+ - Copy and modify configuration files in `config/`
83
+ - Ensure Kafka brokers are accessible
84
+
85
+ ## ⚙️ Configuration
86
+
87
+ The SDK uses two separate configuration files to manage different aspects of the plugin system:
88
+
89
+ ### Configuration File Structure
90
+
91
+ #### `config/config.yml` - Cluster Configuration
92
+ This file contains the **cluster-level configuration** that is **shared across all plugins** in the CDP Forge platform.
93
+ ```yaml
94
+ kafkaConfig:
95
+ brokers:
96
+ - 'localhost:36715'
97
+
98
+ manager:
99
+ url: 'https://plugin_template_url'
100
+ config_topic: 'config'
101
+
102
+ mysql:
103
+ uri: 'mysql://user:password@my-server-ip:3306'
104
+ ```
105
+
106
+ **Important**: If you're using the **Helm installer** provided by the CDP Forge platform, this file is **automatically generated** and you don't need to modify it manually.
107
+
108
+ #### `config/plugin.yml` - Plugin-Specific Configuration
109
+ This file contains **plugin-specific settings** that define how your individual plugin behaves within the pipeline.
110
+
111
+ ```yaml
112
+ plugin:
113
+ name: 'myPlugin'
114
+ priority: 1 # 1 to 100 (not required if parallel)
115
+ type: 'blocking' # or 'parallel'
116
+
117
+ [any other useful string for the plugin]
118
+ ```
119
+
120
+ ### Field Descriptions
121
+
122
+ #### Cluster Configuration (`config.yml`)
123
+ - **`kafkaConfig.brokers`**
124
+ List of Kafka broker addresses to which the plugin will connect. This is configured at the cluster level and shared by all plugins.
125
+
126
+ - **`manager.url`**
127
+ URL used to register or communicate with the plugin manager service.
128
+
129
+ - **`manager.config_topic`**
130
+ Kafka topic used for plugin configuration management across the cluster.
131
+
132
+ - **`mysql.uri`**
133
+ MySQL connection string for database operations.
134
+
135
+ #### Plugin Configuration (`plugin.yml`)
136
+ - **`plugin.name`**
137
+ Unique identifier for your plugin instance within the pipeline.
138
+
139
+ - **`plugin.priority`**
140
+ (Required only for `blocking` plugins)
141
+ An integer from **1 to 100** that defines the execution order of the plugin within the pipeline. A lower number means higher priority, so the plugin with priority 1 will be executed before plugins with priority 2,3,4...
142
+
143
+ - **`plugin.type`**
144
+ Defines the plugin execution mode:
145
+ - `blocking`: The plugin processes data and returns a `Promise<Log>` for the next stage.
146
+ - `parallel`: The plugin runs independently and returns a `Promise<void>`.
147
+
148
+ ### Configuration Management
149
+
150
+ - **Cluster Config (`config.yml`)**: Managed by the platform, automatically generated by Helm installer
151
+ - **Plugin Config (`plugin.yml`)**: Managed by you, defines your plugin's behavior
152
+ - **Environment Variables**: Can override both configurations if needed
153
+ - **Runtime Updates**: Plugin configuration can be updated without restarting the cluster
154
+
155
+ ### Using ConfigReader for Convenience
156
+
157
+ The SDK provides a `ConfigReader` utility that automatically merges both configuration files into a single `config` object, making it easier to access all settings in your plugin code.
158
+
159
+ ```typescript
160
+ import { ConfigReader } from 'plugin-pipeline-sdk';
161
+
162
+ // The ConfigReader automatically loads and merges:
163
+ // - config/config.yml (cluster configuration)
164
+ // - config/plugin.yml (plugin configuration)
165
+ const config = ConfigReader.getInstance('./config/config.yml', './config/plugin.yml').config;
166
+
167
+ // Access cluster configuration
168
+ console.log(config.kafkaConfig.brokers);
169
+ console.log(config.manager.url);
170
+
171
+ // Access plugin configuration
172
+ console.log(config.plugin.name);
173
+ console.log(config.plugin.priority);
174
+
175
+ // Access merged configuration
176
+ console.log(config.mysql.uri);
177
+ ```
178
+
179
+ ### Starting the Server with Configuration
180
+
181
+ The `start()` function requires the merged configuration to initialize the server:
182
+
183
+ ```typescript
184
+ import { start, PipelinePluginI, Log, ConfigReader } from 'plugin-pipeline-sdk';
185
+
186
+ const config = ConfigReader.getInstance('./config/config.yml', './config/plugin.yml').config;
187
+
188
+ class MyPlugin implements PipelinePluginI {
189
+ async elaborate(log: Log): Promise<Log | null> {
190
+ // Your plugin logic here
191
+ return log;
192
+ }
193
+
194
+ async init(): Promise<void> {
195
+ // Plugin initialization
196
+ }
197
+ }
198
+
199
+ // Start the server with the merged configuration
200
+ start(new MyPlugin(), config).then(({ stage, configListener }) => {
201
+ console.log('Server started with merged configuration');
202
+ }).catch(error => {
203
+ console.error('Error starting server:', error);
204
+ });
205
+ ```
206
+
207
+ The server will:
208
+ 1. **Load** both configuration files using the specified paths
209
+ 2. **Merge** them into a single config object
210
+ 3. **Validate** the configuration
211
+ 4. **Start** the plugin with the merged settings
212
+
213
+ ## 🔧 Plugin Development
214
+
215
+ To create a new plugin, follow these steps:
216
+
217
+ 1. **Configure the `config.yml` and `plugin.yml` files correctly**
218
+ 2. **Implement the `elaborate` function in your plugin class**
219
+
220
+ ### Plugin Implementation
221
+
222
+ The plugin must implement the `PipelinePluginI` interface:
223
+
224
+ ```typescript
225
+ import { PipelinePluginI, Log } from 'plugin-pipeline-sdk';
226
+
227
+ export default class MyPlugin implements PipelinePluginI {
228
+ elaborate(log: Log): Promise<Log | null> {
229
+ // Implement your processing logic here
230
+ // For blocking plugins: return Promise<Log>
231
+ // For parallel plugins: return Promise<void>
232
+ return Promise.resolve(log);
233
+ }
234
+
235
+ init(): Promise<void> {
236
+ // Plugin initialization
237
+ return Promise.resolve();
238
+ }
239
+ }
240
+ ```
241
+
242
+ ### Plugin Types
243
+
244
+ Depending on the plugin type:
245
+ - **`blocking` plugins**: The `elaborate` function must return a `Promise<Log>`.
246
+ - **`parallel` plugins**: The `elaborate` function must return a `Promise<void>`.
247
+
248
+ ## 📁 Project Structure
249
+
250
+ ```
251
+ plugin-pipeline-template/
252
+ ├── config/ # Configuration files
253
+ │ ├── config.yml # Cluster configuration
254
+ │ └── plugin.yml # Plugin-specific configuration
255
+ ├── src/ # TypeScript source code
256
+ │ ├── plugin/ # Plugin implementation
257
+ │ │ ├── Plugin.ts # Main plugin class
258
+ │ │ └── PipelinePluginI.ts # Plugin interface
259
+ │ ├── types.ts # Type definitions
260
+ │ ├── config.ts # Configuration management
261
+ │ ├── index.ts # Library entry point
262
+ │ └── ... # Other utility files
263
+ ├── __tests__/ # Unit tests
264
+ ├── Dockerfile # Docker configuration
265
+ ├── package.json # Dependencies and scripts
266
+ └── tsconfig.json # TypeScript configuration
267
+ ```
268
+
269
+ ## 🚀 Available Scripts
270
+
271
+ - **`npm run build`**: Compiles TypeScript code
272
+ - **`npm test`**: Runs unit tests
273
+ - **`npm run clean`**: Cleans the dist folder
274
+ - **`npm run prepublishOnly`**: Builds before publishing
275
+
276
+ ## 🐳 Docker Deployment
277
+
278
+ 1. **Build the image:**
279
+ ```bash
280
+ docker build -t plugin-pipeline-sdk .
281
+ ```
282
+
283
+ 2. **Run the container:**
284
+ ```bash
285
+ docker run -p 3000:3000 plugin-pipeline-sdk
286
+ ```
287
+
288
+ ## 📊 Data Structure
289
+
290
+ The plugin processes `Log` objects that contain:
291
+
292
+ ```typescript
293
+ interface Log {
294
+ client: number;
295
+ date: string;
296
+ device: {
297
+ browser?: string;
298
+ id: string;
299
+ ip?: string;
300
+ os?: string;
301
+ type?: string;
302
+ userAgent?: string;
303
+ };
304
+ event: string;
305
+ geo?: {
306
+ city?: string;
307
+ country?: string;
308
+ point?: {
309
+ type: string;
310
+ coordinates: number[];
311
+ };
312
+ region?: string;
313
+ };
314
+ googleTopics?: GoogleTopic[];
315
+ instance: number;
316
+ page: {
317
+ description?: string;
318
+ href?: string;
319
+ image?: string;
320
+ title: string;
321
+ type?: string;
322
+ };
323
+ product?: Product[];
324
+ referrer?: string;
325
+ session: string;
326
+ target?: string;
327
+ order?: string;
328
+ [key: string]: any; // Allows additional properties
329
+ }
330
+ ```
331
+
332
+ ## 📦 Publishing to NPM
333
+
334
+ To publish this library to npm, see the [Publishing Guide](PUBLISHING.md).
335
+
336
+ ## 🤝 Contributing
337
+
338
+ Contributions are welcome! To contribute:
339
+
340
+ 1. Fork the repository
341
+ 2. Create a feature branch (`git checkout -b feature/AmazingFeature`)
342
+ 3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
343
+ 4. Push to the branch (`git push origin feature/AmazingFeature`)
344
+ 5. Open a Pull Request
345
+
346
+ ## 📄 License
347
+
348
+ This project is distributed under the GPL-3.0 license. See the `LICENSE` file for more details.
349
+
350
+ ## 📞 Support
351
+
352
+ For support and questions, please open an issue on the GitHub repository.
@@ -0,0 +1,7 @@
1
+ # This file is generated by the helm package and should be mounted on the plugin container
2
+ kafkaConfig:
3
+ brokers:
4
+ - 'localhost:36715'
5
+ config_topic: 'config'
6
+
7
+ pluginManagerUrl: 'https://plugin_template_url'
@@ -0,0 +1,4 @@
1
+ plugin:
2
+ name: 'myPlugin'
3
+ priority: 1 # 1 to 100 (no need if parallel)
4
+ type: 'blocking' # or 'parallel'
@@ -0,0 +1,11 @@
1
+ import PipelineSTage from "./PipelineStage";
2
+ import { Config } from "@cdp-forge/types";
3
+ export default class ConfigListener {
4
+ private kafka;
5
+ private consumer;
6
+ private stage;
7
+ private config;
8
+ constructor(stage: PipelineSTage, config: Config);
9
+ start(): Promise<void>;
10
+ }
11
+ //# sourceMappingURL=ConfigListener.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigListener.d.ts","sourceRoot":"","sources":["../src/ConfigListener.ts"],"names":[],"mappings":"AACA,OAAO,aAAa,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAiB,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAIzD,MAAM,CAAC,OAAO,OAAO,cAAc;IAC/B,OAAO,CAAC,KAAK,CAAQ;IACrB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAgB;IAC7B,OAAO,CAAC,MAAM,CAAS;gBAEX,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM;IAW1C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAe/B"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const kafkajs_1 = require("kafkajs");
4
+ const podName = process.env.CLIENT_ID || Math.random().toString(36).substring(2, 10);
5
+ class ConfigListener {
6
+ constructor(stage, config) {
7
+ this.config = config;
8
+ this.kafka = new kafkajs_1.Kafka({
9
+ clientId: config.plugin.name + `plugin-${podName}`,
10
+ brokers: config.kafkaConfig.brokers,
11
+ });
12
+ this.consumer = this.kafka.consumer({ groupId: config.plugin.name + `plugin-${podName}` });
13
+ this.stage = stage;
14
+ }
15
+ async start() {
16
+ await this.consumer.connect();
17
+ await this.consumer.subscribe({ topic: this.config.manager.config_topic, fromBeginning: false });
18
+ await this.consumer.run({
19
+ autoCommit: false,
20
+ eachMessage: async ({ topic, partition, message }) => {
21
+ const configs = message.value ? JSON.parse(message.value.toString()) : null;
22
+ const config = configs.find(config => config.plugin === this.config.plugin.name);
23
+ if (config) {
24
+ await this.stage.restart(config.inputTopic, config.outputTopic);
25
+ }
26
+ await this.consumer.commitOffsets([{ topic, partition, offset: (BigInt(message.offset) + 1n).toString() }]);
27
+ }
28
+ });
29
+ }
30
+ }
31
+ exports.default = ConfigListener;
32
+ //# sourceMappingURL=ConfigListener.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigListener.js","sourceRoot":"","sources":["../src/ConfigListener.ts"],"names":[],"mappings":";;AAAA,qCAA8D;AAI9D,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAErF,MAAqB,cAAc;IAM/B,YAAY,KAAoB,EAAE,MAAc;QAC5C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,KAAK,GAAG,IAAI,eAAK,CAAC;YACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,UAAU,OAAO,EAAE;YAClD,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,OAAO;SACpC,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,UAAU,OAAO,EAAE,EAAC,CAAC,CAAC;QAE5F,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,KAAK;QACP,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QAC9B,MAAM,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QACjG,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;YACpB,UAAU,EAAE,KAAK;YACjB,WAAW,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAuB,EAAE,EAAE;gBACtE,MAAM,OAAO,GAAoB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAC7F,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACjF,IAAG,MAAM,EAAE,CAAC;oBACR,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;gBACpE,CAAC;gBACD,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;YAChH,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AAhCD,iCAgCC"}
@@ -0,0 +1,6 @@
1
+ import { Config } from '@cdp-forge/types';
2
+ export default class ConfigReader {
3
+ static config: Config;
4
+ static generate(configPath: string, pluginPath: string): Config;
5
+ }
6
+ //# sourceMappingURL=ConfigReader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigReader.d.ts","sourceRoot":"","sources":["../src/ConfigReader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,CAAC,OAAO,OAAO,YAAY;IAC/B,OAAc,MAAM,EAAE,MAAM,CAAC;WAEf,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;CAOvE"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ const yaml_1 = __importDefault(require("yaml"));
40
+ const fs = __importStar(require("fs"));
41
+ class ConfigReader {
42
+ static generate(configPath, pluginPath) {
43
+ ConfigReader.config = {
44
+ ...yaml_1.default.parse(fs.readFileSync(configPath, 'utf8')),
45
+ ...yaml_1.default.parse(fs.readFileSync(pluginPath, 'utf8'))
46
+ };
47
+ return ConfigReader.config;
48
+ }
49
+ }
50
+ exports.default = ConfigReader;
51
+ //# sourceMappingURL=ConfigReader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigReader.js","sourceRoot":"","sources":["../src/ConfigReader.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAwB;AACxB,uCAAyB;AAGzB,MAAqB,YAAY;IAGxB,MAAM,CAAC,QAAQ,CAAC,UAAkB,EAAE,UAAkB;QAC3D,YAAY,CAAC,MAAM,GAAG;YACpB,GAAG,cAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAClD,GAAG,cAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;SACnD,CAAC;QACF,OAAO,YAAY,CAAC,MAAM,CAAC;IAC7B,CAAC;CACF;AAVD,+BAUC"}
@@ -0,0 +1,19 @@
1
+ import { Kafka, Producer, Consumer } from "kafkajs";
2
+ import PipelinePluginI from "./plugin/PipelinePluginI";
3
+ import { Config } from "@cdp-forge/types";
4
+ export default class PipelineSTage {
5
+ plugin: PipelinePluginI;
6
+ consumer: Consumer;
7
+ producer: Producer;
8
+ kafka: Kafka;
9
+ input: string | null;
10
+ output: string | null;
11
+ currentOperation: Promise<void>;
12
+ constructor(plugin: PipelinePluginI, config: Config);
13
+ start(inputTopic: string, outputTopic?: string | null): Promise<void>;
14
+ private _start;
15
+ stop(): Promise<void>;
16
+ private _stop;
17
+ restart(inputTopic: string, outputTopic: string | null): Promise<void>;
18
+ }
19
+ //# sourceMappingURL=PipelineStage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineStage.d.ts","sourceRoot":"","sources":["../src/PipelineStage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAsB,MAAM,SAAS,CAAC;AACxE,OAAO,eAAe,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAO,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI/C,MAAM,CAAC,OAAO,OAAO,aAAa;IAC9B,MAAM,EAAE,eAAe,CAAC;IACxB,QAAQ,EAAE,QAAQ,CAAC;IACnB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;gBAEpB,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM;IAa7C,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,GAAE,MAAM,GAAG,IAAW,GAAG,OAAO,CAAC,IAAI,CAAC;YASnE,MAAM;IA4Bd,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAMb,KAAK;IAKb,OAAO,CAAC,UAAU,EAAE,MAAM,EAAC,WAAW,EAAE,MAAM,GAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;CAI5E"}
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const kafkajs_1 = require("kafkajs");
4
+ const podName = process.env.CLIENT_ID || 'default-client-id';
5
+ class PipelineSTage {
6
+ constructor(plugin, config) {
7
+ this.plugin = plugin;
8
+ this.kafka = new kafkajs_1.Kafka({
9
+ clientId: config.plugin.name + `plugin-${podName}`,
10
+ brokers: config.kafkaConfig.brokers,
11
+ });
12
+ this.consumer = this.kafka.consumer({ groupId: config.plugin.name + `plugin` });
13
+ this.producer = this.kafka.producer();
14
+ this.input = null;
15
+ this.output = null;
16
+ this.currentOperation = Promise.resolve();
17
+ }
18
+ async start(inputTopic, outputTopic = null) {
19
+ this.input = inputTopic;
20
+ this.output = outputTopic;
21
+ this.currentOperation = this.currentOperation.then(() => this.plugin.init());
22
+ await this.currentOperation;
23
+ this.currentOperation = this._start();
24
+ return this.currentOperation;
25
+ }
26
+ async _start() {
27
+ if (this.output)
28
+ await this.producer.connect();
29
+ await this.consumer.connect();
30
+ await this.consumer.subscribe({ topic: this.input, fromBeginning: false });
31
+ await this.consumer.run({
32
+ autoCommit: false,
33
+ eachMessage: async ({ topic, partition, message }) => {
34
+ const log = message.value ? JSON.parse(message.value.toString()) : null;
35
+ if (!log)
36
+ return;
37
+ const elaboratedLog = await this.plugin.elaborate(log);
38
+ if (!elaboratedLog) {
39
+ console.warn('Messaggio non elaborato');
40
+ await this.consumer.commitOffsets([{ topic, partition, offset: (BigInt(message.offset) + 1n).toString() }]);
41
+ return;
42
+ }
43
+ if (this.output) {
44
+ await this.producer.send({
45
+ topic: this.output,
46
+ messages: [{ value: JSON.stringify(elaboratedLog) }],
47
+ });
48
+ await this.consumer.commitOffsets([{ topic, partition, offset: (BigInt(message.offset) + 1n).toString() }]);
49
+ }
50
+ },
51
+ });
52
+ }
53
+ async stop() {
54
+ await this.currentOperation;
55
+ this.currentOperation = this._stop();
56
+ return this.currentOperation;
57
+ }
58
+ async _stop() {
59
+ await this.consumer.disconnect();
60
+ await this.producer.disconnect();
61
+ }
62
+ async restart(inputTopic, outputTopic) {
63
+ await this.stop();
64
+ await this.start(inputTopic, outputTopic);
65
+ }
66
+ }
67
+ exports.default = PipelineSTage;
68
+ //# sourceMappingURL=PipelineStage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PipelineStage.js","sourceRoot":"","sources":["../src/PipelineStage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ # This file is generated by the helm package and should be mounted on the plugin container
2
+ kafkaConfig:
3
+ brokers:
4
+ - 'localhost:36715'
5
+ config_topic: 'config'
6
+
7
+ pluginManagerUrl: 'https://plugin_template_url'
@@ -0,0 +1,4 @@
1
+ plugin:
2
+ name: 'myPlugin'
3
+ priority: 1 # 1 to 100 (no need if parallel)
4
+ type: 'blocking' # or 'parallel'
@@ -0,0 +1,8 @@
1
+ export default class Config {
2
+ private static instance;
3
+ private readonly configData;
4
+ private constructor();
5
+ static getInstance(): Config;
6
+ get config(): any;
7
+ }
8
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,OAAO,OAAO,MAAM;IACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAM;IAEjC,OAAO;WAYO,WAAW,IAAI,MAAM;IAOnC,IAAW,MAAM,IAAI,GAAG,CAEvB;CACF"}